From f3273f6e6297a8f6ad72f432236c695636bcb39b Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Thu, 23 Jul 2015 11:33:07 -0400 Subject: [PATCH 01/66] First draft of assistive MathML extension. Still needs configuration, and we need to make sure the mml2jax exteion doesn't try to process the hidden MathML. --- unpacked/extensions/AssistiveMML.js | 109 ++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 unpacked/extensions/AssistiveMML.js diff --git a/unpacked/extensions/AssistiveMML.js b/unpacked/extensions/AssistiveMML.js new file mode 100644 index 000000000..299844018 --- /dev/null +++ b/unpacked/extensions/AssistiveMML.js @@ -0,0 +1,109 @@ +/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ + +/************************************************************* + * + * MathJax/extensions/AssistiveMML.js + * + * Implements an extension that inserts hidden MathML into the + * page for screen readers or other asistive technology. + * + * --------------------------------------------------------------------- + * + * Copyright (c) 2015 The MathJax Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +(function (AJAX,CALLBACK,HUB,HTML) { + + var AssistiveMML = MathJax.Extension["AssistiveMML"] = { + version: "2.6", + + // + // For each jax in the state, look up the frame. + // If the jax doesn't use NativeMML and hasn't already been handled: + // Get the MathML for the jax, taking resets into account. + // Add a data-mathml attribute to the frame, and + // Create a span that is not visible on screen and put the MathML in it, + // and add it to the frame. + // When all the jax are processed, call the callback. + // + HandleMML: function (state) { + var m = state.jax.length, jax, mml, frame, span; + while (state.i < m) { + jax = state.jax[state.i]; + frame = document.getElementById(jax.inputID+"-Frame"); + if (jax.outputJax !== "NativeMML" && frame && !frame.getAttribute("data-mathml")) { + try { + mml = jax.root.toMathML("").replace(/\n */g,"").replace(//g,""); + } catch (err) { + if (!err.restart) throw err; // an actual error + return MathJax.Callback.After(["HandleMML",this,state],err.restart); + } + frame.setAttribute("data-mathml",mml); + span = HTML.Element("span",{ + isMathJax: true, + style:{ + position:"absolute!important", + left:"-100000px", top:"auto", height:"1px", width:"1px", + "padding-top":"1px", display:"block" + } + }); + span.innerHTML = mml; + frame.appendChild(span); + } + state.i++; + } + state.callback(); + }, + + // + // The hook for the End Math signal. + // This sets up a state object that lists the jax and index into the jax, + // and a dummy callback that is used to synchronizing with MathJax. + // It will be called when the jax are all processed, and that will + // let the MathJax queue continue (it will block until then). + // + EndMathHook: function (node) { + var state = { + jax: HUB.getAllJax(node), i: 0, + callback: MathJax.Callback(function () { + console.log("MathML time: "+((new Date().getTime())-state.start)); + }), + start: new Date().getTime() + }; + this.HandleMML(state); + return state.callback; + } + + }; + + // + // Call the hook when math has been processed. + // + HUB.Register.MessageHook("End Math",function (msg) {AssistiveMML.EndMathHook(msg[1])}); + + HUB.Startup.signal.Post("AssistiveMML Ready"); + +})(MathJax.Ajax,MathJax.Callback,MathJax.Hub,MathJax.HTML); + +// +// Make sure the toMathML extension is loaded before we signal +// the load complete for this extension. +// +MathJax.Callback.Queue( + ["Require",MathJax.Ajax,"[MathJax]/extensions/toMathML.js"], + ["loadComplete",MathJax.Ajax,"[MathJax]/extensions/AssistiveMML.js"] +); + From d8357a2d03546576a368a25a9d860e1e796b1cfe Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Thu, 23 Jul 2015 15:14:02 -0400 Subject: [PATCH 02/66] Change CSS to that recommended by the Yahoo Accessibility team at https://developer.yahoo.com/blogs/ydn/clip-hidden-content-better-accessibility-53456.html --- unpacked/extensions/AssistiveMML.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/unpacked/extensions/AssistiveMML.js b/unpacked/extensions/AssistiveMML.js index 299844018..f668e553a 100644 --- a/unpacked/extensions/AssistiveMML.js +++ b/unpacked/extensions/AssistiveMML.js @@ -55,9 +55,15 @@ span = HTML.Element("span",{ isMathJax: true, style:{ - position:"absolute!important", - left:"-100000px", top:"auto", height:"1px", width:"1px", - "padding-top":"1px", display:"block" + position:"absolute", + clip: (HUB.Browser.isMSIE && (document.documentMode||0) < 8 ? + "rect(1px 1px 1px 1px)" : "rect(1px, 1px, 1px, 1px)"), + padding: "1 0 0 0", + border: "0", + height: "1px", + width: "1px", + overflow: "hidden", + display:"block" } }); span.innerHTML = mml; From f0cc437b1e61d05c6c46d6b64a2a947c815272bf Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Thu, 23 Jul 2015 16:40:18 -0400 Subject: [PATCH 03/66] Refactor code to make a separate configuration section with dynamically generated stylesheet. Use a class for the added MathML rather than explicit CSS. --- unpacked/extensions/AssistiveMML.js | 97 ++++++++++++++++------------- 1 file changed, 55 insertions(+), 42 deletions(-) diff --git a/unpacked/extensions/AssistiveMML.js b/unpacked/extensions/AssistiveMML.js index f668e553a..59513e8f2 100644 --- a/unpacked/extensions/AssistiveMML.js +++ b/unpacked/extensions/AssistiveMML.js @@ -26,9 +26,54 @@ */ (function (AJAX,CALLBACK,HUB,HTML) { - + var SETTINGS = HUB.config.menuSettings; + var AssistiveMML = MathJax.Extension["AssistiveMML"] = { version: "2.6", + + config: { + disabled: false, + styles: { + ".MJX_Assistive_MathML": { + position:"absolute!important", + clip: (HUB.Browser.isMSIE && (document.documentMode||0) < 8 ? + "rect(1px 1px 1px 1px)" : "rect(1px, 1px, 1px, 1px)"), + padding: "1px 0 0 0!important", + border: "0!important", + height: "1px!important", + width: "1px!important", + overflow: "hidden!important", + display:"block!important" + } + } + }, + + Config: function () { + if (!this.config.disabled && SETTINGS.assistiveMML == null) + HUB.Config({menuSettings:{assistiveMML:true}}); + AJAX.Styles(this.config.styles); + HUB.Register.MessageHook("End Math",function (msg) {AssistiveMML.EndMathHook(msg[1])}); + }, + + // + // The hook for the End Math signal. + // This sets up a state object that lists the jax and index into the jax, + // and a dummy callback that is used to synchronizing with MathJax. + // It will be called when the jax are all processed, and that will + // let the MathJax queue continue (it will block until then). + // + EndMathHook: function (node) { + if (!SETTINGS.assistiveMML) return; + var state = { + jax: HUB.getAllJax(node), i: 0, + callback: MathJax.Callback(function () { + console.log("MathML time: "+((new Date().getTime())-state.start)); + }), + start: new Date().getTime() + }; + this.HandleMML(state); + return state.callback; + }, // // For each jax in the state, look up the frame. @@ -52,64 +97,32 @@ return MathJax.Callback.After(["HandleMML",this,state],err.restart); } frame.setAttribute("data-mathml",mml); - span = HTML.Element("span",{ - isMathJax: true, - style:{ - position:"absolute", - clip: (HUB.Browser.isMSIE && (document.documentMode||0) < 8 ? - "rect(1px 1px 1px 1px)" : "rect(1px, 1px, 1px, 1px)"), - padding: "1 0 0 0", - border: "0", - height: "1px", - width: "1px", - overflow: "hidden", - display:"block" - } - }); + span = HTML.addElement(frame,"span",{ + isMathJax: true, className: "MJX_Assistive_MathML" + }); span.innerHTML = mml; - frame.appendChild(span); } state.i++; } state.callback(); - }, - - // - // The hook for the End Math signal. - // This sets up a state object that lists the jax and index into the jax, - // and a dummy callback that is used to synchronizing with MathJax. - // It will be called when the jax are all processed, and that will - // let the MathJax queue continue (it will block until then). - // - EndMathHook: function (node) { - var state = { - jax: HUB.getAllJax(node), i: 0, - callback: MathJax.Callback(function () { - console.log("MathML time: "+((new Date().getTime())-state.start)); - }), - start: new Date().getTime() - }; - this.HandleMML(state); - return state.callback; } }; - // - // Call the hook when math has been processed. - // - HUB.Register.MessageHook("End Math",function (msg) {AssistiveMML.EndMathHook(msg[1])}); - HUB.Startup.signal.Post("AssistiveMML Ready"); })(MathJax.Ajax,MathJax.Callback,MathJax.Hub,MathJax.HTML); // // Make sure the toMathML extension is loaded before we signal -// the load complete for this extension. +// the load complete for this extension. Then wait for the end +// of the user configuration before configuring this extension. // MathJax.Callback.Queue( ["Require",MathJax.Ajax,"[MathJax]/extensions/toMathML.js"], - ["loadComplete",MathJax.Ajax,"[MathJax]/extensions/AssistiveMML.js"] + ["loadComplete",MathJax.Ajax,"[MathJax]/extensions/AssistiveMML.js"], + function () { + MathJax.Hub.Register.StartupHook("End Config",["Config",MathJax.Extension.AssistiveMML]); + } ); From 82e0daf2c6c369aaa55a85fa646be427c18fbe89 Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Thu, 23 Jul 2015 17:09:43 -0400 Subject: [PATCH 04/66] Add a hidden menu item that controls the AssistiveMML extension. --- unpacked/extensions/MathMenu.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/unpacked/extensions/MathMenu.js b/unpacked/extensions/MathMenu.js index 08b32b2c6..2c910a29d 100644 --- a/unpacked/extensions/MathMenu.js +++ b/unpacked/extensions/MathMenu.js @@ -1115,7 +1115,8 @@ ITEM.RADIO("MathML", "renderer", {action: MENU.Renderer, value:"NativeMML"}), ITEM.RADIO("SVG", "renderer", {action: MENU.Renderer}), ITEM.RULE(), - ITEM.CHECKBOX("Fast Preview", "CHTMLpreview") + ITEM.CHECKBOX("Fast Preview", "CHTMLpreview"), + ITEM.CHECKBOX("Assistive MathML", "assistiveMML", {hidden:!CONFIG.showAssistiveMML}) ), ITEM.SUBMENU("MathPlayer", {hidden:!HUB.Browser.isMSIE || !CONFIG.showMathPlayer, disabled:!HUB.Browser.hasMathPlayer}, @@ -1202,6 +1203,10 @@ MENU.cookie.showLocale = CONFIG.showLocale = show; MENU.saveCookie(); MENU.menu.Find("Language").hidden = !show; }; + MENU.showAssistiveMML = function (show) { + MENU.cookie.showAssistiveMML = CONFIG.showAssistiveMML = show; MENU.saveCookie(); + MENU.menu.Find("Math Settings","Math Renderer","Assistive MathML").hidden = !show; + }; MathJax.Hub.Register.StartupHook("HTML-CSS Jax Ready",function () { if (!MathJax.OutputJax["HTML-CSS"].config.imageFont) From 1dff53daa8447c5f4f250879e614ca531c34c51a Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Fri, 24 Jul 2015 07:19:27 -0400 Subject: [PATCH 05/66] Make sure mml2jax doesn't process the assistive MathML. --- unpacked/extensions/mml2jax.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/unpacked/extensions/mml2jax.js b/unpacked/extensions/mml2jax.js index a348bc55e..8edb8d5c1 100644 --- a/unpacked/extensions/mml2jax.js +++ b/unpacked/extensions/mml2jax.js @@ -99,8 +99,8 @@ MathJax.Extension.mml2jax = { } for (var i = 0, m = math.length; i < m; i++) { var parent = math[i].parentNode; - if (parent && parent.className !== preview && !math[i].prefix === !namespace) - {array.push(math[i])} + if (parent && parent.className !== preview && + !parent.isMathJax && !math[i].prefix === !namespace) array.push(math[i]); } }, From 8d38947024039a2833eaa155a47d8cbc8ed3a8c3 Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Fri, 24 Jul 2015 07:20:10 -0400 Subject: [PATCH 06/66] Add aria attributes for the normal and assistive output. --- unpacked/extensions/AssistiveMML.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/unpacked/extensions/AssistiveMML.js b/unpacked/extensions/AssistiveMML.js index 59513e8f2..ca89fd072 100644 --- a/unpacked/extensions/AssistiveMML.js +++ b/unpacked/extensions/AssistiveMML.js @@ -101,6 +101,8 @@ isMathJax: true, className: "MJX_Assistive_MathML" }); span.innerHTML = mml; + frame.firstChild.setAttribute("aria-hidden","true"); + span.setAttribute("aria-readonly","true"); } state.i++; } From 4149a87a962c08d7b636c65ae541927622caad7b Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Fri, 24 Jul 2015 09:25:11 -0400 Subject: [PATCH 07/66] Autoload AssisitveMML if the menu item is set and the extension isn't loaded. --- unpacked/MathJax.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/unpacked/MathJax.js b/unpacked/MathJax.js index 01d5b81d9..8c181f416 100644 --- a/unpacked/MathJax.js +++ b/unpacked/MathJax.js @@ -2554,6 +2554,8 @@ MathJax.Hub.Startup = { } if (config.menuSettings.CHTMLpreview && !MathJax.Extension["CHTML-preview"]) {MathJax.Hub.config.extensions.push("CHTML-preview.js")} + if (config.menuSettings.assistiveMML && !MathJax.Extension.AssistiveMML) + {MathJax.Hub.config.extensions.push("AssistiveMML.js")} },MathJax.Hub.config], ["Post",this.signal,"End Cookie"] ); From 7c68c1cb1c073c4b8605ce14b53ba57391b65455 Mon Sep 17 00:00:00 2001 From: zorkow Date: Tue, 18 Aug 2015 22:01:27 +0100 Subject: [PATCH 08/66] WIP --- unpacked/extensions/MathEvents.js | 19 ++- unpacked/extensions/MathMenu.js | 214 ++++++++++++++++++++++++---- unpacked/jax/output/HTML-CSS/jax.js | 5 +- 3 files changed, 205 insertions(+), 33 deletions(-) diff --git a/unpacked/extensions/MathEvents.js b/unpacked/extensions/MathEvents.js index 49853e69b..ba63f0e15 100644 --- a/unpacked/extensions/MathEvents.js +++ b/unpacked/extensions/MathEvents.js @@ -142,7 +142,20 @@ } return false; }, - + + // + // Keydown event handler. Should only fire on Space key. + // + // TODO: (sorge) Fit this into the Handler function. + // + Keydown: function (event, math) { + var jax = OUTPUT[this.jaxID]; + if (event.keyCode === 32) { + // TODO: Put the focus on the first element. + EVENT.ContextMenu(event, this); + }; + }, + // // Load the contextual menu code, if needed, and post the menu // @@ -178,7 +191,7 @@ load = LOCALE.loadDomain("MathMenu"); if (!load) { MENU.jax = jax; - var source = MENU.menu.Find("Show Math As").menu; + var source = MENU.menu.Find("Show Math As").submenu; source.items[0].name = jax.sourceMenuTitle; source.items[0].format = (jax.sourceMenuFormat||"MathML"); source.items[1].name = INPUT[jax.inputJax].sourceMenuTitle; @@ -189,7 +202,7 @@ // items accordingly. // var annotations = source.items[2]; annotations.disabled = true; - var annotationItems = annotations.menu.items; + var annotationItems = annotations.submenu.items; annotationList = MathJax.Hub.Config.semanticsAnnotations; for (var i = 0, m = annotationItems.length; i < m; i++) { var name = annotationItems[i].name[1] diff --git a/unpacked/extensions/MathMenu.js b/unpacked/extensions/MathMenu.js index 4e2bd453f..329bd6abe 100644 --- a/unpacked/extensions/MathMenu.js +++ b/unpacked/extensions/MathMenu.js @@ -29,7 +29,7 @@ (function (HUB,HTML,AJAX,CALLBACK,OUTPUT) { var VERSION = "2.5.0"; - var SIGNAL = MathJax.Callback.Signal("menu") // signal for menu events + var SIGNAL = MathJax.Callback.Signal("menu"); // signal for menu events MathJax.Extension.MathMenu = { version: VERSION, @@ -234,7 +234,7 @@ var menu = HTML.Element("div",{ onmouseup: MENU.Mouseup, ondblclick: FALSE, ondragstart: FALSE, onselectstart: FALSE, oncontextmenu: FALSE, - menuItem: this, className: "MathJax_Menu" + menuItem: this, className: "MathJax_Menu", onkeydown: MENU.Keydown }); if (!forceLTR) {MathJax.Localization.setCSS(menu)} @@ -248,7 +248,6 @@ div.appendChild(menu); this.posted = true; - menu.style.width = (menu.offsetWidth+2) + "px"; var x = event.pageX, y = event.pageY; if (!x && !y) { @@ -284,6 +283,7 @@ menu.style.left = x+"px"; menu.style.top = y+"px"; if (document.selection && document.selection.empty) {document.selection.empty()} + MENU.Focus(event, menu); return FALSE(event); }, @@ -301,6 +301,7 @@ delete MENU.jax.hover.nofade; HOVER.UnHover(MENU.jax); } + MENU.Unfocus(); return FALSE(event); }, @@ -314,8 +315,8 @@ for (var i = 0, m = this.items.length; i < m; i++) { if (this.items[i].name[n] === name) { if (names.length) { - if (!this.items[i].menu) {return null} - return this.items[i].menu.FindN(n,names[0],names.slice(1)); + if (!this.items[i].submenu) {return null} + return this.items[i].submenu.FindN(n,names[0],names.slice(1)); } return this.items[i]; } @@ -332,23 +333,74 @@ for (var i = 0, m = this.items.length; i < m; i++) {if (this.items[i].name[n] === name) {return i}} return null; - } + }, + /* + * Moving in the list of items. + */ + Up: function(item) { + var index = this.items.indexOf(item); + if (index === -1) { + return; + } + do { + index--; + if (index < 0) { + index = this.items.length - 1; + } + } while (!this.items[index].GetNode().role); + MENU.UnfocusItem(item); + MENU.FocusItem(this.items[index]); + }, + Down: function(item) { + var index = this.items.indexOf(item); + if (index === -1) { + return; + } + do { + index++; + if (index >= this.items.length) { + index = 0; + } + } while (!this.items[index].GetNode().role); + MENU.UnfocusItem(item); + MENU.FocusItem(this.items[index]); + } + },{ config: CONFIG, div: null, // the DOM elements for the menu and submenus - Close: function (event) - {return MENU.Event(event,this.menu||this.parentNode,(this.menu?"Touchend":"Remove"))}, + /*************************************************************/ + /* + * Enum element for key codes. + */ + KEY: { + RETURN: 13, + ESCAPE: 27, + SPACE: 32, + LEFT: 37, + UP: 38, + RIGHT: 39, + DOWN: 40 + }, + Remove: function (event) {return MENU.Event(event,this,"Remove")}, Mouseover: function (event) {return MENU.Event(event,this,"Mouseover")}, Mouseout: function (event) {return MENU.Event(event,this,"Mouseout")}, Mousedown: function (event) {return MENU.Event(event,this,"Mousedown")}, Mouseup: function (event) {return MENU.Event(event,this,"Mouseup")}, + Keydown: function (event) {return MENU.Event(event,this,"Keydown")}, + /* + * Events for mobile devices. + */ Touchstart: function (event) {return MENU.Event(event,this,"Touchstart")}, Touchend: function (event) {return MENU.Event(event,this,"Touchend")}, + Close: function (event) { + return MENU.Event(event,this.menu||this.parentNode,(this.menu?"Touchend":"Remove")); + }, Event: function (event,menu,type,force) { if (MENU.skipMouseover && type === "Mouseover" && !force) {return FALSE(event)} if (MENU.skipUp) { @@ -361,7 +413,6 @@ if (item && item[type]) {return item[type](event,menu)} return null; }, - /* * Style for the background DIV */ @@ -400,7 +451,57 @@ bg.style.height = document.body.scrollHeight + "px"; } }, + + + /*************************************************************/ + /* + * Keyboard navigation of menu. + */ + jaxs: [], + hasJaxs: false, + oldJax: null, + + GetJaxs: function() { + // input.id + adding frame to get the elements. + var nodes = document.getElementsByClassName('MathJax'); + for (var i = 0, node; node = nodes[i]; i++) { + MENU.jaxs.push(node); + } + }, + Focus: function(event, menu) { + console.log('focusing...'); + if (!MENU.hasJaxs) { + MENU.GetJaxs(); + } + MENU.oldJax = event.srcElement; + for (var j = 0, jax; jax = MENU.jaxs[j]; j++) { + jax.tabIndex = -1; + } + MENU.FocusItem(MENU.menu.items[0]); + console.log('end focusing...'); + }, + FocusItem: function(item) { + console.log('Focusing on item'); + console.log(item); + var node = item.GetNode(); + node.tabIndex = 0; + item.Activate(node); + node.focus(); + }, + Unfocus: function() { + for (var j = 0, jax; jax = MENU.jaxs[j]; j++) { + jax.tabIndex = 0; + } + MENU.oldJax.focus(); + MENU.oldJax = null; + }, + UnfocusItem: function(item) { + var node = item.GetNode(); + node.tabIndex = -1; + item.Deactivate(node); + }, + saveCookie: function () {HTML.Cookie.Set("menu",this.cookie)}, getCookie: function () {this.cookie = HTML.Cookie.Get("menu")} @@ -411,9 +512,11 @@ * Abstract class of menu items. */ var ITEM = MENU.ITEM = MathJax.Object.Subclass({ - name: "", // the menu item's label as [id,label] pair - node: null, + name: "", // The menu item's label as [id,label] pair. + node: null, // The HTML node of the item. + menu: null, // The parent menu containing that item. + /* * Accessor method for node. */ @@ -426,7 +529,6 @@ SetNode: function(node) { this.node = node; }, - Attributes: function() { return {onmouseup: MENU.Mouseup, ondragstart: FALSE, onselectstart: FALSE, onselectend: FALSE, @@ -439,21 +541,27 @@ var label = this.Label(def,menu); var node = HTML.addElement(menu, "div", def, label); this.SetNode(node); + this.menu = menu; } }, Name: function () {return _(this.name[0],this.name[1])}, Mouseover: function (event,menu) { if (!this.disabled) {this.Activate(menu)} - if (!this.menu || !this.menu.posted) { + if (!this.submenu || !this.submenu.posted) { + console.log('This is not a submenu method!'); var menus = document.getElementById("MathJax_MenuFrame").childNodes, - items = menu.parentNode.childNodes; + items = this.menu.childNodes; for (var i = 0, m = items.length; i < m; i++) { var item = items[i].menuItem; - if (item && item.menu && item.menu.posted) {item.Deactivate(items[i])} + // Deactivates submenu items. + if (item && item.submenu && item.submenu.posted) { + item.Deactivate(items[i]); + } } + // Removes all submenus. m = menus.length-1; - while (m >= 0 && menu.parentNode.menuItem !== menus[m].menuItem) { + while (m >= 0 && this.menu.menuItem !== menus[m].menuItem) { menus[m].menuItem.posted = false; menus[m].parentNode.removeChild(menus[m]); m--; @@ -462,7 +570,7 @@ } }, Mouseout: function (event,menu) { - if (!this.menu || !this.menu.posted) {this.Deactivate(menu)} + if (!this.submenu || !this.submenu.posted) {this.Deactivate(menu)} if (this.timer) {clearTimeout(this.timer); delete this.timer} }, Mouseup: function (event,menu) {return this.Remove(event,menu)}, @@ -485,7 +593,10 @@ return menu.Remove(event,menu); }, - Activate: function (menu) {this.Deactivate(menu); menu.className += " MathJax_MenuActive"}, + Activate: function (menu) { + this.Deactivate(menu); + menu.className += " MathJax_MenuActive"; + }, Deactivate: function (menu) {menu.className = menu.className.replace(/ MathJax_MenuActive/,"")}, With: function (def) {if (def) {HUB.Insert(this,def)}; return this}, @@ -509,8 +620,30 @@ } var augdef = {onmouseover: MENU.Mouseover, onmouseout: MENU.Mouseout, onmousedown: MENU.Mousedown, role: this.role, + onkeydown: MENU.Keydown, tabIndex: -1, 'aria-disabled': !!this.disabled}; return MathJax.Hub.Insert(def, augdef); + }, + Keydown: function(event, menu) { + console.log('MENUEntry'); + switch (event.keyCode) { + case MENU.KEY.ESCAPE: + this.Remove(event, menu); + break; + case MENU.KEY.UP: + menu.parentNode.menuItem.Up(menu.menuItem); + break; + case MENU.KEY.DOWN: + menu.parentNode.menuItem.Down(menu.menuItem); + break; + default: + break; + } + return FALSE(event); + }, + Remove: function(event, menu) { + MENU.UnfocusItem(this); + this.SUPER(arguments).Remove.apply(this, arguments); } }); @@ -536,6 +669,13 @@ } return FALSE(event); } + // Keydown: function(event, menu) { + // console.log('here'); + // if (event.keyCode === MENU.KEY.ESCAPE) { + // this.Remove(event, menu); + // } + // return FALSE(event); + // } }); /*************************************************************/ @@ -543,7 +683,7 @@ * A menu item that posts a submenu */ MENU.ITEM.SUBMENU = MENU.ENTRY.Subclass({ - menu: null, // the submenu + submenu: null, // the submenu marker: "\u25BA", // the submenu arrow markerRTL: "\u25C4", // the submenu arrow for RTL @@ -551,10 +691,10 @@ if (!(name instanceof Array)) {name = [name,name]} // make [id,label] pair this.name = name; var i = 1; if (!(def instanceof MENU.ITEM)) {this.With(def), i++} - this.menu = MENU.apply(MENU,[].slice.call(arguments,i)); + this.submenu = MENU.apply(MENU,[].slice.call(arguments,i)); }, Label: function (def,menu) { - this.menu.posted = false; + this.submenu.posted = false; return [this.Name()+" ",["span",{ className:"MathJax_MenuArrow" + this.rtlClass() },[this.isRTL() ? this.markerRTL : this.marker]]]; @@ -565,16 +705,16 @@ this.timer = setTimeout(CALLBACK(["Mouseup",this,event,menu]),CONFIG.delay); }, Touchend: function (event,menu) { - var forceout = this.menu.posted; + var forceout = this.submenu.posted; var result = this.SUPER(arguments).Touchend.apply(this,arguments); if (forceout) {this.Deactivate(menu); delete ITEM.lastItem; delete ITEM.lastMenu} return result; }, Mouseup: function (event,menu) { if (!this.disabled) { - if (!this.menu.posted) { + if (!this.submenu.posted) { if (this.timer) {clearTimeout(this.timer); delete this.timer} - this.menu.Post(event,menu,this.ltr); + this.submenu.Post(event,menu,this.ltr); } else { var menus = document.getElementById("MathJax_MenuFrame").childNodes, m = menus.length-1; @@ -582,13 +722,31 @@ var child = menus[m]; child.menuItem.posted = false; child.parentNode.removeChild(child); - if (child.menuItem === this.menu) {break}; + if (child.menuItem === this.submenu) {break}; m--; } } } return FALSE(event); + }, + Keydown: function(event, menu) { + console.log('MENUSubmenu'); + switch (event.keyCode) { + case MENU.KEY.RIGHT: + case MENU.KEY.SPACE: + if (!this.submenu.posted) { + this.submenu.Post(event,menu,this.ltr); + } + break; + case MENU.KEY.LEFT: + menu.parentNode.menuItem.Down(menu.menuItem); + break; + default: + break; + } + return this.SUPER(arguments).Keydown.apply(this, arguments); } + }); /*************************************************************/ @@ -1056,7 +1214,7 @@ // MENU.CreateLocaleMenu = function () { if (!MENU.menu) return; - var menu = MENU.menu.Find("Language").menu, items = menu.items; + var menu = MENU.menu.Find("Language").submenu, items = menu.items; // // Get the names of the languages and sort them // @@ -1082,7 +1240,7 @@ // MENU.CreateAnnotationMenu = function () { if (!MENU.menu) return; - var menu = MENU.menu.Find("Show Math As","Annotation").menu; + var menu = MENU.menu.Find("Show Math As","Annotation").submenu; var annotations = CONFIG.semanticsAnnotations; for (var a in annotations) { if (annotations.hasOwnProperty(a)) { @@ -1197,7 +1355,7 @@ if (MENU.isMobile) { (function () { var settings = CONFIG.settings; - var trigger = MENU.menu.Find("Math Settings","Zoom Trigger").menu; + var trigger = MENU.menu.Find("Math Settings","Zoom Trigger").submenu; trigger.items[0].disabled = trigger.items[1].disabled = true; if (settings.zoom === "Hover" || settings.zoom == "Click") {settings.zoom = "None"} trigger.items = trigger.items.slice(0,4); diff --git a/unpacked/jax/output/HTML-CSS/jax.js b/unpacked/jax/output/HTML-CSS/jax.js index 1a99295d4..79b915d90 100644 --- a/unpacked/jax/output/HTML-CSS/jax.js +++ b/unpacked/jax/output/HTML-CSS/jax.js @@ -569,8 +569,9 @@ span = div = this.Element("span",{ className:"MathJax", id:jax.inputID+"-Frame", isMathJax:true, jaxID:this.id, oncontextmenu:EVENT.Menu, onmousedown: EVENT.Mousedown, - onmouseover:EVENT.Mouseover, onmouseout:EVENT.Mouseout, onmousemove:EVENT.Mousemove, - onclick:EVENT.Click, ondblclick:EVENT.DblClick + onmouseover:EVENT.Mouseover, onmouseout:EVENT.Mouseout, + onmousemove:EVENT.Mousemove, onclick:EVENT.Click, + ondblclick:EVENT.DblClick, onkeydown: EVENT.Keydown, tabIndex: "0" }); if (HUB.Browser.noContextMenu) { span.ontouchstart = TOUCH.start; From 1be417af3a98edd42e2bc89432e08a2d733dfb08 Mon Sep 17 00:00:00 2001 From: zorkow Date: Fri, 21 Aug 2015 04:34:18 +0100 Subject: [PATCH 09/66] Combined keyboard and mouse navigation works. --- unpacked/extensions/MathEvents.js | 16 +- unpacked/extensions/MathMenu.js | 369 +++++++++++++++++++----------- 2 files changed, 246 insertions(+), 139 deletions(-) diff --git a/unpacked/extensions/MathEvents.js b/unpacked/extensions/MathEvents.js index ba63f0e15..016622f17 100644 --- a/unpacked/extensions/MathEvents.js +++ b/unpacked/extensions/MathEvents.js @@ -109,6 +109,20 @@ RIGHTBUTTON: 2, // the event.button value for right button MENUKEY: "altKey", // the event value for alternate context menu + /*************************************************************/ + /* + * Enum element for key codes. + */ + KEY: { + RETURN: 13, + ESCAPE: 27, + SPACE: 32, + LEFT: 37, + UP: 38, + RIGHT: 39, + DOWN: 40 + }, + Mousedown: function (event) {return EVENT.Handler(event,"Mousedown",this)}, Mouseup: function (event) {return EVENT.Handler(event,"Mouseup",this)}, Mousemove: function (event) {return EVENT.Handler(event,"Mousemove",this)}, @@ -150,7 +164,7 @@ // Keydown: function (event, math) { var jax = OUTPUT[this.jaxID]; - if (event.keyCode === 32) { + if (event.keyCode === EVENT.KEY.SPACE) { // TODO: Put the focus on the first element. EVENT.ContextMenu(event, this); }; diff --git a/unpacked/extensions/MathMenu.js b/unpacked/extensions/MathMenu.js index d535722c9..6393d7942 100644 --- a/unpacked/extensions/MathMenu.js +++ b/unpacked/extensions/MathMenu.js @@ -198,10 +198,11 @@ } }); - var FALSE, HOVER; + var FALSE, HOVER, KEY; HUB.Register.StartupHook("MathEvents Ready",function () { FALSE = MathJax.Extension.MathEvents.Event.False; HOVER = MathJax.Extension.MathEvents.Hover; + KEY = MathJax.Extension.MathEvents.Event.KEY; }); /*************************************************************/ @@ -250,6 +251,12 @@ this.posted = true; menu.style.width = (menu.offsetWidth+2) + "px"; var x = event.pageX, y = event.pageY; + var node = MENU.node || event.target; + if (!x && !y && node) { + var rect = node.getBoundingClientRect(); + x = rect.right; + y = rect.bottom; + } if (!x && !y) { x = event.clientX + document.body.scrollLeft + document.documentElement.scrollLeft; y = event.clientY + document.body.scrollTop + document.documentElement.scrollTop; @@ -283,7 +290,7 @@ menu.style.left = x+"px"; menu.style.top = y+"px"; if (document.selection && document.selection.empty) {document.selection.empty()} - MENU.Focus(event, menu); + MENU.Focus(menu); return FALSE(event); }, @@ -301,7 +308,7 @@ delete MENU.jax.hover.nofade; HOVER.UnHover(MENU.jax); } - MENU.Unfocus(); + MENU.Unfocus(menu); return FALSE(event); }, @@ -338,55 +345,56 @@ /* * Moving in the list of items. */ - Up: function(item) { - var index = this.items.indexOf(item); - if (index === -1) { - return; + Keydown: function(event, menu) { + if (!this.posted) { + return FALSE(event); } - do { - index--; - if (index < 0) { - index = this.items.length - 1; - } - } while (!this.items[index].GetNode().role); - MENU.UnfocusItem(item); - MENU.FocusItem(this.items[index]); + switch (event.keyCode) { + case KEY.ESCAPE: + this.Remove(event, menu); + break; + case KEY.RIGHT: + this.Right(event, menu); + break; + case KEY.LEFT: + this.Left(event, menu); + break; + case KEY.UP: + this.Up(event, menu); + break; + case KEY.DOWN: + this.Down(event, menu); + break; + case KEY.RETURN: + case KEY.SPACE: + this.Space(event, menu); + break; + default: + break; + } + return FALSE(event); }, - Down: function(item) { - var index = this.items.indexOf(item); - if (index === -1) { - return; - } - do { - index++; - if (index >= this.items.length) { - index = 0; - } - } while (!this.items[index].GetNode().role); - MENU.UnfocusItem(item); - MENU.FocusItem(this.items[index]); - } - + Right: function(event, menu) { + MENU.Right(event, menu); + }, + Left: function(event, menu) { + MENU.Left(event, menu); + }, + Up: function(event, menu) { + var item = this.items[this.items.length - 1]; + item.Activate(item.GetNode()); + }, + Down: function(event, menu) { + var item = this.items[0]; + item.Activate(item.GetNode()); + }, + Space: function(event, menu) { } },{ config: CONFIG, div: null, // the DOM elements for the menu and submenus - /*************************************************************/ - /* - * Enum element for key codes. - */ - KEY: { - RETURN: 13, - ESCAPE: 27, - SPACE: 32, - LEFT: 37, - UP: 38, - RIGHT: 39, - DOWN: 40 - }, - Remove: function (event) {return MENU.Event(event,this,"Remove")}, Mouseover: function (event) {return MENU.Event(event,this,"Mouseover")}, Mouseout: function (event) {return MENU.Event(event,this,"Mouseout")}, @@ -457,51 +465,84 @@ /* * Keyboard navigation of menu. */ - jaxs: [], - hasJaxs: false, - oldJax: null, - + jaxs: [], // List of all MathJax nodes. + hasJaxs: false, // Flag to indicate if the MathJax node list has already + // been computed. + node: null, // The node the menu was activated on. + active: null, // The currently focused item. There can only be one! + posted: false, // Is a menu open? + GetJaxs: function() { - // input.id + adding frame to get the elements. var nodes = document.getElementsByClassName('MathJax'); for (var i = 0, node; node = nodes[i]; i++) { MENU.jaxs.push(node); } }, - Focus: function(event, menu) { - console.log('focusing...'); + // + // Focus is a global affair, since we only ever want a single focused item. + // + Focus: function(menu) { + if (!MENU.posted) { + MENU.Activate(menu); + } + if (MENU.active) { + MENU.active.tabIndex = -1; + } + MENU.active = menu; + MENU.active.tabIndex = 0; + MENU.active.focus(); + }, + Activate: function(menu) { if (!MENU.hasJaxs) { MENU.GetJaxs(); } - MENU.oldJax = event.srcElement; + if (!MENU.node) { + MENU.node = document.getElementById(MENU.jax.inputID + '-Frame'); + } for (var j = 0, jax; jax = MENU.jaxs[j]; j++) { jax.tabIndex = -1; } - MENU.FocusItem(MENU.menu.items[0]); - console.log('end focusing...'); - }, - FocusItem: function(item) { - console.log('Focusing on item'); - console.log(item); - var node = item.GetNode(); - node.tabIndex = 0; - item.Activate(node); - node.focus(); + MENU.posted = true; }, Unfocus: function() { + MENU.active.tabIndex = -1; + MENU.active = null; for (var j = 0, jax; jax = MENU.jaxs[j]; j++) { jax.tabIndex = 0; } - MENU.oldJax.focus(); - MENU.oldJax = null; + MENU.node.focus(); + MENU.node = null; + MENU.posted = false; }, - UnfocusItem: function(item) { - var node = item.GetNode(); - node.tabIndex = -1; - item.Deactivate(node); + //TODO: A toggle focus method on the top level would avoid having to + //tabIndex all the Jaxs. + Move: function(event, menu, move) { + var len = MENU.jaxs.length; + if (len === 0) { + return; + } + var next = MENU.jaxs[MENU.Mod(move(MENU.jaxs.indexOf(MENU.node)), len)]; + if (next === MENU.node) { + return; + } + MENU.menu.Remove(event, menu); + MENU.jax = MathJax.Hub.getJaxFor(next); + MENU.node = next; + MENU.menu.Post(null); + }, + Right: function(event, menu) { + MENU.Move(event, menu, function(x) {return x + 1;}); + }, + Left: function(event, menu) { + MENU.Move(event, menu, function(x) {return x - 1;}); + }, + + //TODO: Helper. To move + // Computes a mod n. + Mod: function(a, n) { + return ((a % n) + n) % n; }, - saveCookie: function () {HTML.Cookie.Set("menu",this.cookie)}, getCookie: function () {this.cookie = HTML.Cookie.Get("menu")} @@ -515,7 +556,7 @@ name: "", // The menu item's label as [id,label] pair. node: null, // The HTML node of the item. - menu: null, // The parent menu containing that item. + menu: null, // The parent menu containing that item. HTML node. /* * Accessor method for node. @@ -551,33 +592,36 @@ Name: function () {return _(this.name[0],this.name[1])}, Mouseover: function (event,menu) { - if (!this.disabled) {this.Activate(menu)} - if (!this.submenu || !this.submenu.posted) { - console.log('This is not a submenu method!'); - var menus = document.getElementById("MathJax_MenuFrame").childNodes, - items = this.menu.childNodes; - for (var i = 0, m = items.length; i < m; i++) { - var item = items[i].menuItem; - // Deactivates submenu items. - if (item && item.submenu && item.submenu.posted) { - item.Deactivate(items[i]); - } - } - // Removes all submenus. - m = menus.length-1; - while (m >= 0 && this.menu.menuItem !== menus[m].menuItem) { - menus[m].menuItem.posted = false; - menus[m].parentNode.removeChild(menus[m]); - m--; - } - if (this.Timer && !MENU.isMobile) {this.Timer(event,menu)} - } + this.Activate(menu); }, Mouseout: function (event,menu) { if (!this.submenu || !this.submenu.posted) {this.Deactivate(menu)} if (this.timer) {clearTimeout(this.timer); delete this.timer} }, Mouseup: function (event,menu) {return this.Remove(event,menu)}, + + + DeactivateSubmenus: function(menu) { + var menus = document.getElementById("MathJax_MenuFrame").childNodes, + items = this.menu.childNodes; + for (var i = 0, m = items.length; i < m; i++) { + var item = items[i].menuItem; + // Deactivates submenu items. + if (item && item.submenu && item.submenu.posted) { + item.Deactivate(items[i]); + } + } + this.RemoveSubmenus(menu, menus); + }, + RemoveSubmenus: function(menu, menus) { + menus = menus || document.getElementById("MathJax_MenuFrame").childNodes; + var m = menus.length-1; + while (m >= 0 && this.menu.menuItem !== menus[m].menuItem) { + menus[m].menuItem.posted = false; + menus[m].parentNode.removeChild(menus[m]); + m--; + } + }, Touchstart: function (event,menu) {return this.TouchEvent(event,menu,"Mousedown")}, Touchend: function (event,menu) {return this.TouchEvent(event,menu,"Mouseup")}, @@ -599,7 +643,11 @@ Activate: function (menu) { this.Deactivate(menu); - menu.className += " MathJax_MenuActive"; + if (!this.disabled) { + menu.className += " MathJax_MenuActive"; + } + this.DeactivateSubmenus(menu); + MENU.Focus(menu); }, Deactivate: function (menu) {menu.className = menu.className.replace(/ MathJax_MenuActive/,"")}, @@ -622,32 +670,79 @@ this, {onmouseover: MENU.Mouseover, onmouseout: MENU.Mouseout, onmousedown: MENU.Mousedown, role: this.role, + onkeydown: MENU.Keydown, 'aria-disabled': !!this.disabled}); if (this.disabled) { def.className += " MathJax_MenuDisabled"; } return def; - } - Keydown: function(event, menu) { - console.log('MENUEntry'); + }, + Keydown: function(event, item) { switch (event.keyCode) { - case MENU.KEY.ESCAPE: - this.Remove(event, menu); + case KEY.ESCAPE: + this.Remove(event, item); break; - case MENU.KEY.UP: - menu.parentNode.menuItem.Up(menu.menuItem); + case KEY.UP: + this.Up(event, item); break; - case MENU.KEY.DOWN: - menu.parentNode.menuItem.Down(menu.menuItem); + case KEY.DOWN: + this.Down(event, item); + break; + case KEY.RIGHT: + this.Right(event, item); + break; + case KEY.LEFT: + this.Left(event, item); + break; + case KEY.SPACE: + case KEY.RETURN: + this.Space(event, item); break; default: break; } return FALSE(event); }, - Remove: function(event, menu) { - MENU.UnfocusItem(this); - this.SUPER(arguments).Remove.apply(this, arguments); + Move: function(event, item, move) { + var items = this.menu.menuItem.items; + var len = items.length; + var index = items.indexOf(this); + if (index === -1) { + return; + } + do { + index = MENU.Mod(move(index), len); + } while (items[index].hidden || !items[index].GetNode().role); + this.Deactivate(item); + item = items[index]; + item.Activate(item.GetNode()); + }, + Up: function(event, item) { + this.Move(event, item, function(x) { return x - 1; }); + }, + Down: function(event, item) { + this.Move(event, item, function(x) { return x + 1; }); + }, + Right: function(event, item) { + if (this.menu.menuItem === MENU.menu) { + MENU.Right(event, item); + } + }, + Left: function(event, item) { + if (this.menu.menuItem === MENU.menu) { + MENU.Left(event, item); + } else { + this.Deactivate(item); + var sibling = item.parentNode.previousSibling; + var actives = sibling.getElementsByClassName('MathJax_MenuActive'); + if (actives.length > 0) { + MENU.Focus(actives[0]); + } + this.RemoveSubmenus(item); + } + }, + Space: function (event, menu) { + this.Mouseup(event, menu); } }); @@ -665,6 +760,7 @@ }, Label: function (def,menu) {return [this.Name()]}, + //TODO: Focus the popup. Mouseup: function (event,menu) { if (!this.disabled) { this.Remove(event,menu); @@ -673,13 +769,6 @@ } return FALSE(event); } - // Keydown: function(event, menu) { - // console.log('here'); - // if (event.keyCode === MENU.KEY.ESCAPE) { - // this.Remove(event, menu); - // } - // return FALSE(event); - // } }); /*************************************************************/ @@ -714,43 +803,40 @@ if (forceout) {this.Deactivate(menu); delete ITEM.lastItem; delete ITEM.lastMenu} return result; }, + Mouseover: function(event, menu) { + this.Activate(menu); + }, Mouseup: function (event,menu) { if (!this.disabled) { if (!this.submenu.posted) { if (this.timer) {clearTimeout(this.timer); delete this.timer} this.submenu.Post(event,menu,this.ltr); + MENU.Focus(menu); } else { - var menus = document.getElementById("MathJax_MenuFrame").childNodes, - m = menus.length-1; - while (m >= 0) { - var child = menus[m]; - child.menuItem.posted = false; - child.parentNode.removeChild(child); - if (child.menuItem === this.submenu) {break}; - m--; - } + this.RemoveSubmenus(menu); } } return FALSE(event); }, - Keydown: function(event, menu) { - console.log('MENUSubmenu'); - switch (event.keyCode) { - case MENU.KEY.RIGHT: - case MENU.KEY.SPACE: - if (!this.submenu.posted) { - this.submenu.Post(event,menu,this.ltr); - } - break; - case MENU.KEY.LEFT: - menu.parentNode.menuItem.Down(menu.menuItem); - break; - default: - break; + Activate: function (menu) { + if (!this.disabled) { + this.Deactivate(menu); + menu.className += " MathJax_MenuActive"; + } + if (!this.submenu.posted) { + this.DeactivateSubmenus(menu); + } + MENU.Focus(menu); + if (!MENU.isMobile) { + this.Timer(event,menu); + } + }, + Right: function(event, menu) { + if (this.submenu.items.length > 0) { + var item = this.submenu.items[0]; + item.Activate(item.GetNode()); } - return this.SUPER(arguments).Keydown.apply(this, arguments); } - }); /*************************************************************/ @@ -825,8 +911,11 @@ /*************************************************************/ /* * A menu item that is a label - */ - MENU.ITEM.LABEL = MENU.ITEM.Subclass({ + * //TODO: Turn this into a focusable! No mouse interaction! + */ + MENU.ITEM.LABEL = MENU.ENTRY.Subclass({ + role: "menuitem", // Aria role. + Init: function (name,def) { if (!(name instanceof Array)) {name = [name,name]} // make [id,label] pair this.name = name; this.With(def); @@ -834,6 +923,10 @@ Label: function (def,menu) { def.className += " MathJax_MenuLabel"; return [this.Name()]; + }, + Activate: function(menu) { + this.Deactivate(menu); + MENU.Focus(menu); } }); From 85c1801fbacb3aee8fdc850541041fcf35c83ef1 Mon Sep 17 00:00:00 2001 From: zorkow Date: Fri, 21 Aug 2015 04:59:31 +0100 Subject: [PATCH 10/66] Fixes issues with submenus. --- unpacked/extensions/MathMenu.js | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/unpacked/extensions/MathMenu.js b/unpacked/extensions/MathMenu.js index 6393d7942..35ae6e61d 100644 --- a/unpacked/extensions/MathMenu.js +++ b/unpacked/extensions/MathMenu.js @@ -595,8 +595,7 @@ this.Activate(menu); }, Mouseout: function (event,menu) { - if (!this.submenu || !this.submenu.posted) {this.Deactivate(menu)} - if (this.timer) {clearTimeout(this.timer); delete this.timer} + this.Deactivate(menu); }, Mouseup: function (event,menu) {return this.Remove(event,menu)}, @@ -793,23 +792,34 @@ },[this.isRTL() ? this.markerRTL : this.marker]]]; }, Timer: function (event,menu) { - if (this.timer) {clearTimeout(this.timer)} + this.ClearTimer(); event = {clientX: event.clientX, clientY: event.clientY}; // MSIE can't pass the event below this.timer = setTimeout(CALLBACK(["Mouseup",this,event,menu]),CONFIG.delay); }, + ClearTimer: function() { + if (this.timer) { + clearTimeout(this.timer); + } + }, Touchend: function (event,menu) { var forceout = this.submenu.posted; var result = this.SUPER(arguments).Touchend.apply(this,arguments); if (forceout) {this.Deactivate(menu); delete ITEM.lastItem; delete ITEM.lastMenu} return result; }, + Mouseout: function(event, menu) { + if (!this.submenu.posted) { + this.Deactivate(menu); + } + this.ClearTimer(); + }, Mouseover: function(event, menu) { this.Activate(menu); }, Mouseup: function (event,menu) { if (!this.disabled) { if (!this.submenu.posted) { - if (this.timer) {clearTimeout(this.timer); delete this.timer} + this.ClearTimer(); this.submenu.Post(event,menu,this.ltr); MENU.Focus(menu); } else { @@ -825,11 +835,11 @@ } if (!this.submenu.posted) { this.DeactivateSubmenus(menu); + if (!MENU.isMobile) { + this.Timer(event,menu); + } } MENU.Focus(menu); - if (!MENU.isMobile) { - this.Timer(event,menu); - } }, Right: function(event, menu) { if (this.submenu.items.length > 0) { @@ -911,7 +921,6 @@ /*************************************************************/ /* * A menu item that is a label - * //TODO: Turn this into a focusable! No mouse interaction! */ MENU.ITEM.LABEL = MENU.ENTRY.Subclass({ role: "menuitem", // Aria role. @@ -927,7 +936,8 @@ Activate: function(menu) { this.Deactivate(menu); MENU.Focus(menu); - } + }, + Mouseup: function (event,menu) { } }); /*************************************************************/ From 70da9faa9032d98d6dce3fc48ba484bca785a8a0 Mon Sep 17 00:00:00 2001 From: zorkow Date: Fri, 21 Aug 2015 05:34:13 +0100 Subject: [PATCH 11/66] Introduces abstract superclass of all keyboard navigatable objects. --- unpacked/extensions/MathMenu.js | 119 +++++++++++++++----------------- 1 file changed, 55 insertions(+), 64 deletions(-) diff --git a/unpacked/extensions/MathMenu.js b/unpacked/extensions/MathMenu.js index 35ae6e61d..793ef1ffa 100644 --- a/unpacked/extensions/MathMenu.js +++ b/unpacked/extensions/MathMenu.js @@ -204,12 +204,56 @@ HOVER = MathJax.Extension.MathEvents.Hover; KEY = MathJax.Extension.MathEvents.Event.KEY; }); + + + /*************************************************************/ + /* + * Abstract class of all keyboard navigatable objects. + */ + var NAV = MathJax.Object.Subclass({ + /* + * Moving in the list of items. + */ + Keydown: function(event, menu) { + switch (event.keyCode) { + case KEY.ESCAPE: + this.Remove(event, menu); + break; + case KEY.RIGHT: + this.Right(event, menu); + break; + case KEY.LEFT: + this.Left(event, menu); + break; + case KEY.UP: + this.Up(event, menu); + break; + case KEY.DOWN: + this.Down(event, menu); + break; + case KEY.RETURN: + case KEY.SPACE: + this.Space(event, menu); + break; + default: + break; + } + return FALSE(event); + }, + Escape: function(event, menu) { }, + Right: function(event, menu) { }, + Left: function(event, menu) { }, + Up: function(event, menu) { }, + Down: function(event, menu) { }, + Space: function(event, menu) { } + }, {}); + /*************************************************************/ /* * The main menu class */ - var MENU = MathJax.Menu = MathJax.Object.Subclass({ + var MENU = MathJax.Menu = NAV.Subclass({ version: VERSION, items: [], posted: false, @@ -342,38 +386,6 @@ return null; }, - /* - * Moving in the list of items. - */ - Keydown: function(event, menu) { - if (!this.posted) { - return FALSE(event); - } - switch (event.keyCode) { - case KEY.ESCAPE: - this.Remove(event, menu); - break; - case KEY.RIGHT: - this.Right(event, menu); - break; - case KEY.LEFT: - this.Left(event, menu); - break; - case KEY.UP: - this.Up(event, menu); - break; - case KEY.DOWN: - this.Down(event, menu); - break; - case KEY.RETURN: - case KEY.SPACE: - this.Space(event, menu); - break; - default: - break; - } - return FALSE(event); - }, Right: function(event, menu) { MENU.Right(event, menu); }, @@ -385,10 +397,10 @@ item.Activate(item.GetNode()); }, Down: function(event, menu) { + console.log('In menu'); var item = this.items[0]; item.Activate(item.GetNode()); - }, - Space: function(event, menu) { } + } },{ config: CONFIG, @@ -410,6 +422,7 @@ return MENU.Event(event,this.menu||this.parentNode,(this.menu?"Touchend":"Remove")); }, Event: function (event,menu,type,force) { + console.log(type); if (MENU.skipMouseover && type === "Mouseover" && !force) {return FALSE(event)} if (MENU.skipUp) { if (type.match(/Mouseup|Touchend/)) {delete MENU.skipUp; return FALSE(event)} @@ -418,6 +431,8 @@ } if (!event) {event = window.event} var item = menu.menuItem; + console.log(item); + console.log(item[type]); if (item && item[type]) {return item[type](event,menu)} return null; }, @@ -460,7 +475,6 @@ } }, - /*************************************************************/ /* * Keyboard navigation of menu. @@ -537,7 +551,7 @@ MENU.Move(event, menu, function(x) {return x - 1;}); }, - //TODO: Helper. To move + //TODO: Move to utility class. // Computes a mod n. Mod: function(a, n) { return ((a % n) + n) % n; @@ -548,11 +562,13 @@ }); + MathJax.Menu.NAV = NAV; + /*************************************************************/ /* * Abstract class of menu items. */ - var ITEM = MENU.ITEM = MathJax.Object.Subclass({ + var ITEM = MENU.ITEM = NAV.Subclass({ name: "", // The menu item's label as [id,label] pair. node: null, // The HTML node of the item. @@ -676,32 +692,6 @@ } return def; }, - Keydown: function(event, item) { - switch (event.keyCode) { - case KEY.ESCAPE: - this.Remove(event, item); - break; - case KEY.UP: - this.Up(event, item); - break; - case KEY.DOWN: - this.Down(event, item); - break; - case KEY.RIGHT: - this.Right(event, item); - break; - case KEY.LEFT: - this.Left(event, item); - break; - case KEY.SPACE: - case KEY.RETURN: - this.Space(event, item); - break; - default: - break; - } - return FALSE(event); - }, Move: function(event, item, move) { var items = this.menu.menuItem.items; var len = items.length; @@ -720,6 +710,7 @@ this.Move(event, item, function(x) { return x - 1; }); }, Down: function(event, item) { + console.log('?????'); this.Move(event, item, function(x) { return x + 1; }); }, Right: function(event, item) { From 66fb6c9ab445f117b9ab5023e1eb88d12e33aca1 Mon Sep 17 00:00:00 2001 From: zorkow Date: Fri, 21 Aug 2015 11:57:51 +0100 Subject: [PATCH 12/66] Fixes event problem --- unpacked/extensions/MathMenu.js | 55 ++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/unpacked/extensions/MathMenu.js b/unpacked/extensions/MathMenu.js index 793ef1ffa..c7466d7cd 100644 --- a/unpacked/extensions/MathMenu.js +++ b/unpacked/extensions/MathMenu.js @@ -294,7 +294,9 @@ div.appendChild(menu); this.posted = true; menu.style.width = (menu.offsetWidth+2) + "px"; - var x = event.pageX, y = event.pageY; + if (event) { + var x = event.pageX, y = event.pageY; + } var node = MENU.node || event.target; if (!x && !y && node) { var rect = node.getBoundingClientRect(); @@ -309,7 +311,7 @@ if (x + menu.offsetWidth > document.body.offsetWidth - this.margin) {x = document.body.offsetWidth - menu.offsetWidth - this.margin} if (MENU.isMobile) {x = Math.max(5,x-Math.floor(menu.offsetWidth/2)); y -= 20} - MENU.skipUp = event.isContextMenu; + if (event) {MENU.skipUp = event.isContextMenu;} } else { var side = "left", mw = parent.offsetWidth; x = (MENU.isMobile ? 30 : mw - 2); y = 0; @@ -394,12 +396,11 @@ }, Up: function(event, menu) { var item = this.items[this.items.length - 1]; - item.Activate(item.GetNode()); + item.Activate(event, item.GetNode()); }, Down: function(event, menu) { - console.log('In menu'); var item = this.items[0]; - item.Activate(item.GetNode()); + item.Activate(event, item.GetNode()); } },{ @@ -422,7 +423,6 @@ return MENU.Event(event,this.menu||this.parentNode,(this.menu?"Touchend":"Remove")); }, Event: function (event,menu,type,force) { - console.log(type); if (MENU.skipMouseover && type === "Mouseover" && !force) {return FALSE(event)} if (MENU.skipUp) { if (type.match(/Mouseup|Touchend/)) {delete MENU.skipUp; return FALSE(event)} @@ -431,8 +431,6 @@ } if (!event) {event = window.event} var item = menu.menuItem; - console.log(item); - console.log(item[type]); if (item && item[type]) {return item[type](event,menu)} return null; }, @@ -506,7 +504,7 @@ MENU.active.tabIndex = 0; MENU.active.focus(); }, - Activate: function(menu) { + Activate: function(event, menu) { if (!MENU.hasJaxs) { MENU.GetJaxs(); } @@ -608,7 +606,7 @@ Name: function () {return _(this.name[0],this.name[1])}, Mouseover: function (event,menu) { - this.Activate(menu); + this.Activate(event, menu); }, Mouseout: function (event,menu) { this.Deactivate(menu); @@ -656,7 +654,7 @@ return menu.Remove(event,menu); }, - Activate: function (menu) { + Activate: function (event, menu) { this.Deactivate(menu); if (!this.disabled) { menu.className += " MathJax_MenuActive"; @@ -664,7 +662,11 @@ this.DeactivateSubmenus(menu); MENU.Focus(menu); }, - Deactivate: function (menu) {menu.className = menu.className.replace(/ MathJax_MenuActive/,"")}, + Deactivate: function (menu) { + console.log(menu); + console.log(menu.className); + + menu.className = menu.className.replace(/ MathJax_MenuActive/,"")}, With: function (def) {if (def) {HUB.Insert(this,def)}; return this}, @@ -704,13 +706,12 @@ } while (items[index].hidden || !items[index].GetNode().role); this.Deactivate(item); item = items[index]; - item.Activate(item.GetNode()); + item.Activate(event, item.GetNode()); }, Up: function(event, item) { this.Move(event, item, function(x) { return x - 1; }); }, Down: function(event, item) { - console.log('?????'); this.Move(event, item, function(x) { return x + 1; }); }, Right: function(event, item) { @@ -733,7 +734,19 @@ }, Space: function (event, menu) { this.Mouseup(event, menu); - } + }, + + Activate: function (event, menu) { + this.Deactivate(menu); + if (!this.disabled) { + menu.className += " MathJax_MenuActive"; + } + this.DeactivateSubmenus(menu); + MENU.Focus(menu); + }, + Deactivate: function (menu) { + menu.className = menu.className.replace(/ MathJax_MenuActive/,"")} + }); /*************************************************************/ @@ -805,21 +818,21 @@ this.ClearTimer(); }, Mouseover: function(event, menu) { - this.Activate(menu); + this.Activate(event, menu); }, Mouseup: function (event,menu) { if (!this.disabled) { if (!this.submenu.posted) { this.ClearTimer(); - this.submenu.Post(event,menu,this.ltr); + this.submenu.Post(event, menu, this.ltr); MENU.Focus(menu); } else { - this.RemoveSubmenus(menu); + this.DeactivateSubmenus(menu); } } return FALSE(event); }, - Activate: function (menu) { + Activate: function (event, menu) { if (!this.disabled) { this.Deactivate(menu); menu.className += " MathJax_MenuActive"; @@ -835,7 +848,7 @@ Right: function(event, menu) { if (this.submenu.items.length > 0) { var item = this.submenu.items[0]; - item.Activate(item.GetNode()); + item.Activate(event, item.GetNode()); } } }); @@ -924,7 +937,7 @@ def.className += " MathJax_MenuLabel"; return [this.Name()]; }, - Activate: function(menu) { + Activate: function(event, menu) { this.Deactivate(menu); MENU.Focus(menu); }, From 4c54fe224e08b5bb53e59e2af2b4c46013ddafeb Mon Sep 17 00:00:00 2001 From: zorkow Date: Fri, 21 Aug 2015 12:36:44 +0100 Subject: [PATCH 13/66] Fixes tangling active on mouseover. --- unpacked/extensions/MathMenu.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/unpacked/extensions/MathMenu.js b/unpacked/extensions/MathMenu.js index c7466d7cd..865c65654 100644 --- a/unpacked/extensions/MathMenu.js +++ b/unpacked/extensions/MathMenu.js @@ -423,6 +423,7 @@ return MENU.Event(event,this.menu||this.parentNode,(this.menu?"Touchend":"Remove")); }, Event: function (event,menu,type,force) { + console.log(type); if (MENU.skipMouseover && type === "Mouseover" && !force) {return FALSE(event)} if (MENU.skipUp) { if (type.match(/Mouseup|Touchend/)) {delete MENU.skipUp; return FALSE(event)} @@ -606,6 +607,9 @@ Name: function () {return _(this.name[0],this.name[1])}, Mouseover: function (event,menu) { + if (menu.parentNode === MENU.active.parentNode) { + this.Deactivate(MENU.active); + } this.Activate(event, menu); }, Mouseout: function (event,menu) { @@ -745,7 +749,8 @@ MENU.Focus(menu); }, Deactivate: function (menu) { - menu.className = menu.className.replace(/ MathJax_MenuActive/,"")} + menu.className = menu.className.replace(/ MathJax_MenuActive/,""); + } }); From 64e8419ff1e8f0ca1167350d573e1e82ef7c9b1b Mon Sep 17 00:00:00 2001 From: zorkow Date: Fri, 21 Aug 2015 12:37:26 +0100 Subject: [PATCH 14/66] Whitespace cleanup. --- unpacked/extensions/MathEvents.js | 88 +++++++++++----------- unpacked/extensions/MathMenu.js | 118 +++++++++++++++--------------- 2 files changed, 103 insertions(+), 103 deletions(-) diff --git a/unpacked/extensions/MathEvents.js b/unpacked/extensions/MathEvents.js index 016622f17..d122f66af 100644 --- a/unpacked/extensions/MathEvents.js +++ b/unpacked/extensions/MathEvents.js @@ -4,20 +4,20 @@ /************************************************************* * * MathJax/extensions/MathEvents.js - * + * * Implements the event handlers needed by the output jax to perform * menu, hover, and other events. * * --------------------------------------------------------------------- - * + * * Copyright (c) 2011-2015 The MathJax Consortium - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -27,12 +27,12 @@ (function (HUB,HTML,AJAX,CALLBACK,LOCALE,OUTPUT,INPUT) { var VERSION = "2.5.0"; - + var EXTENSION = MathJax.Extension; var ME = EXTENSION.MathEvents = {version: VERSION}; - + var SETTINGS = HUB.config.menuSettings; - + var CONFIG = { hover: 500, // time required to be considered a hover frame: { @@ -41,7 +41,7 @@ bcolor: "#A6D", // frame border color hwidth: "15px", // haze width hcolor: "#83A" // haze color - }, + }, button: { x: -6, y: -3, // menu button offsets wx: -2 // button offset for full-width equations @@ -99,12 +99,12 @@ } }; - + // // Common event-handling code // var EVENT = ME.Event = { - + LEFTBUTTON: 0, // the event.button value for left button RIGHTBUTTON: 2, // the event.button value for right button MENUKEY: "altKey", // the event value for alternate context menu @@ -131,7 +131,7 @@ Click: function (event) {return EVENT.Handler(event,"Click",this)}, DblClick: function (event) {return EVENT.Handler(event,"DblClick",this)}, Menu: function (event) {return EVENT.Handler(event,"ContextMenu",this)}, - + // // Call the output jax's event handler or the zoom handler // @@ -143,7 +143,7 @@ if (jax[type]) {return jax[type](event,math)} if (EXTENSION.MathZoom) {return EXTENSION.MathZoom.HandleEvent(event,type,math)} }, - + // // Try to cancel the event in every way we can // @@ -156,12 +156,12 @@ } return false; }, - + // // Keydown event handler. Should only fire on Space key. // // TODO: (sorge) Fit this into the Handler function. - // + // Keydown: function (event, math) { var jax = OUTPUT[this.jaxID]; if (event.keyCode === EVENT.KEY.SPACE) { @@ -169,7 +169,7 @@ EVENT.ContextMenu(event, this); }; }, - + // // Load the contextual menu code, if needed, and post the menu // @@ -192,7 +192,7 @@ } // - // If the menu code is loaded, + // If the menu code is loaded, // Check if localization needs loading; // If not, post the menu, and return. // Otherwise wait for the localization to load @@ -206,12 +206,12 @@ if (!load) { MENU.jax = jax; var source = MENU.menu.Find("Show Math As").submenu; - source.items[0].name = jax.sourceMenuTitle; - source.items[0].format = (jax.sourceMenuFormat||"MathML"); + source.items[0].name = jax.sourceMenuTitle; + source.items[0].format = (jax.sourceMenuFormat||"MathML"); source.items[1].name = INPUT[jax.inputJax].sourceMenuTitle; source.items[5].disabled = !INPUT[jax.inputJax].annotationEncoding; - // + // // Try and find each known annotation format and enable the menu // items accordingly. // @@ -253,7 +253,7 @@ ); return EVENT.False(event); }, - + // // Mousedown handler for alternate means of accessing menu // @@ -270,26 +270,26 @@ return JAX.ContextMenu(event,math,true); } }, - + ClearSelection: function () { if (ME.safariContextMenuBug) {setTimeout("window.getSelection().empty()",0)} if (document.selection) {setTimeout("document.selection.empty()",0)} }, - + getBBox: function (span) { span.appendChild(ME.topImg); var h = ME.topImg.offsetTop, d = span.offsetHeight-h, w = span.offsetWidth; span.removeChild(ME.topImg); return {w:w, h:h, d:d}; } - + }; - + // // Handle hover "discoverability" // var HOVER = ME.Hover = { - + // // Check if we are moving from a non-MathJax element to a MathJax one // and either start fading in again (if it is fading out) or start the @@ -336,7 +336,7 @@ return EVENT.False(event); } }, - + // // Clear the old timer and start a new one // @@ -347,7 +347,7 @@ ClearHoverTimer: function () { if (this.hoverTimer) {clearTimeout(this.hoverTimer); delete this.hoverTimer} }, - + // // Handle putting up the hover frame // @@ -458,7 +458,7 @@ jax.hover.timer = setTimeout(CALLBACK(["HoverFade",this,jax]),(delay||CONFIG.fadeDelay)); } }, - + // // Handle a click on the menu button // @@ -466,7 +466,7 @@ if (!event) {event = window.event} return OUTPUT[this.jax].ContextMenu(event,this.math,true); }, - + // // Clear all hover timers // @@ -476,7 +476,7 @@ HOVER.ClearHoverTimer(); delete jax.hover; }, - + // // Make a measurement in pixels // @@ -496,9 +496,9 @@ } }; - + // - // Handle touch events. + // Handle touch events. // // Use double-tap-and-hold as a replacement for context menu event. // Use double-tap as a replacement for double click. @@ -507,7 +507,7 @@ last: 0, // time of last tap event delay: 500, // delay time for double-click - + // // Check if this is a double-tap, and if so, start the timer // for the double-tap and hold (to trigger the contextual menu) @@ -521,9 +521,9 @@ event.preventDefault(); } }, - + // - // Check if there is a timeout pending, i.e., we have a + // Check if there is a timeout pending, i.e., we have a // double-tap and were waiting to see if it is held long // enough for the menu. Since we got the end before the // timeout, it is a double-click, not a double-tap-and-hold. @@ -539,7 +539,7 @@ return EVENT.Handler((event.touches[0]||event.touch),"DblClick",this); } }, - + // // If the timeout passes without an end event, we issue // the contextual menu event. @@ -548,10 +548,10 @@ delete TOUCH.timeout; TOUCH.last = 0; TOUCH.up = false; return EVENT.Handler((event.touches[0]||event.touch),"ContextMenu",math); } - + }; - - /* + + /* * // * // Mobile screens are small, so use larger version of arrow * // @@ -561,7 +561,7 @@ * CONFIG.button.x = -6; * } */ - + // // Set up browser-specific values // @@ -584,7 +584,7 @@ ME.noContextMenuBug = true; // doesn't produce contextmenu event } }); - + // // Used in measuring zoom and hover positions // @@ -605,7 +605,7 @@ haze["-moz-box-shadow"] = haze["-khtml-box-shadow"] = "0px 0px "+CONFIG.frame.hwidth+" "+CONFIG.frame.hcolor; }; - + // // Queue the events needed for startup // @@ -617,6 +617,6 @@ ["Post",HUB.Startup.signal,"MathEvents Ready"], ["loadComplete",AJAX,"[MathJax]/extensions/MathEvents.js"] ); - + })(MathJax.Hub,MathJax.HTML,MathJax.Ajax,MathJax.Callback, MathJax.Localization,MathJax.OutputJax,MathJax.InputJax); diff --git a/unpacked/extensions/MathMenu.js b/unpacked/extensions/MathMenu.js index 865c65654..e4be5c4b1 100644 --- a/unpacked/extensions/MathMenu.js +++ b/unpacked/extensions/MathMenu.js @@ -4,21 +4,21 @@ /************************************************************* * * MathJax/extensions/MathMenu.js - * + * * Implements a right-mouse (or CTRL-click) menu over mathematics * elements that gives the user the ability to copy the source, * change the math size, and zoom settings. * * --------------------------------------------------------------------- - * + * * Copyright (c) 2010-2015 The MathJax Consortium - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -30,7 +30,7 @@ var VERSION = "2.5.0"; var SIGNAL = MathJax.Callback.Signal("menu"); // signal for menu events - + MathJax.Extension.MathMenu = { version: VERSION, signal: SIGNAL @@ -45,7 +45,7 @@ var isPC = HUB.Browser.isPC, isMSIE = HUB.Browser.isMSIE, isIE9 = ((document.documentMode||0) > 8); var ROUND = (isPC ? null : "5px"); - + var CONFIG = HUB.CombineConfig("MathMenu",{ delay: 150, // the delay for submenus @@ -72,7 +72,7 @@ left: Math.round((screen.width - 400)/2), top: Math.round((screen.height - 300)/3) }, - + styles: { "#MathJax_About": { position:"fixed", left:"50%", width:"auto", "text-align":"center", @@ -143,28 +143,28 @@ padding: (isPC ? "2px 2em 4px 1.33em" : "1px 2em 3px 1.33em"), "font-style":"italic" }, - + ".MathJax_MenuRule": { "border-top": (isPC ? "1px solid #CCCCCC" : "1px solid #DDDDDD"), margin: (isPC ? "4px 1px 0px" : "4px 3px") }, - + ".MathJax_MenuDisabled": { color:"GrayText" }, - + ".MathJax_MenuActive": { "background-color": (isPC ? "Highlight" : "#606872"), color: (isPC ? "HighlightText" : "white") }, - + "#MathJax_AboutClose": { top:".2em", right:".2em" }, ".MathJax_Menu .MathJax_MenuClose": { top:"-10px", left:"-10px" }, - + ".MathJax_MenuClose": { position:"absolute", cursor:"pointer", @@ -184,7 +184,7 @@ "-webkit-border-radius": "18px", // Safari and Chrome "-moz-border-radius": "18px", // Firefox "-khtml-border-radius": "18px", // Konqueror - "line-height":0, + "line-height":0, padding:"8px 0 6px" // may need to be browser-specific }, ".MathJax_MenuClose:hover": { @@ -197,7 +197,7 @@ } }); - + var FALSE, HOVER, KEY; HUB.Register.StartupHook("MathEvents Ready",function () { FALSE = MathJax.Extension.MathEvents.Event.False; @@ -247,7 +247,7 @@ Down: function(event, menu) { }, Space: function(event, menu) { } }, {}); - + /*************************************************************/ /* @@ -259,7 +259,7 @@ posted: false, title: null, margin: 5, - + Init: function (def) {this.items = [].slice.call(arguments,0)}, With: function (def) {if (def) {HUB.Insert(this,def)}; return this}, @@ -290,7 +290,7 @@ ontouchstart: MENU.Close, ontouchend: FALSE, onmousedown: MENU.Close, onmouseup: FALSE },[["span",{},"\u00D7"]]); } - + div.appendChild(menu); this.posted = true; menu.style.width = (menu.offsetWidth+2) + "px"; @@ -332,9 +332,9 @@ menu.style["KhtmlBorderRadiusTop"+side] = 0; // Konqueror } } - + menu.style.left = x+"px"; menu.style.top = y+"px"; - + if (document.selection && document.selection.empty) {document.selection.empty()} MENU.Focus(menu); return FALSE(event); @@ -376,7 +376,7 @@ } return null; }, - + /* * Find the index of a menu item (so we can insert before or after it) */ @@ -387,7 +387,7 @@ {if (this.items[i].name[n] === name) {return i}} return null; }, - + Right: function(event, menu) { MENU.Right(event, menu); }, @@ -403,7 +403,7 @@ item.Activate(event, item.GetNode()); } },{ - + config: CONFIG, div: null, // the DOM elements for the menu and submenus @@ -484,7 +484,7 @@ node: null, // The node the menu was activated on. active: null, // The currently focused item. There can only be one! posted: false, // Is a menu open? - + GetJaxs: function() { var nodes = document.getElementsByClassName('MathJax'); for (var i = 0, node; node = nodes[i]; i++) { @@ -555,14 +555,14 @@ Mod: function(a, n) { return ((a % n) + n) % n; }, - + saveCookie: function () {HTML.Cookie.Set("menu",this.cookie)}, getCookie: function () {this.cookie = HTML.Cookie.Get("menu")} }); MathJax.Menu.NAV = NAV; - + /*************************************************************/ /* * Abstract class of menu items. @@ -572,7 +572,7 @@ name: "", // The menu item's label as [id,label] pair. node: null, // The HTML node of the item. menu: null, // The parent menu containing that item. HTML node. - + /* * Accessor method for node. */ @@ -608,7 +608,7 @@ Mouseover: function (event,menu) { if (menu.parentNode === MENU.active.parentNode) { - this.Deactivate(MENU.active); + this.Deactivate(MENU.active); } this.Activate(event, menu); }, @@ -639,7 +639,7 @@ m--; } }, - + Touchstart: function (event,menu) {return this.TouchEvent(event,menu,"Mousedown")}, Touchend: function (event,menu) {return this.TouchEvent(event,menu,"Mouseup")}, TouchEvent: function (event,menu,type) { @@ -652,7 +652,7 @@ MENU.Event(event,menu,type); return false; }, - + Remove: function (event,menu) { menu = menu.parentNode.menuItem; return menu.Remove(event,menu); @@ -673,7 +673,7 @@ menu.className = menu.className.replace(/ MathJax_MenuActive/,"")}, With: function (def) {if (def) {HUB.Insert(this,def)}; return this}, - + isRTL: function () {return MENU.isRTL}, rtlClass: function () {return (this.isRTL() ? " RTL" : "")} }); @@ -685,7 +685,7 @@ MENU.ENTRY = MENU.ITEM.Subclass({ role: "menuitem", // Aria role. - + Attributes: function() { var def = this.SUPER(arguments).Attributes.call( this, @@ -739,7 +739,7 @@ Space: function (event, menu) { this.Mouseup(event, menu); }, - + Activate: function (event, menu) { this.Deactivate(menu); if (!this.disabled) { @@ -753,7 +753,7 @@ } }); - + /*************************************************************/ /* * A menu item that performs a command when selected @@ -766,7 +766,7 @@ this.name = name; this.action = action; this.With(def); }, - + Label: function (def,menu) {return [this.Name()]}, //TODO: Focus the popup. Mouseup: function (event,menu) { @@ -866,7 +866,7 @@ variable: null, // the variable name marker: (isPC ? "\u25CF" : "\u2713"), // the checkmark 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); @@ -885,7 +885,7 @@ if (item && item.variable === this.variable) {child[i].firstChild.style.display = "none"} } - menu.firstChild.display = ""; + menu.firstChild.display = ""; CONFIG.settings[this.variable] = this.value; MENU.cookie[this.variable] = CONFIG.settings[this.variable]; MENU.saveCookie(); SIGNAL.Post(["radio button",this]); @@ -930,7 +930,7 @@ /*************************************************************/ /* * A menu item that is a label - */ + */ MENU.ITEM.LABEL = MENU.ENTRY.Subclass({ role: "menuitem", // Aria role. @@ -959,7 +959,7 @@ return null; } }); - + /*************************************************************/ /*************************************************************/ @@ -968,7 +968,7 @@ */ MENU.About = function () { var HTMLCSS = OUTPUT["HTML-CSS"] || {}; - var font = + var font = (HTMLCSS.imgFonts ? "image" : (HTMLCSS.fontInUse ? (HTMLCSS.webFonts ? "web" : "local")+" "+HTMLCSS.fontInUse : @@ -983,7 +983,7 @@ jax.push(["div",{style:{"border-top":"groove 2px",margin:".25em 0"}}]); MENU.About.GetJax(jax,MathJax.Extension,["Extension","%1 Extension v%2"],true); jax.push(["div",{style:{"border-top":"groove 2px",margin:".25em 0"}}],["center",{},[ - HUB.Browser + " v"+HUB.Browser.version + (format ? + HUB.Browser + " v"+HUB.Browser.version + (format ? " \u2014 " + _(format.replace(/ /g,""),format) : "") ]]); MENU.About.div = MENU.Background(MENU.About); @@ -994,7 +994,7 @@ _(font.replace(/ /g,""),"using "+font),["br"],["br"], ["span",{style:{ display:"inline-block", "text-align":"left", "font-size":"80%", - "max-height":"20em", overflow:"auto", + "max-height":"20em", overflow:"auto", "background-color":"#E4E4E4", padding:".4em .6em", border:"1px inset" }},jax],["br"],["br"], ["a",{href:"http://www.mathjax.org/"},["www.mathjax.org"]], @@ -1027,7 +1027,7 @@ return jax; }; - + /* * Handle the MathJax HELP menu */ @@ -1035,7 +1035,7 @@ AJAX.Require("[MathJax]/extensions/HelpDialog.js", function () {MathJax.Extension.Help.Dialog()}); }; - + /* * Handle showing of element's source */ @@ -1119,7 +1119,7 @@ },50); } }; - + /* * Handle rescaling all the math */ @@ -1143,14 +1143,14 @@ "The scale should be a percentage (e.g., 120%%)"))} } }; - + /* * Handle loading the zoom code */ MENU.Zoom = function () { if (!MathJax.Extension.MathZoom) {AJAX.Require("[MathJax]/extensions/MathZoom.js")} }; - + /* * Handle changing the renderer */ @@ -1164,7 +1164,7 @@ switch (CONFIG.settings.renderer) { case "NativeMML": if (!CONFIG.settings.warnedMML) { - if (BROWSER.isChrome && BROWSER.version.substr(0,3) !== "24.") {message = MESSAGE.MML.WebKit} + if (BROWSER.isChrome && BROWSER.version.substr(0,3) !== "24.") {message = MESSAGE.MML.WebKit} else if (BROWSER.isSafari && !BROWSER.versionAtLeast("5.0")) {message = MESSAGE.MML.WebKit} else if (BROWSER.isMSIE) {if (!BROWSER.hasMathPlayer) {message = MESSAGE.MML.MSIE}} else {message = MESSAGE.MML[BROWSER]} @@ -1176,7 +1176,7 @@ if (!CONFIG.settings.warnedSVG) { if (BROWSER.isMSIE && !isIE9) {message = MESSAGE.SVG.MSIE} } - break; + break; } if (message) { message = _(message[0],message[1]); @@ -1209,7 +1209,7 @@ MSIE: ["MSIENativeMMLWarning", "Internet Explorer requires the MathPlayer plugin " + "in order to process MathML output."], - + Opera: ["OperaNativeMMLWarning", "Opera's support for MathML is limited, so switching to " + "MathML output may cause some expressions to render poorly."], @@ -1222,7 +1222,7 @@ "Your browser's native MathML does not implement all the features " + "used by MathJax, so some expressions may not render properly."] }, - + SVG: { MSIE: ["MSIESVGWarning", "SVG is not implemented in Internet Explorer prior to " + @@ -1231,7 +1231,7 @@ "not display properly."] } }; - + /* * Handle setting the HTMLCSS fonts */ @@ -1239,7 +1239,7 @@ var HTMLCSS = OUTPUT["HTML-CSS"]; if (!HTMLCSS) return; document.location.reload(); }; - + /* * Handle selection of locale and rerender the page */ @@ -1261,7 +1261,7 @@ }); } }; - + /* * Handle setting MathPlayer events */ @@ -1294,7 +1294,7 @@ "The MathJax contextual menu will be disabled, but you can " + "Alt-Click on an expression to obtain the MathJax menu instead."] }; - + /*************************************************************/ /*************************************************************/ @@ -1475,7 +1475,7 @@ trigger.items[0].disabled = trigger.items[1].disabled = true; if (settings.zoom === "Hover" || settings.zoom == "Click") {settings.zoom = "None"} trigger.items = trigger.items.slice(0,4); - + if (navigator.appVersion.match(/[ (]Android[) ]/)) { MENU.ITEM.SUBMENU.Augment({marker: "\u00BB"}); } @@ -1485,7 +1485,7 @@ MENU.CreateLocaleMenu(); MENU.CreateAnnotationMenu(); }); - + MENU.showRenderer = function (show) { MENU.cookie.showRenderer = CONFIG.showRenderer = show; MENU.saveCookie(); MENU.menu.Find("Math Settings","Math Renderer").hidden = !show; @@ -1511,12 +1511,12 @@ MENU.cookie.showLocale = CONFIG.showLocale = show; MENU.saveCookie(); MENU.menu.Find("Language").hidden = !show; }; - + MathJax.Hub.Register.StartupHook("HTML-CSS Jax Ready",function () { if (!MathJax.OutputJax["HTML-CSS"].config.imageFont) {MENU.menu.Find("Math Settings","Font Preference","TeX (image)").disabled = true} }); - + /*************************************************************/ CALLBACK.Queue( From 2f834334223e78792224578dc86470ab659b77b1 Mon Sep 17 00:00:00 2001 From: zorkow Date: Fri, 21 Aug 2015 12:59:28 +0100 Subject: [PATCH 15/66] Makes Attributes interface uniform. --- unpacked/extensions/MathMenu.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/unpacked/extensions/MathMenu.js b/unpacked/extensions/MathMenu.js index e4be5c4b1..7237a0092 100644 --- a/unpacked/extensions/MathMenu.js +++ b/unpacked/extensions/MathMenu.js @@ -423,7 +423,6 @@ return MENU.Event(event,this.menu||this.parentNode,(this.menu?"Touchend":"Remove")); }, Event: function (event,menu,type,force) { - console.log(type); if (MENU.skipMouseover && type === "Mouseover" && !force) {return FALSE(event)} if (MENU.skipUp) { if (type.match(/Mouseup|Touchend/)) {delete MENU.skipUp; return FALSE(event)} @@ -686,13 +685,14 @@ role: "menuitem", // Aria role. - Attributes: function() { - var def = this.SUPER(arguments).Attributes.call( - this, + Attributes: function(def) { + def = HUB.Insert( {onmouseover: MENU.Mouseover, onmouseout: MENU.Mouseout, onmousedown: MENU.Mousedown, role: this.role, onkeydown: MENU.Keydown, - 'aria-disabled': !!this.disabled}); + 'aria-disabled': !!this.disabled}, + def); + def = this.SUPER(arguments).Attributes.call(this, def); if (this.disabled) { def.className += " MathJax_MenuDisabled"; } From 72e1e6b5b566f5b51d0e07b970299c18b6322aa7 Mon Sep 17 00:00:00 2001 From: zorkow Date: Fri, 21 Aug 2015 13:07:42 +0100 Subject: [PATCH 16/66] Fixes case of disabled submenu entry. --- unpacked/extensions/MathMenu.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/unpacked/extensions/MathMenu.js b/unpacked/extensions/MathMenu.js index 7237a0092..4132d47d7 100644 --- a/unpacked/extensions/MathMenu.js +++ b/unpacked/extensions/MathMenu.js @@ -666,10 +666,8 @@ MENU.Focus(menu); }, Deactivate: function (menu) { - console.log(menu); - console.log(menu.className); - - menu.className = menu.className.replace(/ MathJax_MenuActive/,"")}, + menu.className = menu.className.replace(/ MathJax_MenuActive/,""); + }, With: function (def) {if (def) {HUB.Insert(this,def)}; return this}, @@ -851,6 +849,9 @@ MENU.Focus(menu); }, Right: function(event, menu) { + if (this.disabled) { + return; + } if (this.submenu.items.length > 0) { var item = this.submenu.items[0]; item.Activate(event, item.GetNode()); From e29e3c9e99facb1f1417ee3c2ff2b6f3f691c1cd Mon Sep 17 00:00:00 2001 From: zorkow Date: Mon, 24 Aug 2015 17:01:50 +0100 Subject: [PATCH 17/66] Fixes activation problem for submenu anchor. --- unpacked/extensions/MathMenu.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/unpacked/extensions/MathMenu.js b/unpacked/extensions/MathMenu.js index 4132d47d7..407b23be2 100644 --- a/unpacked/extensions/MathMenu.js +++ b/unpacked/extensions/MathMenu.js @@ -623,7 +623,8 @@ for (var i = 0, m = items.length; i < m; i++) { var item = items[i].menuItem; // Deactivates submenu items. - if (item && item.submenu && item.submenu.posted) { + if (item && item.submenu && item.submenu.posted && + item !== menu.menuItem) { item.Deactivate(items[i]); } } From 816259d6ffc9fe6d020e9ea5d53a81b99fad226b Mon Sep 17 00:00:00 2001 From: zorkow Date: Tue, 25 Aug 2015 13:48:00 +0100 Subject: [PATCH 18/66] Introduces accessor methods for all cached HTML nodes. --- unpacked/extensions/MathMenu.js | 68 +++++++++++++++++++++------------ 1 file changed, 43 insertions(+), 25 deletions(-) diff --git a/unpacked/extensions/MathMenu.js b/unpacked/extensions/MathMenu.js index 407b23be2..ced9b8a30 100644 --- a/unpacked/extensions/MathMenu.js +++ b/unpacked/extensions/MathMenu.js @@ -297,7 +297,7 @@ if (event) { var x = event.pageX, y = event.pageY; } - var node = MENU.node || event.target; + var node = MENU.GetNode() || event.target; if (!x && !y && node) { var rect = node.getBoundingClientRect(); x = rect.right; @@ -480,8 +480,8 @@ jaxs: [], // List of all MathJax nodes. hasJaxs: false, // Flag to indicate if the MathJax node list has already // been computed. - node: null, // The node the menu was activated on. - active: null, // The currently focused item. There can only be one! + node: null, // The node the menu was activated on. HTML! + active: null, // The currently focused item. There can only be one! HTML! posted: false, // Is a menu open? GetJaxs: function() { @@ -490,6 +490,18 @@ MENU.jaxs.push(node); } }, + GetNode: function() { + return MENU.node; + }, + SetNode: function(node) { + MENU.node = node; + }, + GetActive: function() { + return MENU.active; + }, + SetActive: function(node) { + MENU.active = node; + }, // // Focus is a global affair, since we only ever want a single focused item. // @@ -497,19 +509,19 @@ if (!MENU.posted) { MENU.Activate(menu); } - if (MENU.active) { - MENU.active.tabIndex = -1; + if (MENU.GetActive()) { + MENU.GetActive().tabIndex = -1; } - MENU.active = menu; - MENU.active.tabIndex = 0; - MENU.active.focus(); + MENU.SetActive(menu); + MENU.GetActive().tabIndex = 0; + MENU.GetActive().focus(); }, Activate: function(event, menu) { if (!MENU.hasJaxs) { MENU.GetJaxs(); } - if (!MENU.node) { - MENU.node = document.getElementById(MENU.jax.inputID + '-Frame'); + if (!MENU.GetNode()) { + MENU.SetNode(document.getElementById(MENU.jax.inputID + '-Frame')); } for (var j = 0, jax; jax = MENU.jaxs[j]; j++) { jax.tabIndex = -1; @@ -517,13 +529,13 @@ MENU.posted = true; }, Unfocus: function() { - MENU.active.tabIndex = -1; - MENU.active = null; + MENU.GetActive().tabIndex = -1; + MENU.SetActive(null); for (var j = 0, jax; jax = MENU.jaxs[j]; j++) { jax.tabIndex = 0; } - MENU.node.focus(); - MENU.node = null; + MENU.GetNode().focus(); + MENU.SetNode(null); MENU.posted = false; }, //TODO: A toggle focus method on the top level would avoid having to @@ -533,13 +545,13 @@ if (len === 0) { return; } - var next = MENU.jaxs[MENU.Mod(move(MENU.jaxs.indexOf(MENU.node)), len)]; - if (next === MENU.node) { + var next = MENU.jaxs[MENU.Mod(move(MENU.jaxs.indexOf(MENU.GetNode())), len)]; + if (next === MENU.GetNode()) { return; } MENU.menu.Remove(event, menu); MENU.jax = MathJax.Hub.getJaxFor(next); - MENU.node = next; + MENU.SetNode(next); MENU.menu.Post(null); }, Right: function(event, menu) { @@ -584,6 +596,12 @@ SetNode: function(node) { this.node = node; }, + GetMenuNode: function() { + return this.menu; + }, + SetMenuNode: function(menu) { + this.menu = menu; + }, Attributes: function(def) { return HUB.Insert( @@ -600,14 +618,14 @@ var label = this.Label(def,menu); var node = HTML.addElement(menu, "div", def, label); this.SetNode(node); - this.menu = menu; + this.SetMenuNode(menu); } }, Name: function () {return _(this.name[0],this.name[1])}, Mouseover: function (event,menu) { - if (menu.parentNode === MENU.active.parentNode) { - this.Deactivate(MENU.active); + if (menu.parentNode === MENU.GetActive().parentNode) { + this.Deactivate(MENU.GetActive()); } this.Activate(event, menu); }, @@ -619,7 +637,7 @@ DeactivateSubmenus: function(menu) { var menus = document.getElementById("MathJax_MenuFrame").childNodes, - items = this.menu.childNodes; + items = this.GetMenuNode().childNodes; for (var i = 0, m = items.length; i < m; i++) { var item = items[i].menuItem; // Deactivates submenu items. @@ -633,7 +651,7 @@ RemoveSubmenus: function(menu, menus) { menus = menus || document.getElementById("MathJax_MenuFrame").childNodes; var m = menus.length-1; - while (m >= 0 && this.menu.menuItem !== menus[m].menuItem) { + while (m >= 0 && this.GetMenuNode().menuItem !== menus[m].menuItem) { menus[m].menuItem.posted = false; menus[m].parentNode.removeChild(menus[m]); m--; @@ -698,7 +716,7 @@ return def; }, Move: function(event, item, move) { - var items = this.menu.menuItem.items; + var items = this.GetMenuNode().menuItem.items; var len = items.length; var index = items.indexOf(this); if (index === -1) { @@ -718,12 +736,12 @@ this.Move(event, item, function(x) { return x + 1; }); }, Right: function(event, item) { - if (this.menu.menuItem === MENU.menu) { + if (this.GetMenuNode().menuItem === MENU.menu) { MENU.Right(event, item); } }, Left: function(event, item) { - if (this.menu.menuItem === MENU.menu) { + if (this.GetMenuNode().menuItem === MENU.menu) { MENU.Left(event, item); } else { this.Deactivate(item); From 1228bb89ad5c9ffb307dee22ed0d1814e378a4d5 Mon Sep 17 00:00:00 2001 From: zorkow Date: Wed, 26 Aug 2015 13:38:44 +0100 Subject: [PATCH 19/66] Introduces accessor function for cached MathJax nodes. --- unpacked/extensions/MathMenu.js | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/unpacked/extensions/MathMenu.js b/unpacked/extensions/MathMenu.js index ced9b8a30..0bbf3c6ae 100644 --- a/unpacked/extensions/MathMenu.js +++ b/unpacked/extensions/MathMenu.js @@ -485,10 +485,15 @@ posted: false, // Is a menu open? GetJaxs: function() { + if (MENU.hasJaxs) { + return MENU.jaxs; + } var nodes = document.getElementsByClassName('MathJax'); for (var i = 0, node; node = nodes[i]; i++) { MENU.jaxs.push(node); } + MENU.hasJaxs = true; + return MENU.jaxs; }, GetNode: function() { return MENU.node; @@ -517,13 +522,10 @@ MENU.GetActive().focus(); }, Activate: function(event, menu) { - if (!MENU.hasJaxs) { - MENU.GetJaxs(); - } if (!MENU.GetNode()) { MENU.SetNode(document.getElementById(MENU.jax.inputID + '-Frame')); } - for (var j = 0, jax; jax = MENU.jaxs[j]; j++) { + for (var j = 0, jax; jax = MENU.GetJaxs()[j]; j++) { jax.tabIndex = -1; } MENU.posted = true; @@ -531,7 +533,8 @@ Unfocus: function() { MENU.GetActive().tabIndex = -1; MENU.SetActive(null); - for (var j = 0, jax; jax = MENU.jaxs[j]; j++) { + var jaxs = MENU.GetJaxs(); + for (var j = 0, jax; jax = jaxs[j]; j++) { jax.tabIndex = 0; } MENU.GetNode().focus(); @@ -541,11 +544,12 @@ //TODO: A toggle focus method on the top level would avoid having to //tabIndex all the Jaxs. Move: function(event, menu, move) { - var len = MENU.jaxs.length; + var jaxs = MENU.GetJaxs(); + var len = jaxs.length; if (len === 0) { return; } - var next = MENU.jaxs[MENU.Mod(move(MENU.jaxs.indexOf(MENU.GetNode())), len)]; + var next = jaxs[MENU.Mod(move(jaxs.indexOf(MENU.GetNode())), len)]; if (next === MENU.GetNode()) { return; } From 39109bf88a1a4a04d1c1f109eb8c44cf75f2ea13 Mon Sep 17 00:00:00 2001 From: zorkow Date: Wed, 26 Aug 2015 13:56:30 +0100 Subject: [PATCH 20/66] Removes caching of MathJax nodes. --- unpacked/extensions/MathMenu.js | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/unpacked/extensions/MathMenu.js b/unpacked/extensions/MathMenu.js index 0bbf3c6ae..9472b68bb 100644 --- a/unpacked/extensions/MathMenu.js +++ b/unpacked/extensions/MathMenu.js @@ -477,26 +477,22 @@ /* * Keyboard navigation of menu. */ - jaxs: [], // List of all MathJax nodes. - hasJaxs: false, // Flag to indicate if the MathJax node list has already - // been computed. node: null, // The node the menu was activated on. HTML! active: null, // The currently focused item. There can only be one! HTML! posted: false, // Is a menu open? GetJaxs: function() { - if (MENU.hasJaxs) { - return MENU.jaxs; + var jaxs = MathJax.Hub.getAllJax(); + var nodes = []; + for (var i = 0, jax; jax = jaxs[i]; i++) { + var node = document.getElementById(jax.inputID + "-Frame"); + nodes.push(node.isMathJax ? node : node.firstChild); } - var nodes = document.getElementsByClassName('MathJax'); - for (var i = 0, node; node = nodes[i]; i++) { - MENU.jaxs.push(node); - } - MENU.hasJaxs = true; - return MENU.jaxs; + return nodes; }, GetNode: function() { - return MENU.node; + return document.getElementById(MENU.jax.inputID + '-Frame'); + // return MENU.node; }, SetNode: function(node) { MENU.node = node; @@ -525,7 +521,8 @@ if (!MENU.GetNode()) { MENU.SetNode(document.getElementById(MENU.jax.inputID + '-Frame')); } - for (var j = 0, jax; jax = MENU.GetJaxs()[j]; j++) { + var jaxs = MENU.GetJaxs(); + for (var j = 0, jax; jax = jaxs[j]; j++) { jax.tabIndex = -1; } MENU.posted = true; From 1c07cf3189672877293f102c18b9f215c03be979 Mon Sep 17 00:00:00 2001 From: zorkow Date: Wed, 26 Aug 2015 14:17:08 +0100 Subject: [PATCH 21/66] Removes all caching of MathJax nodes. --- unpacked/extensions/MathMenu.js | 39 ++++++++++++++------------------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/unpacked/extensions/MathMenu.js b/unpacked/extensions/MathMenu.js index 9472b68bb..8e5f23646 100644 --- a/unpacked/extensions/MathMenu.js +++ b/unpacked/extensions/MathMenu.js @@ -297,7 +297,7 @@ if (event) { var x = event.pageX, y = event.pageY; } - var node = MENU.GetNode() || event.target; + var node = MENU.CurrentNode() || event.target; if (!x && !y && node) { var rect = node.getBoundingClientRect(); x = rect.right; @@ -477,26 +477,24 @@ /* * Keyboard navigation of menu. */ - node: null, // The node the menu was activated on. HTML! active: null, // The currently focused item. There can only be one! HTML! posted: false, // Is a menu open? - GetJaxs: function() { + GetNode: function(jax) { + var node = document.getElementById(jax.inputID + '-Frame'); + return node.isMathJax ? node : node.firstChild; + }, + CurrentNode: function() { + return MENU.GetNode(MENU.jax); + }, + AllNodes: function() { var jaxs = MathJax.Hub.getAllJax(); var nodes = []; for (var i = 0, jax; jax = jaxs[i]; i++) { - var node = document.getElementById(jax.inputID + "-Frame"); - nodes.push(node.isMathJax ? node : node.firstChild); + nodes.push(MENU.GetNode(jax)); } return nodes; }, - GetNode: function() { - return document.getElementById(MENU.jax.inputID + '-Frame'); - // return MENU.node; - }, - SetNode: function(node) { - MENU.node = node; - }, GetActive: function() { return MENU.active; }, @@ -518,10 +516,7 @@ MENU.GetActive().focus(); }, Activate: function(event, menu) { - if (!MENU.GetNode()) { - MENU.SetNode(document.getElementById(MENU.jax.inputID + '-Frame')); - } - var jaxs = MENU.GetJaxs(); + var jaxs = MENU.AllNodes(); for (var j = 0, jax; jax = jaxs[j]; j++) { jax.tabIndex = -1; } @@ -530,29 +525,27 @@ Unfocus: function() { MENU.GetActive().tabIndex = -1; MENU.SetActive(null); - var jaxs = MENU.GetJaxs(); + var jaxs = MENU.AllNodes(); for (var j = 0, jax; jax = jaxs[j]; j++) { jax.tabIndex = 0; } - MENU.GetNode().focus(); - MENU.SetNode(null); + MENU.CurrentNode().focus(); MENU.posted = false; }, //TODO: A toggle focus method on the top level would avoid having to //tabIndex all the Jaxs. Move: function(event, menu, move) { - var jaxs = MENU.GetJaxs(); + var jaxs = MENU.AllNodes(); var len = jaxs.length; if (len === 0) { return; } - var next = jaxs[MENU.Mod(move(jaxs.indexOf(MENU.GetNode())), len)]; - if (next === MENU.GetNode()) { + var next = jaxs[MENU.Mod(move(jaxs.indexOf(MENU.CurrentNode())), len)]; + if (next === MENU.CurrentNode()) { return; } MENU.menu.Remove(event, menu); MENU.jax = MathJax.Hub.getJaxFor(next); - MENU.SetNode(next); MENU.menu.Post(null); }, Right: function(event, menu) { From 0d60b0654ba6904d84611f5d4df4e542ac533fbd Mon Sep 17 00:00:00 2001 From: zorkow Date: Fri, 28 Aug 2015 12:29:19 +0100 Subject: [PATCH 22/66] Removes caching of active element. --- unpacked/extensions/MathMenu.js | 32 +++++++++----------------------- 1 file changed, 9 insertions(+), 23 deletions(-) diff --git a/unpacked/extensions/MathMenu.js b/unpacked/extensions/MathMenu.js index 8e5f23646..2e6274e84 100644 --- a/unpacked/extensions/MathMenu.js +++ b/unpacked/extensions/MathMenu.js @@ -495,25 +495,16 @@ } return nodes; }, - GetActive: function() { - return MENU.active; - }, - SetActive: function(node) { - MENU.active = node; + ActiveNode: function() { + return document.activeElement; }, // // Focus is a global affair, since we only ever want a single focused item. // Focus: function(menu) { - if (!MENU.posted) { - MENU.Activate(menu); - } - if (MENU.GetActive()) { - MENU.GetActive().tabIndex = -1; - } - MENU.SetActive(menu); - MENU.GetActive().tabIndex = 0; - MENU.GetActive().focus(); + !MENU.posted ? MENU.Activate(menu) : MENU.ActiveNode().tabIndex = -1; + menu.tabIndex = 0; + menu.focus(); }, Activate: function(event, menu) { var jaxs = MENU.AllNodes(); @@ -523,8 +514,7 @@ MENU.posted = true; }, Unfocus: function() { - MENU.GetActive().tabIndex = -1; - MENU.SetActive(null); + MENU.ActiveNode().tabIndex = -1; var jaxs = MENU.AllNodes(); for (var j = 0, jax; jax = jaxs[j]; j++) { jax.tabIndex = 0; @@ -591,10 +581,7 @@ this.node = node; }, GetMenuNode: function() { - return this.menu; - }, - SetMenuNode: function(menu) { - this.menu = menu; + return this.GetNode().parentNode; }, Attributes: function(def) { @@ -612,14 +599,13 @@ var label = this.Label(def,menu); var node = HTML.addElement(menu, "div", def, label); this.SetNode(node); - this.SetMenuNode(menu); } }, Name: function () {return _(this.name[0],this.name[1])}, Mouseover: function (event,menu) { - if (menu.parentNode === MENU.GetActive().parentNode) { - this.Deactivate(MENU.GetActive()); + if (menu.parentNode === MENU.ActiveNode().parentNode) { + this.Deactivate(MENU.ActiveNode()); } this.Activate(event, menu); }, From 7f4c56df9b334a85b068c0faa2f56ab98ee58d0d Mon Sep 17 00:00:00 2001 From: zorkow Date: Fri, 28 Aug 2015 16:28:12 +0100 Subject: [PATCH 23/66] Removes all caching of DOM elements. --- unpacked/extensions/MathMenu.js | 60 +++++++++++++++------------------ 1 file changed, 27 insertions(+), 33 deletions(-) diff --git a/unpacked/extensions/MathMenu.js b/unpacked/extensions/MathMenu.js index 2e6274e84..37275bfb1 100644 --- a/unpacked/extensions/MathMenu.js +++ b/unpacked/extensions/MathMenu.js @@ -395,12 +395,12 @@ MENU.Left(event, menu); }, Up: function(event, menu) { - var item = this.items[this.items.length - 1]; - item.Activate(event, item.GetNode()); + var node = menu.lastChild; + node.menuItem.Activate(event, node); }, Down: function(event, menu) { - var item = this.items[0]; - item.Activate(event, item.GetNode()); + var node = menu.firstChild; + node.menuItem.Activate(event, node); } },{ @@ -568,22 +568,6 @@ node: null, // The HTML node of the item. menu: null, // The parent menu containing that item. HTML node. - /* - * Accessor method for node. - */ - GetNode: function() { - return this.node; - }, - /* - * Registers the HTML node of the menu item. - */ - SetNode: function(node) { - this.node = node; - }, - GetMenuNode: function() { - return this.GetNode().parentNode; - }, - Attributes: function(def) { return HUB.Insert( {onmouseup: MENU.Mouseup, @@ -598,7 +582,6 @@ var def = this.Attributes(); var label = this.Label(def,menu); var node = HTML.addElement(menu, "div", def, label); - this.SetNode(node); } }, Name: function () {return _(this.name[0],this.name[1])}, @@ -617,7 +600,7 @@ DeactivateSubmenus: function(menu) { var menus = document.getElementById("MathJax_MenuFrame").childNodes, - items = this.GetMenuNode().childNodes; + items = ITEM.GetMenuNode(menu).childNodes; for (var i = 0, m = items.length; i < m; i++) { var item = items[i].menuItem; // Deactivates submenu items. @@ -631,7 +614,7 @@ RemoveSubmenus: function(menu, menus) { menus = menus || document.getElementById("MathJax_MenuFrame").childNodes; var m = menus.length-1; - while (m >= 0 && this.GetMenuNode().menuItem !== menus[m].menuItem) { + while (m >= 0 && ITEM.GetMenuNode(menu).menuItem !== menus[m].menuItem) { menus[m].menuItem.posted = false; menus[m].parentNode.removeChild(menus[m]); m--; @@ -672,6 +655,10 @@ isRTL: function () {return MENU.isRTL}, rtlClass: function () {return (this.isRTL() ? " RTL" : "")} + }, { + GetMenuNode: function(item) { + return item.parentNode; + } }); /*************************************************************/ @@ -696,18 +683,25 @@ return def; }, Move: function(event, item, move) { - var items = this.GetMenuNode().menuItem.items; - var len = items.length; + var menuNode = ITEM.GetMenuNode(item); + var items = []; + for (var i = 0, allItems = menuNode.menuItem.items, it; + it = allItems[i]; i++) { + if (!it.hidden) { + items.push(it); + } + } var index = items.indexOf(this); if (index === -1) { return; } + var len = items.length; + var children = menuNode.childNodes; do { index = MENU.Mod(move(index), len); - } while (items[index].hidden || !items[index].GetNode().role); + } while (items[index].hidden || !children[index].role); this.Deactivate(item); - item = items[index]; - item.Activate(event, item.GetNode()); + items[index].Activate(event, children[index]); }, Up: function(event, item) { this.Move(event, item, function(x) { return x - 1; }); @@ -716,12 +710,12 @@ this.Move(event, item, function(x) { return x + 1; }); }, Right: function(event, item) { - if (this.GetMenuNode().menuItem === MENU.menu) { + if (ITEM.GetMenuNode(item).menuItem === MENU.menu) { MENU.Right(event, item); } }, Left: function(event, item) { - if (this.GetMenuNode().menuItem === MENU.menu) { + if (ITEM.GetMenuNode(item).menuItem === MENU.menu) { MENU.Left(event, item); } else { this.Deactivate(item); @@ -851,9 +845,9 @@ if (this.disabled) { return; } - if (this.submenu.items.length > 0) { - var item = this.submenu.items[0]; - item.Activate(event, item.GetNode()); + var submenuNodes = ITEM.GetMenuNode(menu).nextSibling.childNodes; + if (submenuNodes.length > 0) { + menu.menuItem.Activate(event, submenuNodes[0]); } } }); From d18bfbf66dee2dc1cbc5f39b05461884e53c644f Mon Sep 17 00:00:00 2001 From: zorkow Date: Fri, 28 Aug 2015 16:52:34 +0100 Subject: [PATCH 24/66] Removes redundant methods. --- unpacked/extensions/MathMenu.js | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/unpacked/extensions/MathMenu.js b/unpacked/extensions/MathMenu.js index 37275bfb1..afa91727d 100644 --- a/unpacked/extensions/MathMenu.js +++ b/unpacked/extensions/MathMenu.js @@ -639,18 +639,6 @@ return menu.Remove(event,menu); }, - Activate: function (event, menu) { - this.Deactivate(menu); - if (!this.disabled) { - menu.className += " MathJax_MenuActive"; - } - this.DeactivateSubmenus(menu); - MENU.Focus(menu); - }, - Deactivate: function (menu) { - menu.className = menu.className.replace(/ MathJax_MenuActive/,""); - }, - With: function (def) {if (def) {HUB.Insert(this,def)}; return this}, isRTL: function () {return MENU.isRTL}, From 583f4a60dc300f26721cc0099d718b22311bf0c0 Mon Sep 17 00:00:00 2001 From: zorkow Date: Fri, 28 Aug 2015 18:42:28 +0100 Subject: [PATCH 25/66] Fixes some scolling issues. --- unpacked/extensions/MathMenu.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/unpacked/extensions/MathMenu.js b/unpacked/extensions/MathMenu.js index afa91727d..f4acc3f25 100644 --- a/unpacked/extensions/MathMenu.js +++ b/unpacked/extensions/MathMenu.js @@ -297,16 +297,16 @@ if (event) { var x = event.pageX, y = event.pageY; } + if (!x && !y && event && event.clientX && event.clientY) { + x = event.clientX + document.body.scrollLeft + document.documentElement.scrollLeft; + y = event.clientY + document.body.scrollTop + document.documentElement.scrollTop; + } var node = MENU.CurrentNode() || event.target; if (!x && !y && node) { var rect = node.getBoundingClientRect(); x = rect.right; y = rect.bottom; } - if (!x && !y) { - x = event.clientX + document.body.scrollLeft + document.documentElement.scrollLeft; - y = event.clientY + document.body.scrollTop + document.documentElement.scrollTop; - } if (!parent) { if (x + menu.offsetWidth > document.body.offsetWidth - this.margin) {x = document.body.offsetWidth - menu.offsetWidth - this.margin} @@ -835,7 +835,7 @@ } var submenuNodes = ITEM.GetMenuNode(menu).nextSibling.childNodes; if (submenuNodes.length > 0) { - menu.menuItem.Activate(event, submenuNodes[0]); + this.submenu.items[0].Activate(event, submenuNodes[0]); } } }); From 66b56d9ac96b64bf2d2240cc659a2f9d331410b8 Mon Sep 17 00:00:00 2001 From: zorkow Date: Fri, 28 Aug 2015 22:52:45 +0100 Subject: [PATCH 26/66] Moves posting code for keyboard triggered menus. --- unpacked/extensions/MathMenu.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/unpacked/extensions/MathMenu.js b/unpacked/extensions/MathMenu.js index f4acc3f25..904e0b9fe 100644 --- a/unpacked/extensions/MathMenu.js +++ b/unpacked/extensions/MathMenu.js @@ -301,13 +301,13 @@ x = event.clientX + document.body.scrollLeft + document.documentElement.scrollLeft; y = event.clientY + document.body.scrollTop + document.documentElement.scrollTop; } - var node = MENU.CurrentNode() || event.target; - if (!x && !y && node) { - var rect = node.getBoundingClientRect(); - x = rect.right; - y = rect.bottom; - } if (!parent) { + var node = MENU.CurrentNode() || event.target; + if (!x && !y && node) { + var rect = node.getBoundingClientRect(); + x = rect.right; + y = rect.bottom; + } if (x + menu.offsetWidth > document.body.offsetWidth - this.margin) {x = document.body.offsetWidth - menu.offsetWidth - this.margin} if (MENU.isMobile) {x = Math.max(5,x-Math.floor(menu.offsetWidth/2)); y -= 20} From 9654bd42562c8fceea92eeb65f2c7c0136a3c4d0 Mon Sep 17 00:00:00 2001 From: zorkow Date: Sat, 29 Aug 2015 00:09:43 +0100 Subject: [PATCH 27/66] Navigation of RTL menus. --- unpacked/extensions/MathMenu.js | 46 ++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/unpacked/extensions/MathMenu.js b/unpacked/extensions/MathMenu.js index 904e0b9fe..caef3b4ca 100644 --- a/unpacked/extensions/MathMenu.js +++ b/unpacked/extensions/MathMenu.js @@ -522,9 +522,7 @@ MENU.CurrentNode().focus(); MENU.posted = false; }, - //TODO: A toggle focus method on the top level would avoid having to - //tabIndex all the Jaxs. - Move: function(event, menu, move) { + MoveHorizontal: function(event, menu, move) { var jaxs = MENU.AllNodes(); var len = jaxs.length; if (len === 0) { @@ -539,10 +537,10 @@ MENU.menu.Post(null); }, Right: function(event, menu) { - MENU.Move(event, menu, function(x) {return x + 1;}); + MENU.MoveHorizontal(event, menu, function(x) {return x + 1;}); }, Left: function(event, menu) { - MENU.Move(event, menu, function(x) {return x - 1;}); + MENU.MoveHorizontal(event, menu, function(x) {return x - 1;}); }, //TODO: Move to utility class. @@ -670,7 +668,7 @@ } return def; }, - Move: function(event, item, move) { + MoveVertical: function(event, item, move) { var menuNode = ITEM.GetMenuNode(item); var items = []; for (var i = 0, allItems = menuNode.menuItem.items, it; @@ -692,28 +690,29 @@ items[index].Activate(event, children[index]); }, Up: function(event, item) { - this.Move(event, item, function(x) { return x - 1; }); + this.MoveVertical(event, item, function(x) { return x - 1; }); }, Down: function(event, item) { - this.Move(event, item, function(x) { return x + 1; }); + this.MoveVertical(event, item, function(x) { return x + 1; }); }, Right: function(event, item) { - if (ITEM.GetMenuNode(item).menuItem === MENU.menu) { - MENU.Right(event, item); - } + this.MoveHorizontal(event, item, MENU.Right, !this.isRTL()); }, Left: function(event, item) { + this.MoveHorizontal(event, item, MENU.Left, this.isRTL()); + }, + MoveHorizontal: function(event, item, move, rtl) { if (ITEM.GetMenuNode(item).menuItem === MENU.menu) { - MENU.Left(event, item); - } else { - this.Deactivate(item); - var sibling = item.parentNode.previousSibling; - var actives = sibling.getElementsByClassName('MathJax_MenuActive'); - if (actives.length > 0) { - MENU.Focus(actives[0]); - } - this.RemoveSubmenus(item); + move(event, item); } + if (rtl) { return; } + this.Deactivate(item); + var sibling = item.parentNode.previousSibling; + var actives = sibling.getElementsByClassName('MathJax_MenuActive'); + if (actives.length > 0) { + MENU.Focus(actives[0]); + } + this.RemoveSubmenus(item); }, Space: function (event, menu) { this.Mouseup(event, menu); @@ -829,10 +828,15 @@ } MENU.Focus(menu); }, - Right: function(event, menu) { + MoveHorizontal: function(event, menu, move, rtl) { + console.log(move); if (this.disabled) { return; } + if (!rtl) { + this.SUPER(arguments).MoveHorizontal.apply(this, arguments); + return; + } var submenuNodes = ITEM.GetMenuNode(menu).nextSibling.childNodes; if (submenuNodes.length > 0) { this.submenu.items[0].Activate(event, submenuNodes[0]); From d73dbe28602df68e487f70835920cc59fe6ba050 Mon Sep 17 00:00:00 2001 From: zorkow Date: Sat, 29 Aug 2015 00:30:34 +0100 Subject: [PATCH 28/66] Adds prototype definition for indexOf. --- unpacked/extensions/MathMenu.js | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/unpacked/extensions/MathMenu.js b/unpacked/extensions/MathMenu.js index caef3b4ca..5ac325c1b 100644 --- a/unpacked/extensions/MathMenu.js +++ b/unpacked/extensions/MathMenu.js @@ -42,7 +42,7 @@ [["MathMenu",id]].concat([].slice.call(arguments,1)) ); }; - + var isPC = HUB.Browser.isPC, isMSIE = HUB.Browser.isMSIE, isIE9 = ((document.documentMode||0) > 8); var ROUND = (isPC ? null : "5px"); @@ -829,7 +829,6 @@ MENU.Focus(menu); }, MoveHorizontal: function(event, menu, move, rtl) { - console.log(move); if (this.disabled) { return; } @@ -1509,7 +1508,19 @@ HUB.Register.StartupHook("End Config",{}), // wait until config is complete ["Styles",AJAX,CONFIG.styles], ["Post",HUB.Startup.signal,"MathMenu Ready"], - ["loadComplete",AJAX,"[MathJax]/extensions/MathMenu.js"] + ["loadComplete",AJAX,"[MathJax]/extensions/MathMenu.js"], + function() { + if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function(item, start) { + for (var i = (start || 0), j = this.length; i < j; i++) { + if (item === this[i]) { + return i; + } + } + return -1; + }; + } + } ); })(MathJax.Hub,MathJax.HTML,MathJax.Ajax,MathJax.CallBack,MathJax.OutputJax); From 189d4a8a81fe6e3484879ed71e14344520e61aef Mon Sep 17 00:00:00 2001 From: zorkow Date: Sat, 29 Aug 2015 01:02:33 +0100 Subject: [PATCH 29/66] Adds tabbing and menu key event for for all renderers. --- unpacked/jax/output/CommonHTML/jax.js | 4 +++- unpacked/jax/output/HTML-CSS/jax.js | 5 +++-- unpacked/jax/output/NativeMML/jax.js | 3 +++ unpacked/jax/output/SVG/jax.js | 4 +++- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/unpacked/jax/output/CommonHTML/jax.js b/unpacked/jax/output/CommonHTML/jax.js index 8e46653a9..c8ac52b58 100644 --- a/unpacked/jax/output/CommonHTML/jax.js +++ b/unpacked/jax/output/CommonHTML/jax.js @@ -205,7 +205,9 @@ className:"MathJax_CHTML", id:jax.inputID+"-Frame", isMathJax:true, jaxID:this.id, oncontextmenu:EVENT.Menu, onmousedown: EVENT.Mousedown, onmouseover:EVENT.Mouseover, onmouseout:EVENT.Mouseout, onmousemove:EVENT.Mousemove, - onclick:EVENT.Click, ondblclick:EVENT.DblClick + onclick:EVENT.Click, ondblclick:EVENT.DblClick, + // Added for keyboard accessible menu. + onkeydown: EVENT.Keydown, tabIndex: "0" }); if (HUB.Browser.noContextMenu) { span.ontouchstart = TOUCH.start; diff --git a/unpacked/jax/output/HTML-CSS/jax.js b/unpacked/jax/output/HTML-CSS/jax.js index 79b915d90..8e900f6d9 100644 --- a/unpacked/jax/output/HTML-CSS/jax.js +++ b/unpacked/jax/output/HTML-CSS/jax.js @@ -571,7 +571,9 @@ oncontextmenu:EVENT.Menu, onmousedown: EVENT.Mousedown, onmouseover:EVENT.Mouseover, onmouseout:EVENT.Mouseout, onmousemove:EVENT.Mousemove, onclick:EVENT.Click, - ondblclick:EVENT.DblClick, onkeydown: EVENT.Keydown, tabIndex: "0" + ondblclick:EVENT.DblClick, + // Added for keyboard accessible menu. + onkeydown: EVENT.Keydown, tabIndex: "0" }); if (HUB.Browser.noContextMenu) { span.ontouchstart = TOUCH.start; @@ -2869,7 +2871,6 @@ var alttext = this.Get("alttext"); if (alttext && !span.getAttribute("aria-label")) span.setAttribute("aria-label",alttext); if (!span.getAttribute("role")) span.setAttribute("role","math"); -// span.setAttribute("tabindex",0); // causes focus outline, so disable for now stack = HTMLCSS.createStack(span); box = HTMLCSS.createBox(stack); // Move font-size from outer span to stack to avoid line separation // problem in strict HTML mode diff --git a/unpacked/jax/output/NativeMML/jax.js b/unpacked/jax/output/NativeMML/jax.js index 3c6f7c289..3d444f745 100644 --- a/unpacked/jax/output/NativeMML/jax.js +++ b/unpacked/jax/output/NativeMML/jax.js @@ -326,6 +326,9 @@ container.onmousedown = EVENT.Mousedown; container.onclick = EVENT.Click; container.ondblclick = EVENT.DblClick; + // Added for keyboard accessible menu. + container.onkeydown = EVENT.Keydown; + container.tabIndex = "0"; if (HUB.Browser.noContextMenu) { container.ontouchstart = TOUCH.start; container.ontouchend = TOUCH.end; diff --git a/unpacked/jax/output/SVG/jax.js b/unpacked/jax/output/SVG/jax.js index 67b6973cc..50f696038 100644 --- a/unpacked/jax/output/SVG/jax.js +++ b/unpacked/jax/output/SVG/jax.js @@ -220,7 +220,9 @@ className:"MathJax_SVG", id:jax.inputID+"-Frame", isMathJax:true, jaxID:this.id, oncontextmenu:EVENT.Menu, onmousedown: EVENT.Mousedown, onmouseover:EVENT.Mouseover, onmouseout:EVENT.Mouseout, onmousemove:EVENT.Mousemove, - onclick:EVENT.Click, ondblclick:EVENT.DblClick + onclick:EVENT.Click, ondblclick:EVENT.DblClick, + // Added for keyboard accessible menu. + onkeydown: EVENT.Keydown, tabIndex: "0" }); if (HUB.Browser.noContextMenu) { span.ontouchstart = TOUCH.start; From 986ee52e8a4c38d0d85f909badf193c41a3a7599 Mon Sep 17 00:00:00 2001 From: zorkow Date: Sat, 29 Aug 2015 01:57:33 +0100 Subject: [PATCH 30/66] Focuses popup windows. --- unpacked/extensions/HelpDialog.js | 7 +++++-- unpacked/extensions/MathMenu.js | 10 ++++++---- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/unpacked/extensions/HelpDialog.js b/unpacked/extensions/HelpDialog.js index 09365fd26..440368281 100644 --- a/unpacked/extensions/HelpDialog.js +++ b/unpacked/extensions/HelpDialog.js @@ -101,7 +101,7 @@ HELP.Post = function () { this.div = MENU.Background(this); var help = HTML.addElement(this.div,"div",{ - id: "MathJax_Help" + id: "MathJax_Help", tabIndex: "0" },LOCALE._("HelpDialog",[ ["b",{style:{fontSize:"120%"}},[["Help","MathJax Help"]]], ["div",{id: "MathJax_HelpContent"},[ @@ -148,10 +148,13 @@ ] ]], ["a",{href:"http://www.mathjax.org/"},["www.mathjax.org"]], - ["span",{id: "MathJax_HelpClose", onclick: HELP.Remove}, + ["span",{id: "MathJax_HelpClose", onclick: HELP.Remove, + onkeydown: HELP.Remove, tabIndex: '0', + 'aria-label': 'Close', 'aria-describedby': 'Close window'}, [["span",{},["\u00D7"]]] ] ])); + help.focus(); LOCALE.setCSS(help); var doc = (document.documentElement||{}); var H = window.innerHeight || doc.clientHeight || doc.scrollHeight || 0; diff --git a/unpacked/extensions/MathMenu.js b/unpacked/extensions/MathMenu.js index 5ac325c1b..01ff4e7ef 100644 --- a/unpacked/extensions/MathMenu.js +++ b/unpacked/extensions/MathMenu.js @@ -477,7 +477,6 @@ /* * Keyboard navigation of menu. */ - active: null, // The currently focused item. There can only be one! HTML! posted: false, // Is a menu open? GetNode: function(jax) { @@ -746,7 +745,6 @@ }, Label: function (def,menu) {return [this.Name()]}, - //TODO: Focus the popup. Mouseup: function (event,menu) { if (!this.disabled) { this.Remove(event,menu); @@ -973,7 +971,7 @@ ]]); MENU.About.div = MENU.Background(MENU.About); var about = HTML.addElement(MENU.About.div,"div",{ - id: "MathJax_About" + id: "MathJax_About", tabIndex:0 },[ ["b",{style:{fontSize:"120%"}},["MathJax"]]," v"+MathJax.version,["br"], _(font.replace(/ /g,""),"using "+font),["br"],["br"], @@ -983,9 +981,13 @@ "background-color":"#E4E4E4", padding:".4em .6em", border:"1px inset" }},jax],["br"],["br"], ["a",{href:"http://www.mathjax.org/"},["www.mathjax.org"]], - ["span",{className:"MathJax_MenuClose",id:"MathJax_AboutClose",onclick:MENU.About.Remove}, + ["span",{className:"MathJax_MenuClose",id:"MathJax_AboutClose", + onclick:MENU.About.Remove, + onkeydown:MENU.About.Remove, tabIndex:0, + 'aria-label': "Close", 'aria-describedby': "Close window"}, [["span",{},"\u00D7"]]] ]); + about.focus(); MathJax.Localization.setCSS(about); var doc = (document.documentElement||{}); var H = window.innerHeight || doc.clientHeight || doc.scrollHeight || 0; From 576d6b2132f058261f42134ca183db725f89ece7 Mon Sep 17 00:00:00 2001 From: zorkow Date: Sat, 29 Aug 2015 02:11:15 +0100 Subject: [PATCH 31/66] Cleans event function. --- unpacked/extensions/MathEvents.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/unpacked/extensions/MathEvents.js b/unpacked/extensions/MathEvents.js index d122f66af..8356c083f 100644 --- a/unpacked/extensions/MathEvents.js +++ b/unpacked/extensions/MathEvents.js @@ -136,10 +136,13 @@ // Call the output jax's event handler or the zoom handler // Handler: function (event,type,math) { + console.log(type); if (AJAX.loadingMathMenu) {return EVENT.False(event)} var jax = OUTPUT[math.jaxID]; + console.log(jax); if (!event) {event = window.event} event.isContextMenu = (type === "ContextMenu"); + console.log(jax[type]); if (jax[type]) {return jax[type](event,math)} if (EXTENSION.MathZoom) {return EXTENSION.MathZoom.HandleEvent(event,type,math)} }, @@ -160,12 +163,8 @@ // // Keydown event handler. Should only fire on Space key. // - // TODO: (sorge) Fit this into the Handler function. - // Keydown: function (event, math) { - var jax = OUTPUT[this.jaxID]; if (event.keyCode === EVENT.KEY.SPACE) { - // TODO: Put the focus on the first element. EVENT.ContextMenu(event, this); }; }, From fbb70fb658cb2152d2ece8e9581d51ac94edf35c Mon Sep 17 00:00:00 2001 From: zorkow Date: Sun, 30 Aug 2015 21:45:10 +0100 Subject: [PATCH 32/66] Removes logging and prototype addition. --- unpacked/extensions/MathEvents.js | 3 --- unpacked/extensions/MathMenu.js | 28 ++++++++++++---------------- 2 files changed, 12 insertions(+), 19 deletions(-) diff --git a/unpacked/extensions/MathEvents.js b/unpacked/extensions/MathEvents.js index 8356c083f..384362c98 100644 --- a/unpacked/extensions/MathEvents.js +++ b/unpacked/extensions/MathEvents.js @@ -136,13 +136,10 @@ // Call the output jax's event handler or the zoom handler // Handler: function (event,type,math) { - console.log(type); if (AJAX.loadingMathMenu) {return EVENT.False(event)} var jax = OUTPUT[math.jaxID]; - console.log(jax); if (!event) {event = window.event} event.isContextMenu = (type === "ContextMenu"); - console.log(jax[type]); if (jax[type]) {return jax[type](event,math)} if (EXTENSION.MathZoom) {return EXTENSION.MathZoom.HandleEvent(event,type,math)} }, diff --git a/unpacked/extensions/MathMenu.js b/unpacked/extensions/MathMenu.js index 01ff4e7ef..c1cde7ef2 100644 --- a/unpacked/extensions/MathMenu.js +++ b/unpacked/extensions/MathMenu.js @@ -527,7 +527,7 @@ if (len === 0) { return; } - var next = jaxs[MENU.Mod(move(jaxs.indexOf(MENU.CurrentNode())), len)]; + var next = jaxs[MENU.Mod(move(MENU.IndexOf(jaxs, MENU.CurrentNode())), len)]; if (next === MENU.CurrentNode()) { return; } @@ -547,7 +547,15 @@ Mod: function(a, n) { return ((a % n) + n) % n; }, - + IndexOf: (Array.prototype.indexOf ? + function (A, item, start) {return A.indexOf(item, start);} : + function (A, item, start) { + for (var i = (start || 0), j = A.length; i < j; i++) { + if (item === A[i]) return i; + } + return -1; + }), + saveCookie: function () {HTML.Cookie.Set("menu",this.cookie)}, getCookie: function () {this.cookie = HTML.Cookie.Get("menu")} @@ -676,7 +684,7 @@ items.push(it); } } - var index = items.indexOf(this); + var index = MENU.IndexOf(items, this); if (index === -1) { return; } @@ -1510,19 +1518,7 @@ HUB.Register.StartupHook("End Config",{}), // wait until config is complete ["Styles",AJAX,CONFIG.styles], ["Post",HUB.Startup.signal,"MathMenu Ready"], - ["loadComplete",AJAX,"[MathJax]/extensions/MathMenu.js"], - function() { - if (!Array.prototype.indexOf) { - Array.prototype.indexOf = function(item, start) { - for (var i = (start || 0), j = this.length; i < j; i++) { - if (item === this[i]) { - return i; - } - } - return -1; - }; - } - } + ["loadComplete",AJAX,"[MathJax]/extensions/MathMenu.js"] ); })(MathJax.Hub,MathJax.HTML,MathJax.Ajax,MathJax.CallBack,MathJax.OutputJax); From f73d5f0094cceb5b76150c0d9268edf4c931a07e Mon Sep 17 00:00:00 2001 From: zorkow Date: Mon, 31 Aug 2015 19:50:55 +0100 Subject: [PATCH 33/66] Caches focused node. --- unpacked/extensions/MathMenu.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/unpacked/extensions/MathMenu.js b/unpacked/extensions/MathMenu.js index c1cde7ef2..aef79a944 100644 --- a/unpacked/extensions/MathMenu.js +++ b/unpacked/extensions/MathMenu.js @@ -478,6 +478,7 @@ * Keyboard navigation of menu. */ posted: false, // Is a menu open? + active: null, // The focused in HTML node in the menu. GetNode: function(jax) { var node = document.getElementById(jax.inputID + '-Frame'); @@ -495,7 +496,11 @@ return nodes; }, ActiveNode: function() { - return document.activeElement; + return MENU.active; + }, + FocusNode: function(node) { + MENU.active = node; + node.focus(); }, // // Focus is a global affair, since we only ever want a single focused item. @@ -503,7 +508,7 @@ Focus: function(menu) { !MENU.posted ? MENU.Activate(menu) : MENU.ActiveNode().tabIndex = -1; menu.tabIndex = 0; - menu.focus(); + MENU.FocusNode(menu); }, Activate: function(event, menu) { var jaxs = MENU.AllNodes(); @@ -518,7 +523,7 @@ for (var j = 0, jax; jax = jaxs[j]; j++) { jax.tabIndex = 0; } - MENU.CurrentNode().focus(); + MENU.FocusNode(MENU.CurrentNode()); MENU.posted = false; }, MoveHorizontal: function(event, menu, move) { From 0895c284d3ed3d9b15ad8d694ed9bca0a5ece8b8 Mon Sep 17 00:00:00 2001 From: zorkow Date: Mon, 31 Aug 2015 19:56:07 +0100 Subject: [PATCH 34/66] Passes through unused key events. --- unpacked/extensions/MathMenu.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/unpacked/extensions/MathMenu.js b/unpacked/extensions/MathMenu.js index aef79a944..8bf93ff7c 100644 --- a/unpacked/extensions/MathMenu.js +++ b/unpacked/extensions/MathMenu.js @@ -193,8 +193,13 @@ }, ".MathJax_MenuClose:hover span": { "background-color":"#CCC!important" + }, + ".MathJax:focus": { + display:"inline-block", + outline:"none", + border:"1px dotted", + margin:"-1px" } - } }); @@ -236,6 +241,7 @@ this.Space(event, menu); break; default: + return; break; } return FALSE(event); From 2143219d9ba2263f93a04e0311b8b4b218895321 Mon Sep 17 00:00:00 2001 From: zorkow Date: Mon, 31 Aug 2015 21:08:27 +0100 Subject: [PATCH 35/66] Adds navigation role to main menu. --- unpacked/extensions/MathMenu.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/unpacked/extensions/MathMenu.js b/unpacked/extensions/MathMenu.js index 8bf93ff7c..feea93a0b 100644 --- a/unpacked/extensions/MathMenu.js +++ b/unpacked/extensions/MathMenu.js @@ -285,7 +285,8 @@ var menu = HTML.Element("div",{ onmouseup: MENU.Mouseup, ondblclick: FALSE, ondragstart: FALSE, onselectstart: FALSE, oncontextmenu: FALSE, - menuItem: this, className: "MathJax_Menu", onkeydown: MENU.Keydown + menuItem: this, className: "MathJax_Menu", onkeydown: MENU.Keydown, + role: "navigation" }); if (!forceLTR) {MathJax.Localization.setCSS(menu)} @@ -412,8 +413,6 @@ config: CONFIG, - div: null, // the DOM elements for the menu and submenus - Remove: function (event) {return MENU.Event(event,this,"Remove")}, Mouseover: function (event) {return MENU.Event(event,this,"Mouseover")}, Mouseout: function (event) {return MENU.Event(event,this,"Mouseout")}, @@ -449,7 +448,8 @@ }, Background: function (menu) { - var div = HTML.addElement(document.body,"div",{style:this.BGSTYLE, id:"MathJax_MenuFrame"}, + var div = HTML.addElement(document.body,"div", + {style:this.BGSTYLE, id:"MathJax_MenuFrame"}, [["div",{style: this.BGSTYLE, menuItem: menu, onmousedown: this.Remove}]]); var bg = div.firstChild; if (MENU.msieBackgroundBug) { @@ -1115,6 +1115,7 @@ W = Math.max(100,Math.min(Math.floor(.5*screen.width),table.offsetWidth+W+25)); H = Math.max(40,Math.min(Math.floor(.5*screen.height),table.offsetHeight+H+25)); if (MENU.prototype.msieHeightBug) {H += 35}; // for title bar in XP + console.log(W + ' ' + H); w.resizeTo(W,H); var X; try {X = event.screenX} catch (e) {}; // IE8 throws an error accessing screenX if (event && X != null) { From ad8a8704d48e5326dcaf3e25397777b16df92467 Mon Sep 17 00:00:00 2001 From: zorkow Date: Mon, 31 Aug 2015 21:50:27 +0100 Subject: [PATCH 36/66] Fixes scroll position and involuntary mouse interaction. --- unpacked/extensions/MathMenu.js | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/unpacked/extensions/MathMenu.js b/unpacked/extensions/MathMenu.js index feea93a0b..ed1cf7aa1 100644 --- a/unpacked/extensions/MathMenu.js +++ b/unpacked/extensions/MathMenu.js @@ -341,9 +341,17 @@ } menu.style.left = x+"px"; menu.style.top = y+"px"; - if (document.selection && document.selection.empty) {document.selection.empty()} + + // Focusing while keeping the scroll position. + var oldX = window.pageXOffset || document.documentElement.scrollLeft; + var oldY = window.pageYOffset || document.documentElement.scrollTop; MENU.Focus(menu); + if (event.type === 'keydown') { + MENU.skipMouseoverFromKey = true; + setTimeout(function() {delete MENU.skipMouseoverFromKey;}, CONFIG.delay); + } + window.scrollTo(oldX, oldY); return FALSE(event); }, @@ -429,6 +437,10 @@ }, Event: function (event,menu,type,force) { if (MENU.skipMouseover && type === "Mouseover" && !force) {return FALSE(event)} + if (MENU.skipMouseoverFromKey && type === "Mouseover") { + delete MENU.skipMouseoverFromKey; + return FALSE(event); + } if (MENU.skipUp) { if (type.match(/Mouseup|Touchend/)) {delete MENU.skipUp; return FALSE(event)} if (type === "Touchstart" || @@ -797,7 +809,8 @@ }, Timer: function (event,menu) { this.ClearTimer(); - event = {clientX: event.clientX, clientY: event.clientY}; // MSIE can't pass the event below + event = {type: event.type, + clientX: event.clientX, clientY: event.clientY}; // MSIE can't pass the event below this.timer = setTimeout(CALLBACK(["Mouseup",this,event,menu]),CONFIG.delay); }, ClearTimer: function() { @@ -1115,7 +1128,6 @@ W = Math.max(100,Math.min(Math.floor(.5*screen.width),table.offsetWidth+W+25)); H = Math.max(40,Math.min(Math.floor(.5*screen.height),table.offsetHeight+H+25)); if (MENU.prototype.msieHeightBug) {H += 35}; // for title bar in XP - console.log(W + ' ' + H); w.resizeTo(W,H); var X; try {X = event.screenX} catch (e) {}; // IE8 throws an error accessing screenX if (event && X != null) { From c890d8183dd6cba96efb1f15b760e39861711f16 Mon Sep 17 00:00:00 2001 From: zorkow Date: Tue, 1 Sep 2015 01:29:55 +0100 Subject: [PATCH 37/66] Removes occurrence of elementsbyclassname. --- unpacked/extensions/MathMenu.js | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/unpacked/extensions/MathMenu.js b/unpacked/extensions/MathMenu.js index ed1cf7aa1..d879b6364 100644 --- a/unpacked/extensions/MathMenu.js +++ b/unpacked/extensions/MathMenu.js @@ -732,15 +732,21 @@ this.MoveHorizontal(event, item, MENU.Left, this.isRTL()); }, MoveHorizontal: function(event, item, move, rtl) { - if (ITEM.GetMenuNode(item).menuItem === MENU.menu) { + var menuNode = ITEM.GetMenuNode(item); + if (menuNode.menuItem === MENU.menu) { move(event, item); } if (rtl) { return; } this.Deactivate(item); - var sibling = item.parentNode.previousSibling; - var actives = sibling.getElementsByClassName('MathJax_MenuActive'); - if (actives.length > 0) { - MENU.Focus(actives[0]); + var parentNodes = menuNode.previousSibling.childNodes; + var length = parentNodes.length; + while (length--) { + var parent = parentNodes[length]; + if (parent.menuItem.submenu && + parent.menuItem.submenu === menuNode.menuItem) { + MENU.Focus(parent); + break; + } } this.RemoveSubmenus(item); }, From faeae3e105c8ba550dbf5a22d6c16360116cac4b Mon Sep 17 00:00:00 2001 From: zorkow Date: Tue, 1 Sep 2015 01:58:38 +0100 Subject: [PATCH 38/66] Fixes interference problems with submenu timer. --- unpacked/extensions/MathMenu.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/unpacked/extensions/MathMenu.js b/unpacked/extensions/MathMenu.js index d879b6364..273aaa403 100644 --- a/unpacked/extensions/MathMenu.js +++ b/unpacked/extensions/MathMenu.js @@ -864,6 +864,10 @@ } MENU.Focus(menu); }, + MoveVertical: function(event, item, move) { + this.ClearTimer(); + this.SUPER(arguments).MoveVertical.apply(this, arguments); + }, MoveHorizontal: function(event, menu, move, rtl) { if (this.disabled) { return; From f73453512b9c6785a4df18fae8bc04360d18b69b Mon Sep 17 00:00:00 2001 From: zorkow Date: Tue, 1 Sep 2015 02:21:06 +0100 Subject: [PATCH 39/66] Hides math element walking behind shift. --- unpacked/extensions/MathMenu.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/unpacked/extensions/MathMenu.js b/unpacked/extensions/MathMenu.js index 273aaa403..47fe8b225 100644 --- a/unpacked/extensions/MathMenu.js +++ b/unpacked/extensions/MathMenu.js @@ -545,6 +545,7 @@ MENU.posted = false; }, MoveHorizontal: function(event, menu, move) { + if (!event.shiftKey) { return; } var jaxs = MENU.AllNodes(); var len = jaxs.length; if (len === 0) { @@ -734,6 +735,7 @@ MoveHorizontal: function(event, item, move, rtl) { var menuNode = ITEM.GetMenuNode(item); if (menuNode.menuItem === MENU.menu) { + if (!event.shiftKey) { return; } move(event, item); } if (rtl) { return; } @@ -869,13 +871,13 @@ this.SUPER(arguments).MoveVertical.apply(this, arguments); }, MoveHorizontal: function(event, menu, move, rtl) { - if (this.disabled) { - return; - } if (!rtl) { this.SUPER(arguments).MoveHorizontal.apply(this, arguments); return; } + if (this.disabled) { + return; + } var submenuNodes = ITEM.GetMenuNode(menu).nextSibling.childNodes; if (submenuNodes.length > 0) { this.submenu.items[0].Activate(event, submenuNodes[0]); From 6cc308b5d0ff98704cb5e127ba42dbddfd23cf36 Mon Sep 17 00:00:00 2001 From: zorkow Date: Tue, 1 Sep 2015 02:40:41 +0100 Subject: [PATCH 40/66] Enables to untrigger menu with space. --- unpacked/extensions/MathMenu.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/unpacked/extensions/MathMenu.js b/unpacked/extensions/MathMenu.js index 47fe8b225..41a2d47f2 100644 --- a/unpacked/extensions/MathMenu.js +++ b/unpacked/extensions/MathMenu.js @@ -416,6 +416,9 @@ Down: function(event, menu) { var node = menu.firstChild; node.menuItem.Activate(event, node); + }, + Space: function(event, menu) { + this.Remove(event, menu); } },{ From afdd671999f9fb778aaa45a1a9bf045758797459 Mon Sep 17 00:00:00 2001 From: zorkow Date: Tue, 1 Sep 2015 03:46:07 +0100 Subject: [PATCH 41/66] Proper keyhandling for popup windows. --- unpacked/extensions/HelpDialog.js | 11 +++++++++-- unpacked/extensions/MathMenu.js | 11 +++++++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/unpacked/extensions/HelpDialog.js b/unpacked/extensions/HelpDialog.js index 440368281..3a195d90c 100644 --- a/unpacked/extensions/HelpDialog.js +++ b/unpacked/extensions/HelpDialog.js @@ -101,7 +101,7 @@ HELP.Post = function () { this.div = MENU.Background(this); var help = HTML.addElement(this.div,"div",{ - id: "MathJax_Help", tabIndex: "0" + id: "MathJax_Help", tabIndex: 0, onkeydown: HELP.Keydown },LOCALE._("HelpDialog",[ ["b",{style:{fontSize:"120%"}},[["Help","MathJax Help"]]], ["div",{id: "MathJax_HelpContent"},[ @@ -149,7 +149,7 @@ ]], ["a",{href:"http://www.mathjax.org/"},["www.mathjax.org"]], ["span",{id: "MathJax_HelpClose", onclick: HELP.Remove, - onkeydown: HELP.Remove, tabIndex: '0', + onkeydown: HELP.Keydown, tabIndex: 0, 'aria-label': 'Close', 'aria-describedby': 'Close window'}, [["span",{},["\u00D7"]]] ] @@ -170,6 +170,13 @@ HELP.Remove = function (event) { if (HELP.div) {document.body.removeChild(HELP.div); delete HELP.div} }; + HELP.Keydown = function(event) { + if (event.keyCode === KEY.ESCAPE || + (this.id === 'MathJax_HelpClose' && + (event.keyCode === KEY.SPACE || event.keyCode === KEY.Return))) { + HELP.Remove(event); + } + }, MathJax.Callback.Queue( HUB.Register.StartupHook("End Config",{}), // wait until config is complete diff --git a/unpacked/extensions/MathMenu.js b/unpacked/extensions/MathMenu.js index 41a2d47f2..e3db9b749 100644 --- a/unpacked/extensions/MathMenu.js +++ b/unpacked/extensions/MathMenu.js @@ -1018,7 +1018,7 @@ ]]); MENU.About.div = MENU.Background(MENU.About); var about = HTML.addElement(MENU.About.div,"div",{ - id: "MathJax_About", tabIndex:0 + id: "MathJax_About", tabIndex: 0, onkeydown: MENU.About.Keydown },[ ["b",{style:{fontSize:"120%"}},["MathJax"]]," v"+MathJax.version,["br"], _(font.replace(/ /g,""),"using "+font),["br"],["br"], @@ -1030,7 +1030,7 @@ ["a",{href:"http://www.mathjax.org/"},["www.mathjax.org"]], ["span",{className:"MathJax_MenuClose",id:"MathJax_AboutClose", onclick:MENU.About.Remove, - onkeydown:MENU.About.Remove, tabIndex:0, + onkeydown: MENU.About.Keydown, tabIndex: 0, 'aria-label': "Close", 'aria-describedby': "Close window"}, [["span",{},"\u00D7"]]] ]); @@ -1050,6 +1050,13 @@ MENU.About.Remove = function (event) { if (MENU.About.div) {document.body.removeChild(MENU.About.div); delete MENU.About.div} }; + MENU.About.Keydown = function(event) { + if (event.keyCode === KEY.ESCAPE || + (this.id === 'MathJax_AboutClose' && + (event.keyCode === KEY.SPACE || event.keyCode === KEY.Return))) { + MENU.About.Remove(event); + } + }, MENU.About.GetJax = function (jax,JAX,type,noTypeCheck) { var info = []; for (var id in JAX) {if (JAX.hasOwnProperty(id) && JAX[id]) { From 516874b50c9e86b7534f655cf4b356b72c0e6fac Mon Sep 17 00:00:00 2001 From: zorkow Date: Tue, 1 Sep 2015 18:52:45 +0100 Subject: [PATCH 42/66] Corrects keys and focusing on popup boxes. --- unpacked/extensions/HelpDialog.js | 11 +++++++++-- unpacked/extensions/MathMenu.js | 5 +++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/unpacked/extensions/HelpDialog.js b/unpacked/extensions/HelpDialog.js index 3a195d90c..07a04f0a3 100644 --- a/unpacked/extensions/HelpDialog.js +++ b/unpacked/extensions/HelpDialog.js @@ -29,7 +29,13 @@ var STIXURL = "http://www.stixfonts.org/"; var MENU = MathJax.Menu; + var FALSE, KEY; + HUB.Register.StartupHook("MathEvents Ready",function () { + FALSE = MathJax.Extension.MathEvents.Event.False; + KEY = MathJax.Extension.MathEvents.Event.KEY; + }); + var CONFIG = HUB.CombineConfig("HelpDialog",{ styles: { @@ -104,7 +110,7 @@ id: "MathJax_Help", tabIndex: 0, onkeydown: HELP.Keydown },LOCALE._("HelpDialog",[ ["b",{style:{fontSize:"120%"}},[["Help","MathJax Help"]]], - ["div",{id: "MathJax_HelpContent"},[ + ["div",{id: "MathJax_HelpContent", tabIndex: 0},[ ["p",{},[["MathJax", "*MathJax* is a JavaScript library that allows page authors to include " + "mathematics within their web pages. As a reader, you don't need to do " + @@ -173,8 +179,9 @@ HELP.Keydown = function(event) { if (event.keyCode === KEY.ESCAPE || (this.id === 'MathJax_HelpClose' && - (event.keyCode === KEY.SPACE || event.keyCode === KEY.Return))) { + (event.keyCode === KEY.SPACE || event.keyCode === KEY.RETURN))) { HELP.Remove(event); + FALSE(event); } }, diff --git a/unpacked/extensions/MathMenu.js b/unpacked/extensions/MathMenu.js index e52a55134..5f9a832d1 100644 --- a/unpacked/extensions/MathMenu.js +++ b/unpacked/extensions/MathMenu.js @@ -1026,7 +1026,7 @@ display:"inline-block", "text-align":"left", "font-size":"80%", "max-height":"20em", overflow:"auto", "background-color":"#E4E4E4", padding:".4em .6em", border:"1px inset" - }},jax],["br"],["br"], + }, tabIndex: 0},jax],["br"],["br"], ["a",{href:"http://www.mathjax.org/"},["www.mathjax.org"]], ["span",{className:"MathJax_MenuClose",id:"MathJax_AboutClose", onclick:MENU.About.Remove, @@ -1053,8 +1053,9 @@ MENU.About.Keydown = function(event) { if (event.keyCode === KEY.ESCAPE || (this.id === 'MathJax_AboutClose' && - (event.keyCode === KEY.SPACE || event.keyCode === KEY.Return))) { + (event.keyCode === KEY.SPACE || event.keyCode === KEY.RETURN))) { MENU.About.Remove(event); + FALSE(event); } }, MENU.About.GetJax = function (jax,JAX,type,noTypeCheck) { From db2869a2d30c782215a7a10eb74f795addc0fa6e Mon Sep 17 00:00:00 2001 From: zorkow Date: Tue, 1 Sep 2015 19:08:08 +0100 Subject: [PATCH 43/66] Increase in minimum width of source window to fix problem on Chrome. --- unpacked/extensions/MathMenu.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unpacked/extensions/MathMenu.js b/unpacked/extensions/MathMenu.js index 5f9a832d1..f01fec1df 100644 --- a/unpacked/extensions/MathMenu.js +++ b/unpacked/extensions/MathMenu.js @@ -1148,7 +1148,7 @@ var table = w.document.body.firstChild; setTimeout(function () { var H = (w.outerHeight-w.innerHeight)||30, W = (w.outerWidth-w.innerWidth)||30, x, y; - W = Math.max(100,Math.min(Math.floor(.5*screen.width),table.offsetWidth+W+25)); + W = Math.max(140,Math.min(Math.floor(.5*screen.width),table.offsetWidth+W+25)); H = Math.max(40,Math.min(Math.floor(.5*screen.height),table.offsetHeight+H+25)); if (MENU.prototype.msieHeightBug) {H += 35}; // for title bar in XP w.resizeTo(W,H); From 7054f376773e9e4ef197a082eab8d3b37d35531e Mon Sep 17 00:00:00 2001 From: zorkow Date: Tue, 1 Sep 2015 19:34:50 +0100 Subject: [PATCH 44/66] Integrates and moves improved CSS for outline. --- unpacked/extensions/MathMenu.js | 6 ------ unpacked/jax/output/HTML-CSS/jax.js | 18 +++++++++++++++++- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/unpacked/extensions/MathMenu.js b/unpacked/extensions/MathMenu.js index f01fec1df..7e67836b7 100644 --- a/unpacked/extensions/MathMenu.js +++ b/unpacked/extensions/MathMenu.js @@ -193,12 +193,6 @@ }, ".MathJax_MenuClose:hover span": { "background-color":"#CCC!important" - }, - ".MathJax:focus": { - display:"inline-block", - outline:"none", - border:"1px dotted", - margin:"-1px" } } }); diff --git a/unpacked/jax/output/HTML-CSS/jax.js b/unpacked/jax/output/HTML-CSS/jax.js index 9188061cf..5dec3a2d0 100644 --- a/unpacked/jax/output/HTML-CSS/jax.js +++ b/unpacked/jax/output/HTML-CSS/jax.js @@ -344,7 +344,23 @@ "#MathJax_Tooltip *": { filter: "none", opacity:1, background:"transparent" // for IE }, - + + // Focus elements for keyboard tabbing. + ".MathJax:focus": ( + (MathJax.Hub.Browser.isSafari || MathJax.Hub.Browser.isChrome) ? { + display:"inline-block", + outline:"none", + margin:"-3px", + padding:"3px", + "-webkit-box-shadow": "0px 0px 5px #345, inset 0px 0px 5px #345", + "box-shadow": "0px 0px 5px #345, inset 0px 0px 5px #345" + } : { + display:"inline-block", + outline:"none", + border:"1px dotted", + margin:"-1px" + }), + // // Used for testing web fonts against the default font used while // web fonts are loading From 56deff3a7ddc67ef02876e564cf332191b90ad21 Mon Sep 17 00:00:00 2001 From: zorkow Date: Tue, 1 Sep 2015 19:42:18 +0100 Subject: [PATCH 45/66] Resets focus on last Maths element when closing popup windows. --- unpacked/extensions/HelpDialog.js | 1 + unpacked/extensions/MathMenu.js | 1 + 2 files changed, 2 insertions(+) diff --git a/unpacked/extensions/HelpDialog.js b/unpacked/extensions/HelpDialog.js index 07a04f0a3..479e8b9f6 100644 --- a/unpacked/extensions/HelpDialog.js +++ b/unpacked/extensions/HelpDialog.js @@ -181,6 +181,7 @@ (this.id === 'MathJax_HelpClose' && (event.keyCode === KEY.SPACE || event.keyCode === KEY.RETURN))) { HELP.Remove(event); + MENU.CurrentNode().focus(); FALSE(event); } }, diff --git a/unpacked/extensions/MathMenu.js b/unpacked/extensions/MathMenu.js index 7e67836b7..fbdeed848 100644 --- a/unpacked/extensions/MathMenu.js +++ b/unpacked/extensions/MathMenu.js @@ -1049,6 +1049,7 @@ (this.id === 'MathJax_AboutClose' && (event.keyCode === KEY.SPACE || event.keyCode === KEY.RETURN))) { MENU.About.Remove(event); + MENU.CurrentNode().focus(); FALSE(event); } }, From a7e4c1a14ce2ef769c5332e8b77eafb40c1a8844 Mon Sep 17 00:00:00 2001 From: zorkow Date: Tue, 1 Sep 2015 21:05:49 +0100 Subject: [PATCH 46/66] Adds final submenu closing and opening on left/right key. --- unpacked/extensions/MathMenu.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/unpacked/extensions/MathMenu.js b/unpacked/extensions/MathMenu.js index fbdeed848..4531b814e 100644 --- a/unpacked/extensions/MathMenu.js +++ b/unpacked/extensions/MathMenu.js @@ -731,12 +731,13 @@ }, MoveHorizontal: function(event, item, move, rtl) { var menuNode = ITEM.GetMenuNode(item); - if (menuNode.menuItem === MENU.menu) { - if (!event.shiftKey) { return; } + if (menuNode.menuItem === MENU.menu && event.shiftKey) { move(event, item); } if (rtl) { return; } - this.Deactivate(item); + if (menuNode.menuItem !== MENU.menu && event.shiftKey) { + this.Deactivate(item); + } var parentNodes = menuNode.previousSibling.childNodes; var length = parentNodes.length; while (length--) { @@ -875,6 +876,10 @@ if (this.disabled) { return; } + if (!this.submenu.posted) { + this.Activate(event, menu); + return; + } var submenuNodes = ITEM.GetMenuNode(menu).nextSibling.childNodes; if (submenuNodes.length > 0) { this.submenu.items[0].Activate(event, submenuNodes[0]); From 7867707d5bf616774bb6d42e15eb100ba3a86011 Mon Sep 17 00:00:00 2001 From: zorkow Date: Tue, 1 Sep 2015 21:16:07 +0100 Subject: [PATCH 47/66] Fixes deactivation problem in last submenu. --- unpacked/extensions/MathMenu.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unpacked/extensions/MathMenu.js b/unpacked/extensions/MathMenu.js index 4531b814e..d1aee27ae 100644 --- a/unpacked/extensions/MathMenu.js +++ b/unpacked/extensions/MathMenu.js @@ -735,7 +735,7 @@ move(event, item); } if (rtl) { return; } - if (menuNode.menuItem !== MENU.menu && event.shiftKey) { + if (menuNode.menuItem !== MENU.menu) { this.Deactivate(item); } var parentNodes = menuNode.previousSibling.childNodes; From 0e1a33263ff4d95e45bf6bc0fe340a659a4138fb Mon Sep 17 00:00:00 2001 From: zorkow Date: Tue, 1 Sep 2015 21:16:29 +0100 Subject: [PATCH 48/66] Adds to keyboard driven menus to FastHTML. --- unpacked/jax/output/FastHTML/jax.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/unpacked/jax/output/FastHTML/jax.js b/unpacked/jax/output/FastHTML/jax.js index e02122a3c..a9767cede 100644 --- a/unpacked/jax/output/FastHTML/jax.js +++ b/unpacked/jax/output/FastHTML/jax.js @@ -197,7 +197,9 @@ className:"MathJax_FHTML", id:jax.inputID+"-Frame", isMathJax:true, jaxID:this.id, oncontextmenu:EVENT.Menu, onmousedown: EVENT.Mousedown, onmouseover:EVENT.Mouseover, onmouseout:EVENT.Mouseout, onmousemove:EVENT.Mousemove, - onclick:EVENT.Click, ondblclick:EVENT.DblClick + onclick:EVENT.Click, ondblclick:EVENT.DblClick, + // Added for keyboard accessible menu. + onkeydown: EVENT.Keydown, tabIndex: "0" }); if (HUB.Browser.noContextMenu) { span.ontouchstart = TOUCH.start; From 0922aa2ebc7403e397340f00c364ec17e7dbf778 Mon Sep 17 00:00:00 2001 From: zorkow Date: Tue, 1 Sep 2015 21:27:25 +0100 Subject: [PATCH 49/66] Moves keyboard menu to centroid. --- unpacked/extensions/MathMenu.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/unpacked/extensions/MathMenu.js b/unpacked/extensions/MathMenu.js index d1aee27ae..19cfa6cd0 100644 --- a/unpacked/extensions/MathMenu.js +++ b/unpacked/extensions/MathMenu.js @@ -306,8 +306,8 @@ var node = MENU.CurrentNode() || event.target; if (!x && !y && node) { var rect = node.getBoundingClientRect(); - x = rect.right; - y = rect.bottom; + x = (rect.right + rect.left) / 2; + y = (rect.bottom + rect.top) / 2; } if (x + menu.offsetWidth > document.body.offsetWidth - this.margin) {x = document.body.offsetWidth - menu.offsetWidth - this.margin} From 74c2b46da5ad46c119e48f474c7250c46d748f30 Mon Sep 17 00:00:00 2001 From: zorkow Date: Tue, 1 Sep 2015 23:12:46 +0100 Subject: [PATCH 50/66] Consistently places menu on maths elements by adding scroll offset. --- unpacked/extensions/MathMenu.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/unpacked/extensions/MathMenu.js b/unpacked/extensions/MathMenu.js index 19cfa6cd0..712a03aaa 100644 --- a/unpacked/extensions/MathMenu.js +++ b/unpacked/extensions/MathMenu.js @@ -305,9 +305,11 @@ if (!parent) { var node = MENU.CurrentNode() || event.target; if (!x && !y && node) { + var offsetX = window.pageXOffset || document.documentElement.scrollLeft; + var offsetY = window.pageYOffset || document.documentElement.scrollTop; var rect = node.getBoundingClientRect(); - x = (rect.right + rect.left) / 2; - y = (rect.bottom + rect.top) / 2; + x = (rect.right + rect.left) / 2 + offsetX; + y = (rect.bottom + rect.top) / 2 + offsetY; } if (x + menu.offsetWidth > document.body.offsetWidth - this.margin) {x = document.body.offsetWidth - menu.offsetWidth - this.margin} From b81019676fcc47af72ad2379586060d245fa8ad9 Mon Sep 17 00:00:00 2001 From: zorkow Date: Wed, 2 Sep 2015 13:36:00 +0100 Subject: [PATCH 51/66] Fixes focusing on first and last element when moving between Maths elements. --- unpacked/extensions/MathMenu.js | 1 + 1 file changed, 1 insertion(+) diff --git a/unpacked/extensions/MathMenu.js b/unpacked/extensions/MathMenu.js index 712a03aaa..acb64c038 100644 --- a/unpacked/extensions/MathMenu.js +++ b/unpacked/extensions/MathMenu.js @@ -556,6 +556,7 @@ } MENU.menu.Remove(event, menu); MENU.jax = MathJax.Hub.getJaxFor(next); + MENU.FocusNode(next); MENU.menu.Post(null); }, Right: function(event, menu) { From 03c0aac6349effafa26c37017be01df1e4e78861 Mon Sep 17 00:00:00 2001 From: zorkow Date: Wed, 2 Sep 2015 13:52:21 +0100 Subject: [PATCH 52/66] Changed single quotes to double quotes for styling. --- unpacked/extensions/HelpDialog.js | 4 ++-- unpacked/extensions/MathMenu.js | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/unpacked/extensions/HelpDialog.js b/unpacked/extensions/HelpDialog.js index 479e8b9f6..2c16eb1ca 100644 --- a/unpacked/extensions/HelpDialog.js +++ b/unpacked/extensions/HelpDialog.js @@ -156,7 +156,7 @@ ["a",{href:"http://www.mathjax.org/"},["www.mathjax.org"]], ["span",{id: "MathJax_HelpClose", onclick: HELP.Remove, onkeydown: HELP.Keydown, tabIndex: 0, - 'aria-label': 'Close', 'aria-describedby': 'Close window'}, + "aria-label": "Close", "aria-describedby": "Close window"}, [["span",{},["\u00D7"]]] ] ])); @@ -178,7 +178,7 @@ }; HELP.Keydown = function(event) { if (event.keyCode === KEY.ESCAPE || - (this.id === 'MathJax_HelpClose' && + (this.id === "MathJax_HelpClose" && (event.keyCode === KEY.SPACE || event.keyCode === KEY.RETURN))) { HELP.Remove(event); MENU.CurrentNode().focus(); diff --git a/unpacked/extensions/MathMenu.js b/unpacked/extensions/MathMenu.js index acb64c038..5a2d92a3d 100644 --- a/unpacked/extensions/MathMenu.js +++ b/unpacked/extensions/MathMenu.js @@ -343,7 +343,7 @@ var oldX = window.pageXOffset || document.documentElement.scrollLeft; var oldY = window.pageYOffset || document.documentElement.scrollTop; MENU.Focus(menu); - if (event.type === 'keydown') { + if (event.type === "keydown") { MENU.skipMouseoverFromKey = true; setTimeout(function() {delete MENU.skipMouseoverFromKey;}, CONFIG.delay); } @@ -498,7 +498,7 @@ active: null, // The focused in HTML node in the menu. GetNode: function(jax) { - var node = document.getElementById(jax.inputID + '-Frame'); + var node = document.getElementById(jax.inputID + "-Frame"); return node.isMathJax ? node : node.firstChild; }, CurrentNode: function() { @@ -691,7 +691,7 @@ {onmouseover: MENU.Mouseover, onmouseout: MENU.Mouseout, onmousedown: MENU.Mousedown, role: this.role, onkeydown: MENU.Keydown, - 'aria-disabled': !!this.disabled}, + "aria-disabled": !!this.disabled}, def); def = this.SUPER(arguments).Attributes.call(this, def); if (this.disabled) { @@ -1033,7 +1033,7 @@ ["span",{className:"MathJax_MenuClose",id:"MathJax_AboutClose", onclick:MENU.About.Remove, onkeydown: MENU.About.Keydown, tabIndex: 0, - 'aria-label': "Close", 'aria-describedby': "Close window"}, + "aria-label": "Close", "aria-describedby": "Close window"}, [["span",{},"\u00D7"]]] ]); about.focus(); @@ -1054,7 +1054,7 @@ }; MENU.About.Keydown = function(event) { if (event.keyCode === KEY.ESCAPE || - (this.id === 'MathJax_AboutClose' && + (this.id === "MathJax_AboutClose" && (event.keyCode === KEY.SPACE || event.keyCode === KEY.RETURN))) { MENU.About.Remove(event); MENU.CurrentNode().focus(); From 03e761dafebd8d2e1b84b33ef9a129f3f22ab21c Mon Sep 17 00:00:00 2001 From: zorkow Date: Wed, 2 Sep 2015 14:08:50 +0100 Subject: [PATCH 53/66] Makes if/return statements uniform to codebase. --- unpacked/extensions/MathMenu.js | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/unpacked/extensions/MathMenu.js b/unpacked/extensions/MathMenu.js index 5a2d92a3d..82926e338 100644 --- a/unpacked/extensions/MathMenu.js +++ b/unpacked/extensions/MathMenu.js @@ -544,16 +544,12 @@ MENU.posted = false; }, MoveHorizontal: function(event, menu, move) { - if (!event.shiftKey) { return; } + if (!event.shiftKey) return; var jaxs = MENU.AllNodes(); var len = jaxs.length; - if (len === 0) { - return; - } + if (len === 0) return; var next = jaxs[MENU.Mod(move(MENU.IndexOf(jaxs, MENU.CurrentNode())), len)]; - if (next === MENU.CurrentNode()) { - return; - } + if (next === MENU.CurrentNode()) return; MENU.menu.Remove(event, menu); MENU.jax = MathJax.Hub.getJaxFor(next); MENU.FocusNode(next); @@ -709,9 +705,7 @@ } } var index = MENU.IndexOf(items, this); - if (index === -1) { - return; - } + if (index === -1) return; var len = items.length; var children = menuNode.childNodes; do { @@ -737,7 +731,7 @@ if (menuNode.menuItem === MENU.menu && event.shiftKey) { move(event, item); } - if (rtl) { return; } + if (rtl) return; if (menuNode.menuItem !== MENU.menu) { this.Deactivate(item); } @@ -876,9 +870,7 @@ this.SUPER(arguments).MoveHorizontal.apply(this, arguments); return; } - if (this.disabled) { - return; - } + if (this.disabled) return; if (!this.submenu.posted) { this.Activate(event, menu); return; From a09993d75a6fa8933b0dc215d421823a67fbcbd2 Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Fri, 11 Sep 2015 09:50:53 -0400 Subject: [PATCH 54/66] Fix About box to show correct font for CommonHTML, and make it easier to add new output formats later. --- unpacked/extensions/MathMenu.js | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/unpacked/extensions/MathMenu.js b/unpacked/extensions/MathMenu.js index 497fc5594..10b8cbdb0 100644 --- a/unpacked/extensions/MathMenu.js +++ b/unpacked/extensions/MathMenu.js @@ -992,13 +992,8 @@ */ MENU.About = function () { var HTMLCSS = OUTPUT["HTML-CSS"] || {}; - var font = - (HTMLCSS.imgFonts ? "image" : - (HTMLCSS.fontInUse ? - (HTMLCSS.webFonts ? "web" : "local")+" "+HTMLCSS.fontInUse : - (OUTPUT.SVG ? "web SVG" : "generic")) ) + " fonts"; - var format = (!HTMLCSS.webFonts || HTMLCSS.imgFonts ? null : - HTMLCSS.allowWebFonts.replace(/otf/,"woff or otf") + " fonts"); + var font = MENU.About.GetFont(); + var format = MENU.About.GetFormat(); var jax = ["MathJax.js v"+MathJax.fileversion,["br"]]; jax.push(["div",{style:{"border-top":"groove 2px",margin:".25em 0"}}]); MENU.About.GetJax(jax,MathJax.InputJax,["InputJax","%1 Input Jax v%2"]); @@ -1063,6 +1058,20 @@ for (var i = 0, m = info.length; i < m; i++) {jax.push(info[i],["br"])} return jax; }; + MENU.About.GetFont = function () { + var jax = MathJax.Hub.outputJax["jax/mml"][0] || {}; + var font = { + SVG: "web SVG", + CommonHTML: "web TeX", + "HTML-CSS": (jax.imgFonts ? "image" : (jax.webFonts ? "web" : "local")+" "+jax.fontInUse) + }[jax.id] || "generic"; + return font + " fonts"; + }; + MENU.About.GetFormat = function () { + var jax = MathJax.Hub.outputJax["jax/mml"][0] || {}; + if (jax.id !== "HTML-CSS"|| !jax.webFonts || jax.imgFonts) return; + return jax.allowWebFonts.replace(/otf/,"woff or otf") + " fonts"; + }; /* From 3a15f830592f4825f548c91699592da545cd0a5f Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Fri, 11 Sep 2015 10:44:50 -0400 Subject: [PATCH 55/66] Adjust role for SVG output and put aria-label on the SVG element rather than the enclosing span; add role and aria-label to CHTML output. Resolves issue #1192. --- unpacked/jax/output/CommonHTML/jax.js | 3 +++ unpacked/jax/output/SVG/jax.js | 5 ++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/unpacked/jax/output/CommonHTML/jax.js b/unpacked/jax/output/CommonHTML/jax.js index 65fa68910..20420ca51 100644 --- a/unpacked/jax/output/CommonHTML/jax.js +++ b/unpacked/jax/output/CommonHTML/jax.js @@ -1666,6 +1666,9 @@ MML.math.Augment({ toCommonHTML: function (node) { node = this.CHTMLdefaultNode(node); + var alttext = this.Get("alttext"); + if (alttext && !node.getAttribute("aria-label")) node.setAttribute("aria-label",alttext); + if (!node.getAttribute("role")) node.setAttribute("role","math"); if (this.CHTML.pwidth) { node.parentNode.style.width = this.CHTML.pwidth; node.parentNode.style.minWidth = this.CHTML.mwidth; diff --git a/unpacked/jax/output/SVG/jax.js b/unpacked/jax/output/SVG/jax.js index 1718cc829..c273f3a9d 100644 --- a/unpacked/jax/output/SVG/jax.js +++ b/unpacked/jax/output/SVG/jax.js @@ -2100,9 +2100,8 @@ // Add it to the MathJax span // var alttext = this.Get("alttext"); - if (alttext && !svg.element.getAttribute("aria-label")) span.setAttribute("aria-label",alttext); - if (!svg.element.getAttribute("role")) span.setAttribute("role","math"); -// span.setAttribute("tabindex",0); // causes focus outline, so disable for now + if (alttext && !svg.element.getAttribute("aria-label")) svg.element.setAttribute("aria-label",alttext); + if (!svg.element.getAttribute("role")) svg.element.setAttribute("role","img"); span.appendChild(svg.element); svg.element = null; // From 89f15693f7a86b942c5750e3a33922b414c355e9 Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Fri, 11 Sep 2015 12:26:28 -0400 Subject: [PATCH 56/66] Remove debugging log message and timer --- unpacked/extensions/AssistiveMML.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/unpacked/extensions/AssistiveMML.js b/unpacked/extensions/AssistiveMML.js index ca89fd072..59b1c795f 100644 --- a/unpacked/extensions/AssistiveMML.js +++ b/unpacked/extensions/AssistiveMML.js @@ -66,10 +66,7 @@ if (!SETTINGS.assistiveMML) return; var state = { jax: HUB.getAllJax(node), i: 0, - callback: MathJax.Callback(function () { - console.log("MathML time: "+((new Date().getTime())-state.start)); - }), - start: new Date().getTime() + callback: MathJax.Callback({}) }; this.HandleMML(state); return state.callback; From e172b049280b268680fa21b32c6384965f0d67b4 Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Sat, 12 Sep 2015 13:23:29 -0400 Subject: [PATCH 57/66] Use less-aggressive CSS for ltr and inline-block, and do Edge check within the extension. --- unpacked/MathJax.js | 1 - unpacked/extensions/MathML/mml3.js | 13 +++++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/unpacked/MathJax.js b/unpacked/MathJax.js index a8b6dbeb3..30ce40297 100644 --- a/unpacked/MathJax.js +++ b/unpacked/MathJax.js @@ -3090,7 +3090,6 @@ MathJax.Hub.Startup = { isMac: (navigator.platform.substr(0,3) === "Mac"), isPC: (navigator.platform.substr(0,3) === "Win"), isMSIE: ("ActiveXObject" in window && "clipboardData" in window), - isMsEdge: (!!AGENT.match(/Edge\//)), isFirefox: (!!AGENT.match(/Gecko\//) && !AGENT.match(/like Gecko/)), isSafari: (!!AGENT.match(/ (Apple)?WebKit\//) && !AGENT.match(/ like iPhone /) && (!window.chrome || window.chrome.loadTimes == null)), diff --git a/unpacked/extensions/MathML/mml3.js b/unpacked/extensions/MathML/mml3.js index f14e3bff9..27eac324e 100644 --- a/unpacked/extensions/MathML/mml3.js +++ b/unpacked/extensions/MathML/mml3.js @@ -80,7 +80,7 @@ MathJax.Hub.Register.StartupHook("MathML Jax Ready",function () { */ var BROWSER = MathJax.Hub.Browser; var exslt = ''; - if (BROWSER.isMsEdge || BROWSER.isMSIE) { + if (!!navigator.userAgent.match(/ Edge\//) || BROWSER.isMSIE) { exslt = 'urn:schemas-microsoft-com:xslt' } else { exslt = 'http://exslt.org/common'; @@ -767,7 +767,16 @@ MathJax.Hub.Register.StartupHook("MathML Jax Ready",function () { } // Tweak CSS to avoid some browsers rearranging HTML output - MathJax.Ajax.Styles(".MathJax span { direction: ltr !important; display: inline-block !important;}"); + MathJax.Ajax.Styles({ + ".MathJax .mi, .MathJax .mo, .MathJax .mn, .MathJax .mtext": { + direction: "ltr", + display: "inline-block" + }, + ".MathJax .ms, .MathJax .mspace, .MathJax .mglyph": { + direction: "ltr", + display: "inline-block" + } + }); MathJax.Hub.Startup.signal.Post("MathML mml3.js Ready"); }); From 17e02d710c9d700ef7d685ab4241938090690de7 Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Sat, 12 Sep 2015 14:19:37 -0400 Subject: [PATCH 58/66] Fix removal of previously rendered CHTML output (for Rerender, etc) to lok for class rather than node type, now that we switched to all spans again (sigh). --- unpacked/jax/output/CommonHTML/jax.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unpacked/jax/output/CommonHTML/jax.js b/unpacked/jax/output/CommonHTML/jax.js index 20420ca51..eba9c5d22 100644 --- a/unpacked/jax/output/CommonHTML/jax.js +++ b/unpacked/jax/output/CommonHTML/jax.js @@ -360,7 +360,7 @@ // Remove any existing output // prev = script.previousSibling; - if (prev && prev.nodeName.toLowerCase() === "mjx-chtml") + if (prev && prev.className.substr(0,9) === "mjx-chtml") prev.parentNode.removeChild(prev); // // Add the node for the math and mark it as being processed From 0412d8ec7e3d388be6dc726eec3f474bd77070f8 Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Sat, 12 Sep 2015 14:23:35 -0400 Subject: [PATCH 59/66] Fixed CHTML.addElement to be able to create non-span elements (e.g., the needed for href attributes) --- unpacked/jax/output/CommonHTML/jax.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/unpacked/jax/output/CommonHTML/jax.js b/unpacked/jax/output/CommonHTML/jax.js index eba9c5d22..54863d260 100644 --- a/unpacked/jax/output/CommonHTML/jax.js +++ b/unpacked/jax/output/CommonHTML/jax.js @@ -324,8 +324,9 @@ if (type.substr(0,4) === "mjx-") { if (!def) def = {}; if (def.className) def.className = type+" "+def.className; else def.className = type; + type = "span"; } - return this.HTMLElement("span",def,content); + return this.HTMLElement(type,def,content); }, addElement: function (node,type,def,content) { return node.appendChild(this.Element(type,def,content)); From 649b7b2863f74eafd35acdbb4b35a353fa14f200 Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Sat, 12 Sep 2015 15:00:06 -0400 Subject: [PATCH 60/66] Properly handle left-hand space for first script after in CHTML mmultiscripts --- unpacked/jax/output/CommonHTML/autoload/mmultiscripts.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/unpacked/jax/output/CommonHTML/autoload/mmultiscripts.js b/unpacked/jax/output/CommonHTML/autoload/mmultiscripts.js index e412a1c91..f19a15e5d 100644 --- a/unpacked/jax/output/CommonHTML/autoload/mmultiscripts.js +++ b/unpacked/jax/output/CommonHTML/autoload/mmultiscripts.js @@ -182,7 +182,7 @@ MathJax.Hub.Register.StartupHook("CommonHTML Jax Ready",function () { BBOX = state.BBOX[type] = CHTML.BBOX.empty(); if (state.w) { BOX.style.paddingLeft = CHTML.Em(state.w); - BBOX.w = BBOX.r = state.w; + BBOX.w = BBOX.r = state.w; BBOX.x = state.w; } } data.toCommonHTML(BOX); @@ -198,7 +198,7 @@ MathJax.Hub.Register.StartupHook("CommonHTML Jax Ready",function () { // right-justify the scripts, otherwise, left-justify them. // CHTMLpadScript: function (type,w,bbox,state) { - if (!bbox) bbox = {w:0, fake:1}; + if (!bbox) bbox = {w:0, fake:1, rscale:1}; var BBOX = state.BBOX[type], dx = 0, dw = 0; if (BBOX) { if (bbox.rscale*bbox.w < w) { @@ -252,7 +252,7 @@ MathJax.Hub.Register.StartupHook("CommonHTML Jax Ready",function () { CHTMLplaceSubSup: function (sub,sbox,sup,Sbox,x,delta,u,v,s) { sub.style.paddingRight = CHTML.Em(s); sbox.w += s; sup.style.paddingBottom = CHTML.Em(u+v-Sbox.d-sbox.h); - sup.style.paddingLeft = CHTML.Em(delta); + sup.style.paddingLeft = CHTML.Em(delta+(Sbox.x||0)); sup.style.paddingRight = CHTML.Em(s); Sbox.w += s; sup.parentNode.style.verticalAlign = CHTML.Em(-v); this.CHTML.combine(sbox,x,-v); @@ -272,7 +272,7 @@ MathJax.Hub.Register.StartupHook("CommonHTML Jax Ready",function () { CHTMLplacePresubPresup: function (presub,pbox,presup,Pbox,delta,u,v,s) { presub.style.paddingLeft = CHTML.Em(s); presup.style.paddingBottom = CHTML.Em(u+v-Pbox.d-pbox.h); - presup.style.paddingLeft = CHTML.Em(delta+s); + presup.style.paddingLeft = CHTML.Em(delta+s+(Pbox.x||0)); presup.style.paddingRight = CHTML.Em(-delta); presup.parentNode.style.verticalAlign = CHTML.Em(-v); this.CHTML.combine(pbox,s,-v); From f54168eed325f881d6ba304a2c23c8a152cd20ff Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Sat, 12 Sep 2015 15:09:01 -0400 Subject: [PATCH 61/66] Fix spacing for eqnarray environment now that it is handled in AMSarray --- unpacked/extensions/TeX/AMSmath.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/unpacked/extensions/TeX/AMSmath.js b/unpacked/extensions/TeX/AMSmath.js index 545135362..c6d974b21 100644 --- a/unpacked/extensions/TeX/AMSmath.js +++ b/unpacked/extensions/TeX/AMSmath.js @@ -134,14 +134,14 @@ MathJax.Hub.Register.StartupHook("TeX Jax Ready",function () { aligned: ['AlignedAMSArray',null,null,null,'rlrlrlrlrlrl',COLS([0,2,0,2,0,2,0,2,0,2,0]),".5em",'D'], gathered: ['AlignedAMSArray',null,null,null,'c',null,".5em",'D'], - subarray: ['Array',null,null,null,null,COLS([0,0,0,0]),"0.1em",'S',1], + subarray: ['Array',null,null,null,null,COLS([0]),"0.1em",'S',1], smallmatrix: ['Array',null,null,null,'c',COLS([1/3]),".2em",'S',1], 'equation': ['EquationBegin','Equation',true], 'equation*': ['EquationBegin','EquationStar',false], - eqnarray: ['AMSarray',null,true,true, 'rcl',MML.LENGTH.THICKMATHSPACE,".5em"], - 'eqnarray*': ['AMSarray',null,false,true,'rcl',MML.LENGTH.THICKMATHSPACE,".5em"] + eqnarray: ['AMSarray',null,true,true, 'rcl',COLS([0]),".5em"], + 'eqnarray*': ['AMSarray',null,false,true,'rcl',COLS([0]),".5em"] }, delimiter: { From 620e303b1096f4936c9c5c1882c8f70758f82827 Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Sun, 13 Sep 2015 10:57:34 -0400 Subject: [PATCH 62/66] Detect Microsoft Edge, and also set isMobile for Window Phone --- unpacked/MathJax.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/unpacked/MathJax.js b/unpacked/MathJax.js index f81670339..e1a1900bc 100644 --- a/unpacked/MathJax.js +++ b/unpacked/MathJax.js @@ -3092,11 +3092,13 @@ MathJax.Hub.Startup = { isMac: (navigator.platform.substr(0,3) === "Mac"), isPC: (navigator.platform.substr(0,3) === "Win"), isMSIE: ("ActiveXObject" in window && "clipboardData" in window), + isEdge: ("MSGestureEvent" in window && "chrome" in window && + window.chrome.loadTimes == null), isFirefox: (!!AGENT.match(/Gecko\//) && !AGENT.match(/like Gecko/)), isSafari: (!!AGENT.match(/ (Apple)?WebKit\//) && !AGENT.match(/ like iPhone /) && - (!window.chrome || window.chrome.loadTimes == null)), - isChrome: (window.chrome != null && window.chrome.loadTimes != null), - isOpera: (window.opera != null && window.opera.version != null), + (!window.chrome || window.chrome.app == null)), + isChrome: ("chrome" in window && window.chrome.loadTimes != null), + isOpera: ("opera" in window && window.opera.version != null), isKonqueror: ("konqueror" in window && navigator.vendor == "KDE"), versionAtLeast: function (v) { var bv = (this.version).split('.'); v = (new String(v)).split('.'); @@ -3124,7 +3126,7 @@ MathJax.Hub.Startup = { HUB.Browser = HUB.Insert(new String(browser),BROWSERS); var VERSION = new RegExp( ".*(Version/| Trident/.*; rv:)((?:\\d+\\.)+\\d+)|" + // for Safari, Opera10, and IE11+ - ".*("+browser+")"+(browser == "MSIE" ? " " : "/")+"((?:\\d+\\.)*\\d+)|"+ // for one of the main browser + ".*("+browser+")"+(browser == "MSIE" ? " " : "/")+"((?:\\d+\\.)*\\d+)|"+ // for one of the main browsers "(?:^|\\(| )([a-z][-a-z0-9._: ]+|(?:Apple)?WebKit)/((?:\\d+\\.)+\\d+)"); // for unrecognized browser var MATCH = VERSION.exec(xAGENT) || ["","","","unknown","0.0"]; HUB.Browser.name = (MATCH[1] != "" ? browser : (MATCH[3] || MATCH[5])); @@ -3179,7 +3181,11 @@ MathJax.Hub.Startup = { AGENT.match(/Mobile/) != null); }, Opera: function (browser) {browser.version = opera.version()}, + Edge: function (browser) { + browser.isMobile = !!navigator.userAgent.match(/ Phone/); + }, MSIE: function (browser) { + browser.isMobile = !!navigator.userAgent.match(/ Phone/); browser.isIE9 = !!(document.documentMode && (window.performance || window.msPerformance)); MathJax.HTML.setScriptBug = !browser.isIE9 || document.documentMode < 9; MathJax.Hub.msieHTMLCollectionBug = (document.documentMode < 9); From 79bd8996edb66d5492140fa6cd224ac395c8979c Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Sun, 13 Sep 2015 11:09:55 -0400 Subject: [PATCH 63/66] Add warning when switching to NativeMML in Edge --- unpacked/extensions/MathMenu.js | 1 + 1 file changed, 1 insertion(+) diff --git a/unpacked/extensions/MathMenu.js b/unpacked/extensions/MathMenu.js index 48d9c020f..c1f7009d1 100644 --- a/unpacked/extensions/MathMenu.js +++ b/unpacked/extensions/MathMenu.js @@ -1213,6 +1213,7 @@ if (BROWSER.isChrome && BROWSER.version.substr(0,3) !== "24.") {message = MESSAGE.MML.WebKit} else if (BROWSER.isSafari && !BROWSER.versionAtLeast("5.0")) {message = MESSAGE.MML.WebKit} else if (BROWSER.isMSIE) {if (!BROWSER.hasMathPlayer) {message = MESSAGE.MML.MSIE}} + else if (BROWSER.isEdge) {message = MESSAGE.MML.WebKit} else {message = MESSAGE.MML[BROWSER]} warned = "warnedMML"; } From 104434c674410da082b0e879896d74cb959a49fb Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Sun, 13 Sep 2015 11:27:54 -0400 Subject: [PATCH 64/66] Add mobile detection for Chrome and enable alternate context menu trigger (double-tap and hold) --- unpacked/MathJax.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/unpacked/MathJax.js b/unpacked/MathJax.js index e1a1900bc..ccee686ca 100644 --- a/unpacked/MathJax.js +++ b/unpacked/MathJax.js @@ -3180,6 +3180,9 @@ MathJax.Hub.Startup = { AGENT.match(/ Fennec\//) != null || AGENT.match(/Mobile/) != null); }, + Chrome: function (browser) { + browser.noContextMenu = browser.isMobile = !!navigator.userAgent.match(/ Mobile[ \/]/); + }, Opera: function (browser) {browser.version = opera.version()}, Edge: function (browser) { browser.isMobile = !!navigator.userAgent.match(/ Phone/); From 031dccee981ab707f8412660f623e0589659bb0f Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Sun, 13 Sep 2015 17:48:29 -0400 Subject: [PATCH 65/66] Fix CHTML issues due to change from custom tags to span-with-class approach (i.e., replace uses of getElementsByTagName). Also fix some issues found by running the test suite. --- .../CommonHTML/autoload/mmultiscripts.js | 10 +++--- .../output/CommonHTML/autoload/multiline.js | 18 +++++------ unpacked/jax/output/CommonHTML/jax.js | 32 ++++++++++++++----- 3 files changed, 38 insertions(+), 22 deletions(-) diff --git a/unpacked/jax/output/CommonHTML/autoload/mmultiscripts.js b/unpacked/jax/output/CommonHTML/autoload/mmultiscripts.js index f19a15e5d..1a1914e17 100644 --- a/unpacked/jax/output/CommonHTML/autoload/mmultiscripts.js +++ b/unpacked/jax/output/CommonHTML/autoload/mmultiscripts.js @@ -45,7 +45,7 @@ MathJax.Hub.Register.StartupHook("CommonHTML Jax Ready",function () { // var base, bbox; if (stretch) { - base = node.getElementsByTagName("mjx-base")[0]; + base = CHTML.getNode(node,"mjx-base"); } else { this.CHTMLaddChild(node,0,{type:"mjx-base", noBBox:true, forceChild:true}); base = node.firstChild; @@ -137,10 +137,10 @@ MathJax.Hub.Register.StartupHook("CommonHTML Jax Ready",function () { // CHTMLgetScripts: function (BOX,BBOX,stretch,node) { if (stretch) { - BOX.sub = node.getElementsByTagName("mjx-sub")[0]; - BOX.sup = node.getElementsByTagName("mjx-sup")[0]; - BOX.presub = node.getElementsByTagName("mjx-presub")[0]; - BOX.presup = node.getElementsByTagName("mjx-presup")[0]; + BOX.sub = CHTML.getNode(node,"mjx-sub"); + BOX.sup = CHTML.getNode(node,"mjx-sup"); + BOX.presub = CHTML.getNode(node,"mjx-presub"); + BOX.presup = CHTML.getNode(node,"mjx-presup"); BBOX.sub = this.CHTMLbbox.sub; BBOX.sup = this.CHTMLbbox.sup; BBOX.presub = this.CHTMLbbox.presub; diff --git a/unpacked/jax/output/CommonHTML/autoload/multiline.js b/unpacked/jax/output/CommonHTML/autoload/multiline.js index 3b30c07f4..fcccc549a 100644 --- a/unpacked/jax/output/CommonHTML/autoload/multiline.js +++ b/unpacked/jax/output/CommonHTML/autoload/multiline.js @@ -505,9 +505,9 @@ MathJax.Hub.Register.StartupHook("CommonHTML Jax Ready",function () { // if (end.length === 0) { var NODE = this.CHTMLnodeElement(), - stack = NODE.getElementsByTagName("mjx-stack")[0], - sup = NODE.getElementsByTagName("mjx-sup")[0], - sub = NODE.getElementsByTagName("mjx-sub")[0]; + stack = CHTML.getNode(NODE,"mjx-stack"), + sup = CHTML.getNode(NODE,"mjx-sup"), + sub = CHTML.getNode(NODE,"mjx-sub"); if (stack) node.appendChild(stack); else if (sup) node.appendChild(sup); else if (sub) node.appendChild(sub); @@ -569,9 +569,9 @@ MathJax.Hub.Register.StartupHook("CommonHTML Jax Ready",function () { // if (start.length < 1) { NODE = this.CHTMLnodeElement(); - var prestack = NODE.getElementsByTagName("mjx-prestack")[0], - presup = NODE.getElementsByTagName("mjx-presup")[0], - presub = NODE.getElementsByTagName("mjx-presub")[0]; + var prestack = CHTML.getNode(NODE,"mjx-prestack"), + presup = CHTML.getNode(NODE,"mjx-presup"), + presub = CHTML.getNode(NODE,"mjx-presub"); if (prestack) node.appendChild(prestack); else if (presup) node.appendChild(presup); else if (presub) node.appendChild(presub); @@ -598,9 +598,9 @@ MathJax.Hub.Register.StartupHook("CommonHTML Jax Ready",function () { // if (end.length === 0) { NODE = this.CHTMLnodeElement(); - var stack = NODE.getElementsByTagName("mjx-stack")[0], - sup = NODE.getElementsByTagName("mjx-sup")[0], - sub = NODE.getElementsByTagName("mjx-sub")[0]; + var stack = CHTML.getNode(NODE,"mjx-stack"), + sup = CHTML.getNode(NODE,"mjx-sup"), + sub = CHTML.getNode(NODE,"mjx-sub"); if (stack) node.appendChild(stack); else if (sup) node.appendChild(sup); else if (sub) node.appendChild(sub); diff --git a/unpacked/jax/output/CommonHTML/jax.js b/unpacked/jax/output/CommonHTML/jax.js index 54863d260..b51900f06 100644 --- a/unpacked/jax/output/CommonHTML/jax.js +++ b/unpacked/jax/output/CommonHTML/jax.js @@ -335,6 +335,22 @@ ucMatch: HTML.ucMatch, setScript: HTML.setScript, + // + // This replaces node.getElementsByTagName(type)[0] + // and should be replaced by that if we go back to using + // custom tags + // + getNode: (document.getElementsByClassName ? + function (node,type) {return node.getElementsByClassName(type)[0]} : + function (node,type) { + var nodes = node.getElementsByTagName("span"); + var name = RegExp("\\b"+type+"\\b"); + for (var i = 0, m = nodes.length; i < m; i++) { + if (name.test(nodes[i].className)) return nodes[i]; + } + } + ), + /********************************************/ @@ -361,7 +377,7 @@ // Remove any existing output // prev = script.previousSibling; - if (prev && prev.className.substr(0,9) === "mjx-chtml") + if (prev && prev.className && String(prev.className).substr(0,9) === "mjx-chtml") prev.parentNode.removeChild(prev); // // Add the node for the math and mark it as being processed @@ -1328,7 +1344,7 @@ if (child) { var type = options.childNodes; if (type) { - if (type instanceof Array) type = type[i]; + if (type instanceof Array) type = type[i]||"span"; node = CHTML.addElement(node,type); } cnode = child.toCommonHTML(node,options.childOptions); @@ -2035,9 +2051,9 @@ // var base, under, over, nodes = []; if (stretch) { - base = node.getElementsByTagName("mjx-op")[0]; - under = node.getElementsByTagName("mjx-under")[0]; - over = node.getElementsByTagName("mjx-over")[0]; + base = CHTML.getNode(node,"mjx-op"); + under = CHTML.getNode(node,"mjx-under"); + over = CHTML.getNode(node,"mjx-over"); nodes[0] = base; nodes[1] = under||over; nodes[2] = over; } else { var types = ["mjx-op","mjx-under","mjx-over"]; @@ -2235,9 +2251,9 @@ // var base, sub, sup; if (stretch) { - base = node.getElementsByTagName("mjx-base")[0]; - sub = node.getElementsByTagName("mjx-sub")[0]; - sup = node.getElementsByTagName("mjx-sup")[0]; + base = CHTML.getNode(node,"mjx-base"); + sub = CHTML.getNode(node,"mjx-sub"); + sup = CHTML.getNode(node,"mjx-sup"); } else { var types = ["mjx-base","mjx-sub","mjx-sup"]; if (this.sup === 1) types[1] = types[2]; From 00af8c161ef8cad47c919691e499e30779c176a9 Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Mon, 14 Sep 2015 06:57:01 -0400 Subject: [PATCH 66/66] Use isEdge for MSEdge detection --- unpacked/extensions/MathML/mml3.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unpacked/extensions/MathML/mml3.js b/unpacked/extensions/MathML/mml3.js index 27eac324e..90a98f59b 100644 --- a/unpacked/extensions/MathML/mml3.js +++ b/unpacked/extensions/MathML/mml3.js @@ -80,7 +80,7 @@ MathJax.Hub.Register.StartupHook("MathML Jax Ready",function () { */ var BROWSER = MathJax.Hub.Browser; var exslt = ''; - if (!!navigator.userAgent.match(/ Edge\//) || BROWSER.isMSIE) { + if (BROWSER.isEdge || BROWSER.isMSIE) { exslt = 'urn:schemas-microsoft-com:xslt' } else { exslt = 'http://exslt.org/common';