From 973edc96860fd46d74214f26644d64c496cf7606 Mon Sep 17 00:00:00 2001
From: zorkow <volker.sorge@gmail.com>
Date: Mon, 17 Aug 2015 19:50:14 +0100
Subject: [PATCH 1/3] Adds level of subclassing for clickable menu items.

---
 unpacked/extensions/MathMenu.js | 61 ++++++++++++++++++++++++---------
 1 file changed, 45 insertions(+), 16 deletions(-)

diff --git a/unpacked/extensions/MathMenu.js b/unpacked/extensions/MathMenu.js
index 08b32b2c6..d602e388a 100644
--- a/unpacked/extensions/MathMenu.js
+++ b/unpacked/extensions/MathMenu.js
@@ -408,22 +408,23 @@
 
   /*************************************************************/
   /*
-   *  The menu item root subclass
+   *  Abstract class of menu items.
    */
   var ITEM = MENU.ITEM = MathJax.Object.Subclass({
     name: "", // the menu item's label as [id,label] pair
+    node: null,
 
+    Attributes: function() {
+      return {onmouseup: MENU.Mouseup,
+              ondragstart: FALSE, onselectstart: FALSE, onselectend: FALSE,
+              ontouchstart: MENU.Touchstart, ontouchend: MENU.Touchend,
+              className: "MathJax_MenuItem", menuItem: this};
+    },    
     Create: function (menu) {
       if (!this.hidden) {
-        var def = {
-          onmouseover: MENU.Mouseover, onmouseout: MENU.Mouseout,
-          onmouseup: MENU.Mouseup, onmousedown: MENU.Mousedown,
-          ondragstart: FALSE, onselectstart: FALSE, onselectend: FALSE,
-          ontouchstart: MENU.Touchstart, ontouchend: MENU.Touchend,
-          className: "MathJax_MenuItem", menuItem: this
-        };
-        if (this.disabled) {def.className += " MathJax_MenuDisabled"}
-        HTML.addElement(menu,"div",def,this.Label(def,menu));
+        var def = this.Attributes();
+        var label = this.Label(def,menu);
+        this.node = HTML.addElement(menu, "div", def, label);
       }
     },
     Name: function () {return _(this.name[0],this.name[1])},
@@ -479,11 +480,31 @@
     rtlClass: function () {return (this.isRTL() ? " RTL" : "")}
   });
 
+  /*************************************************************/
+  /*
+   *  Abstract class of menu items that are focusable and perform some action
+   */
+  MENU.ENTRY = MENU.ITEM.Subclass({
+
+    Attributes: function() {
+      var def = this.SUPER(arguments).Attributes.apply(this,arguments);
+      def.onmouseover =  MENU.Mouseover;
+      def.onmouseout = MENU.Mouseout;
+      def.onmousedown = MENU.Mousedown;
+      def.role = "menuitem";
+      if (this.disabled) {
+        def.className += " MathJax_MenuDisabled";
+        def["aria-disabled"] = true;
+      }
+      return def;
+    },
+  });
+  
   /*************************************************************/
   /*
    *  A menu item that performs a command when selected
    */
-  MENU.ITEM.COMMAND = MENU.ITEM.Subclass({
+  MENU.ITEM.COMMAND = MENU.ENTRY.Subclass({
     action: function () {},
 
     Init: function (name,action,def) {
@@ -507,7 +528,7 @@
   /*
    *  A menu item that posts a submenu
    */
-  MENU.ITEM.SUBMENU = MENU.ITEM.Subclass({
+  MENU.ITEM.SUBMENU = MENU.ENTRY.Subclass({
     menu: null,        // the submenu
     marker: "\u25BA",  // the submenu arrow
     markerRTL: "\u25C4", // the submenu arrow for RTL
@@ -560,10 +581,15 @@
   /*
    *  A menu item that is one of several radio buttons
    */
-  MENU.ITEM.RADIO = MENU.ITEM.Subclass({
+  MENU.ITEM.RADIO = MENU.ENTRY.Subclass({
     variable: null,     // the variable name
     marker: (isPC ? "\u25CF" : "\u2713"),   // the checkmark
 
+    Attributes: function() {
+      var def = this.SUPER(arguments).Attributes.apply(this,arguments);
+      def.role = "menuitemradio";
+      return def;
+    },
     Init: function (name,variable,def) {
       if (!(name instanceof Array)) {name = [name,name]}  // make [id,label] pair
       this.name = name; this.variable = variable; this.With(def);
@@ -597,10 +623,15 @@
   /*
    *  A menu item that is checkable
    */
-  MENU.ITEM.CHECKBOX = MENU.ITEM.Subclass({
+  MENU.ITEM.CHECKBOX = MENU.ENTRY.Subclass({
     variable: null,     // the variable name
     marker: "\u2713",   // the checkmark
 
+    Attributes: function() {
+      var def = this.SUPER(arguments).Attributes.apply(this,arguments);
+      def.role = "menuitemcheckbox";
+      return def;
+    },
     Init: function (name,variable,def) {
       if (!(name instanceof Array)) {name = [name,name]}  // make [id,label] pair
       this.name = name; this.variable = variable; this.With(def);
@@ -633,7 +664,6 @@
       this.name = name; this.With(def);
     },
     Label: function (def,menu) {
-      delete def.onmouseover, delete def.onmouseout; delete def.onmousedown;
       def.className += " MathJax_MenuLabel";
       return [this.Name()];
     }
@@ -645,7 +675,6 @@
    */
   MENU.ITEM.RULE = MENU.ITEM.Subclass({
     Label: function (def,menu) {
-      delete def.onmouseover, delete def.onmouseout; delete def.onmousedown;
       def.className += " MathJax_MenuRule";
       return null;
     }

From c6b98d45cc6cb297e1430576bf75aa85f357a973 Mon Sep 17 00:00:00 2001
From: zorkow <volker.sorge@gmail.com>
Date: Tue, 18 Aug 2015 18:01:57 +0100
Subject: [PATCH 2/3] Injects abstract class for clickable items.

---
 unpacked/extensions/MathMenu.js | 44 +++++++++++++++++++--------------
 1 file changed, 25 insertions(+), 19 deletions(-)

diff --git a/unpacked/extensions/MathMenu.js b/unpacked/extensions/MathMenu.js
index d602e388a..4e2bd453f 100644
--- a/unpacked/extensions/MathMenu.js
+++ b/unpacked/extensions/MathMenu.js
@@ -414,6 +414,19 @@
     name: "", // the menu item's label as [id,label] pair
     node: null,
 
+    /*
+     *  Accessor method for node.
+     */
+    GetNode: function() {
+      return this.node;
+    },
+    /*
+     *  Registers the HTML node of the menu item.
+     */
+    SetNode: function(node) {
+      this.node = node;
+    },
+
     Attributes: function() {
       return {onmouseup: MENU.Mouseup,
               ondragstart: FALSE, onselectstart: FALSE, onselectend: FALSE,
@@ -424,7 +437,8 @@
       if (!this.hidden) {
         var def = this.Attributes();
         var label = this.Label(def,menu);
-        this.node = HTML.addElement(menu, "div", def, label);
+        var node = HTML.addElement(menu, "div", def, label);
+        this.SetNode(node);
       }
     },
     Name: function () {return _(this.name[0],this.name[1])},
@@ -486,18 +500,18 @@
    */
   MENU.ENTRY = MENU.ITEM.Subclass({
 
+    role: "menuitem",  // Aria role.
+    
     Attributes: function() {
       var def = this.SUPER(arguments).Attributes.apply(this,arguments);
-      def.onmouseover =  MENU.Mouseover;
-      def.onmouseout = MENU.Mouseout;
-      def.onmousedown = MENU.Mousedown;
-      def.role = "menuitem";
       if (this.disabled) {
         def.className += " MathJax_MenuDisabled";
-        def["aria-disabled"] = true;
       }
-      return def;
-    },
+      var augdef = {onmouseover: MENU.Mouseover, onmouseout: MENU.Mouseout,
+                    onmousedown: MENU.Mousedown, role: this.role,
+                    'aria-disabled': !!this.disabled};
+      return MathJax.Hub.Insert(def, augdef);
+    }
   });
   
   /*************************************************************/
@@ -584,12 +598,8 @@
   MENU.ITEM.RADIO = MENU.ENTRY.Subclass({
     variable: null,     // the variable name
     marker: (isPC ? "\u25CF" : "\u2713"),   // the checkmark
-
-    Attributes: function() {
-      var def = this.SUPER(arguments).Attributes.apply(this,arguments);
-      def.role = "menuitemradio";
-      return def;
-    },
+    role: "menuitemradio",
+    
     Init: function (name,variable,def) {
       if (!(name instanceof Array)) {name = [name,name]}  // make [id,label] pair
       this.name = name; this.variable = variable; this.With(def);
@@ -626,12 +636,8 @@
   MENU.ITEM.CHECKBOX = MENU.ENTRY.Subclass({
     variable: null,     // the variable name
     marker: "\u2713",   // the checkmark
+    role: "menuitemcheckbox",
 
-    Attributes: function() {
-      var def = this.SUPER(arguments).Attributes.apply(this,arguments);
-      def.role = "menuitemcheckbox";
-      return def;
-    },
     Init: function (name,variable,def) {
       if (!(name instanceof Array)) {name = [name,name]}  // make [id,label] pair
       this.name = name; this.variable = variable; this.With(def);

From 2c028aee2269d8c66c453e9bbfa27573eba49eb0 Mon Sep 17 00:00:00 2001
From: zorkow <volker.sorge@gmail.com>
Date: Tue, 18 Aug 2015 22:51:59 +0100
Subject: [PATCH 3/3] Incorporates review suggestions.

---
 unpacked/extensions/MathMenu.js | 25 ++++++++++++++-----------
 1 file changed, 14 insertions(+), 11 deletions(-)

diff --git a/unpacked/extensions/MathMenu.js b/unpacked/extensions/MathMenu.js
index 4e2bd453f..a0a25e718 100644
--- a/unpacked/extensions/MathMenu.js
+++ b/unpacked/extensions/MathMenu.js
@@ -427,12 +427,14 @@
       this.node = node;
     },
 
-    Attributes: function() {
-      return {onmouseup: MENU.Mouseup,
-              ondragstart: FALSE, onselectstart: FALSE, onselectend: FALSE,
-              ontouchstart: MENU.Touchstart, ontouchend: MENU.Touchend,
-              className: "MathJax_MenuItem", menuItem: this};
-    },    
+    Attributes: function(def) {
+      return HUB.Insert(
+        {onmouseup: MENU.Mouseup,
+         ondragstart: FALSE, onselectstart: FALSE, onselectend: FALSE,
+         ontouchstart: MENU.Touchstart, ontouchend: MENU.Touchend,
+         className: "MathJax_MenuItem", menuItem: this},
+        def);
+    },
     Create: function (menu) {
       if (!this.hidden) {
         var def = this.Attributes();
@@ -503,14 +505,15 @@
     role: "menuitem",  // Aria role.
     
     Attributes: function() {
-      var def = this.SUPER(arguments).Attributes.apply(this,arguments);
+      var def = this.SUPER(arguments).Attributes.call(
+        this,
+        {onmouseover: MENU.Mouseover, onmouseout: MENU.Mouseout,
+         onmousedown: MENU.Mousedown, role: this.role,
+         'aria-disabled': !!this.disabled});
       if (this.disabled) {
         def.className += " MathJax_MenuDisabled";
       }
-      var augdef = {onmouseover: MENU.Mouseover, onmouseout: MENU.Mouseout,
-                    onmousedown: MENU.Mousedown, role: this.role,
-                    'aria-disabled': !!this.disabled};
-      return MathJax.Hub.Insert(def, augdef);
+      return def;
     }
   });