123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810 |
- /*************************************************************
- *
- * [Contrib]/a11y/explorer.js
- *
- * Implements expression exploration via the SRE explorer.
- *
- * ---------------------------------------------------------------------
- *
- * Copyright (c) 2016-2017 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.
- */
- MathJax.Hub.Register.StartupHook('Sre Ready', function() {
- var FALSE, KEY;
- var SETTINGS = MathJax.Hub.config.menuSettings;
- var COOKIE = {}; // replaced when menu is available
- MathJax.Hub.Register.StartupHook('MathEvents Ready', function() {
- FALSE = MathJax.Extension.MathEvents.Event.False;
- KEY = MathJax.Extension.MathEvents.Event.KEY;
- });
- var Assistive = MathJax.Extension.explorer = {
- version: '1.2.3',
- dependents: [], // the extensions that depend on this one
- //
- // Default configurations.
- //
- defaults: {
- walker: 'syntactic',
- highlight: 'none',
- background: 'blue',
- foreground: 'black',
- speech: true,
- generation: 'lazy',
- subtitle: false,
- ruleset: 'mathspeak-default'
- },
- eagerComplexity: 80,
- prefix: 'Assistive-',
- hook: null,
- oldrules: null,
- addMenuOption: function(key, value) {
- SETTINGS[Assistive.prefix + key] = value;
- },
- addDefaults: function() {
- var defaults = MathJax.Hub.CombineConfig('explorer', Assistive.defaults);
- var keys = Object.keys(defaults);
- for (var i = 0, key; key = keys[i]; i++) {
- if (typeof(SETTINGS[Assistive.prefix + key]) === 'undefined') {
- Assistive.addMenuOption(key, defaults[key]);
- }
- }
- Assistive.setSpeechOption();
- Explorer.Reset();
- },
- setOption: function(key, value) {
- if (SETTINGS[Assistive.prefix + key] === value) return;
- Assistive.addMenuOption(key, value);
- Explorer.Reset();
- },
- getOption: function(key) {
- return SETTINGS[Assistive.prefix + key];
- },
- speechOption: function(msg) {
- if (Assistive.oldrules === msg.value) return;
- Assistive.setSpeechOption();
- Explorer.Regenerate();
- },
- setSpeechOption: function() {
- var ruleset = SETTINGS[Assistive.prefix + 'ruleset'];
- var cstr = ruleset.split('-');
- sre.System.getInstance().setupEngine({
- domain: Assistive.Domain(cstr[0]),
- style: cstr[1],
- rules: Assistive.RuleSet(cstr[0])
- });
- Assistive.oldrules = ruleset;
- },
- Domain: function(domain) {
- switch (domain) {
- case 'chromevox':
- return 'default';
- case 'mathspeak':
- default:
- return 'mathspeak';
- }
- },
- RuleSet: function(domain) {
- switch (domain) {
- case 'chromevox':
- return ['AbstractionRules', 'SemanticTreeRules'];
- case 'mathspeak':
- default:
- return ['AbstractionRules', 'MathspeakRules'];
- }
- },
- hook: null,
- Enable: function(update, menu) {
- SETTINGS.explorer = true;
- if (menu) COOKIE.explorer = true;
- MathJax.Extension.collapsible.Enable(false, menu);
- if (MathJax.Extension.AssistiveMML) {
- MathJax.Extension.AssistiveMML.config.disabled = true;
- SETTINGS.assistiveMML = false;
- if (menu) COOKIE.assistiveMML = false;
- }
- this.DisableMenus(false);
- if (!this.hook) {
- this.hook = MathJax.Hub.Register.MessageHook(
- 'New Math', ['Register', this.Explorer]);
- }
- if (update) MathJax.Hub.Queue(['Reprocess', MathJax.Hub]);
- },
- Disable: function(update, menu) {
- SETTINGS.explorer = false;
- if (menu) COOKIE.explorer = false;
- this.DisableMenus(true);
- if (this.hook) {
- MathJax.Hub.UnRegister.MessageHook(this.hook);
- this.hook = null;
- }
- for (var i = this.dependents.length - 1; i >= 0; i--) {
- var dependent = this.dependents[i];
- if (dependent.Disable) dependent.Disable(false, menu);
- }
- // Reprocess on update? I don't think it is necessary
- // (now that we check for being enabled in the event handlers)
- },
- DisableMenus: function(state) {
- if (MathJax.Menu) {
- var menu = MathJax.Menu.menu.FindId('Accessibility', 'Explorer');
- if (menu) {
- menu = menu.submenu;
- var items = menu.items;
- for (var i = 2, item; item = items[i]; i++) item.disabled = state;
- if (!state && menu.FindId('SpeechOutput') && !SETTINGS[Assistive.prefix + 'speech']) {
- menu.FindId('Subtitles').disabled = true;
- menu.FindId('Generation').disabled = true;
- }
- }
- }
- },
- //
- // Register a dependent
- //
- Dependent: function(extension) {
- this.dependents.push(extension);
- }
- };
- var LiveRegion = MathJax.Object.Subclass({
- div: null,
- inner: null,
- Init: function() {
- this.div = LiveRegion.Create('assertive');
- this.inner = MathJax.HTML.addElement(this.div, 'div');
- },
- //
- // Adds the speech div.
- //
- Add: function() {
- if (LiveRegion.added) return;
- document.body.appendChild(this.div);
- LiveRegion.added = true;
- },
- //
- // Shows the live region as a subtitle of a node.
- //
- Show: function(node, highlighter) {
- this.div.classList.add('MJX_LiveRegion_Show');
- var rect = node.getBoundingClientRect();
- var bot = rect.bottom + 10 + window.pageYOffset;
- var left = rect.left + window.pageXOffset;
- this.div.style.top = bot + 'px';
- this.div.style.left = left + 'px';
- var color = highlighter.colorString();
- this.inner.style.backgroundColor = color.background;
- this.inner.style.color = color.foreground;
- },
- //
- // Takes the live region out of the page flow.
- //
- Hide: function(node) {
- this.div.classList.remove('MJX_LiveRegion_Show');
- },
- //
- // Clears the speech div.
- //
- Clear: function() {
- this.Update('');
- this.inner.style.top = '';
- this.inner.style.backgroundColor = '';
- },
- //
- // Speaks a string by poking it into the speech div.
- //
- Update: function(speech) {
- if (Assistive.getOption('speech')) {
- LiveRegion.Update(this.inner, speech);
- }
- }
- }, {
- ANNOUNCE: 'Navigatable Math in page. Explore with shift space and arrow' +
- ' keys. Expand or collapse elements hitting enter.',
- announced: false,
- added: false,
- styles: {'.MJX_LiveRegion':
- {
- position: 'absolute', top: '0', height: '1px', width: '1px',
- padding: '1px', overflow: 'hidden'
- },
- '.MJX_LiveRegion_Show':
- {
- top: '0', position: 'absolute', width: 'auto', height: 'auto',
- padding: '0px 0px', opacity: 1, 'z-index': '202',
- left: 0, right: 0, 'margin': '0 auto',
- 'background-color': 'white', 'box-shadow': '0px 10px 20px #888',
- border: '2px solid #CCCCCC'
- }
- },
- //
- // Creates a live region with a particular type.
- //
- Create: function(type) {
- var element = MathJax.HTML.Element(
- 'div', {className: 'MJX_LiveRegion'});
- element.setAttribute('aria-live', type);
- return element;
- },
- //
- // Updates a live region's text content.
- //
- Update: MathJax.Hub.Browser.isPC ?
- function(div, speech) {
- div.textContent = '';
- setTimeout(function() {div.textContent = speech;}, 100);
- } : function(div, speech) {
- div.textContent = '';
- div.textContent = speech;
- },
- //
- // Speaks the announce string.
- //
- Announce: function() {
- if (!Assistive.getOption('speech')) return;
- LiveRegion.announced = true;
- MathJax.Ajax.Styles(LiveRegion.styles);
- var div = LiveRegion.Create('polite');
- document.body.appendChild(div);
- LiveRegion.Update(div, LiveRegion.ANNOUNCE);
- setTimeout(function() {document.body.removeChild(div);}, 1000);
- }
- });
- MathJax.Extension.explorer.LiveRegion = LiveRegion;
- var A11Y_PATH = MathJax.Ajax.fileURL(MathJax.Ajax.config.path.a11y);
-
- var Explorer = MathJax.Extension.explorer.Explorer = {
- liveRegion: LiveRegion(),
- walker: null,
- highlighter: null,
- hoverer: null,
- flamer: null,
- speechDiv: null,
- earconFile: A11Y_PATH + '/invalid_keypress' +
- (['Firefox', 'Chrome', 'Opera'].indexOf(MathJax.Hub.Browser.name) !== -1 ?
- '.ogg' : '.mp3'),
- expanded: false,
- focusoutEvent: MathJax.Hub.Browser.isFirefox ? 'blur' : 'focusout',
- focusinEvent: 'focus',
- ignoreFocusOut: false,
- jaxCache: {},
- messageID: null,
- //
- // Resets the explorer, rerunning methods not triggered by events.
- //
- Reset: function() {
- Explorer.FlameEnriched();
- },
- //
- // Registers new Maths and adds a key event if it is enriched.
- //
- Register: function(msg) {
- if (!Assistive.hook) return;
- var script = document.getElementById(msg[1]);
- if (script && script.id) {
- var jax = MathJax.Hub.getJaxFor(script.id);
- if (jax && jax.enriched) {
- Explorer.StateChange(script.id, jax);
- Explorer.liveRegion.Add();
- Explorer.AddEvent(script);
- }
- }
- },
- StateChange: function(id, jax) {
- Explorer.GetHighlighter(.2);
- var oldJax = Explorer.jaxCache[id];
- if (oldJax && oldJax === jax.root) return;
- if (oldJax) {
- Explorer.highlighter.resetState(id + '-Frame');
- }
- Explorer.jaxCache[id] = jax.root;
- },
- //
- // Adds Aria attributes.
- //
- AddAria: function(math) {
- math.setAttribute('role', 'application');
- math.setAttribute('aria-label', 'Math');
- },
- //
- // Add hook to run at End Math to restart walking on an expansion element.
- //
- AddHook: function(jax) {
- Explorer.RemoveHook();
- Explorer.hook = MathJax.Hub.Register.MessageHook(
- 'End Math', function(message) {
- var newid = message[1].id + '-Frame';
- var math = document.getElementById(newid);
- if (jax && newid === Explorer.expanded) {
- Explorer.ActivateWalker(math, jax);
- math.focus();
- Explorer.expanded = false;
- }
- });
- },
- //
- // Remove and unregister the explorer hook.
- //
- RemoveHook: function() {
- if (Explorer.hook) {
- MathJax.Hub.UnRegister.MessageHook(Explorer.hook);
- Explorer.hook = null;
- }
- },
- AddMessage: function() {
- return MathJax.Message.Set('Generating Speech Output');
- },
- RemoveMessage: function(id) {
- if (id) MathJax.Message.Clear(id);
- },
- //
- // Adds a key event to an enriched jax.
- //
- AddEvent: function(script) {
- var id = script.id + '-Frame';
- var sibling = script.previousSibling;
- if (!sibling) return;
- var math = sibling.id !== id ? sibling.firstElementChild : sibling;
- Explorer.AddAria(math);
- Explorer.AddMouseEvents(math);
- if (math.className === 'MathJax_MathML') {
- math = math.firstElementChild;
- }
- if (!math) return;
- math.onkeydown = Explorer.Keydown;
- Explorer.Flame(math);
- math.addEventListener(
- Explorer.focusinEvent,
- function(event) {
- if (!Assistive.hook) return;
- if (!LiveRegion.announced) LiveRegion.Announce();
- });
- math.addEventListener(
- Explorer.focusoutEvent,
- function(event) {
- if (!Assistive.hook) return;
- // A fix for Edge.
- if (Explorer.ignoreFocusOut) {
- Explorer.ignoreFocusOut = false;
- if (Explorer.walker.moved === 'enter') {
- event.target.focus();
- return;
- }
- }
- if (Explorer.walker) Explorer.DeactivateWalker();
- });
- //
- if (Assistive.getOption('speech')) {
- Explorer.AddSpeech(math);
- }
- //
- },
- //
- // Add speech output.
- //
- AddSpeech: function(math) {
- var id = math.id;
- var jax = MathJax.Hub.getJaxFor(id);
- var mathml = jax.root.toMathML();
- if (!math.getAttribute('haslabel')) {
- Explorer.AddMathLabel(mathml, id);
- }
- if (math.getAttribute('hasspeech')) return;
- switch (Assistive.getOption('generation')) {
- case 'eager':
- Explorer.AddSpeechEager(mathml, id);
- break;
- case 'mixed':
- var complexity = math.querySelectorAll('[data-semantic-complexity]');
- if (complexity.length >= Assistive.eagerComplexity) {
- Explorer.AddSpeechEager(mathml, id);
- }
- break;
- case 'lazy':
- default:
- break;
- }
- },
- AddSpeechLazy: function(math) {
- var generator = new sre.TreeSpeechGenerator();
- generator.setRebuilt(Explorer.walker.rebuilt);
- generator.getSpeech(Explorer.walker.rootNode, Explorer.walker.xml);
- math.setAttribute('hasspeech', 'true');
- },
- //
- //
- // Adds speech strings to the node using a web worker.
- //
- AddSpeechEager: function(mathml, id) {
- Explorer.MakeSpeechTask(
- mathml, id, sre.TreeSpeechGenerator,
- function(math, speech) {math.setAttribute('hasspeech', 'true');}, 5);
- },
- //
- // Attaches the Math expression as an aria label.
- //
- AddMathLabel: function(mathml, id) {
- Explorer.MakeSpeechTask(
- mathml, id, sre.SummarySpeechGenerator,
- function(math, speech) {
- math.setAttribute('haslabel', 'true');
- math.setAttribute('aria-label', speech);},
- 5);
- },
- //
- // The actual speech task generator.
- //
- MakeSpeechTask: function(mathml, id, constructor, onSpeech, time) {
- var messageID = Explorer.AddMessage();
- setTimeout(function() {
- var speechGenerator = new constructor();
- var math = document.getElementById(id);
- var dummy = new sre.DummyWalker(
- math, speechGenerator, Explorer.highlighter, mathml);
- var speech = dummy.speech();
- if (speech) {
- onSpeech(math, speech);
- }
- Explorer.RemoveMessage(messageID);
- }, time);
- },
- //
- // Event execution on keydown. Subsumes the same method of MathEvents.
- //
- Keydown: function(event) {
- if (event.keyCode === KEY.ESCAPE) {
- if (!Explorer.walker) return;
- Explorer.RemoveHook();
- Explorer.DeactivateWalker();
- FALSE(event);
- return;
- }
- // If walker is active we redirect there.
- if (Explorer.walker && Explorer.walker.isActive()) {
- var move = Explorer.walker.move(event.keyCode);
- if (move === null) return;
- if (move) {
- if (Explorer.walker.moved === 'expand') {
- Explorer.expanded = Explorer.walker.node.id;
- // This sometimes blurs in Edge and sometimes it does not.
- if (MathJax.Hub.Browser.isEdge) {
- Explorer.ignoreFocusOut = true;
- Explorer.DeactivateWalker();
- return;
- }
- // This does not blur in FF, IE.
- if (MathJax.Hub.Browser.isFirefox || MathJax.Hub.Browser.isMSIE) {
- Explorer.DeactivateWalker();
- return;
- }
- }
- Explorer.liveRegion.Update(Explorer.walker.speech());
- Explorer.Highlight();
- } else {
- Explorer.PlayEarcon();
- }
- FALSE(event);
- return;
- }
- var math = event.target;
- if (event.keyCode === KEY.SPACE) {
- if (event.shiftKey && Assistive.hook) {
- var jax = MathJax.Hub.getJaxFor(math);
- Explorer.ActivateWalker(math, jax);
- Explorer.AddHook(jax);
- } else {
- MathJax.Extension.MathEvents.Event.ContextMenu(event, math);
- }
- FALSE(event);
- return;
- }
- },
- GetHighlighter: function(alpha) {
- Explorer.highlighter = sre.HighlighterFactory.highlighter(
- {color: Assistive.getOption('background'), alpha: alpha},
- {color: Assistive.getOption('foreground'), alpha: 1},
- {renderer: MathJax.Hub.outputJax['jax/mml'][0].id,
- browser: MathJax.Hub.Browser.name}
- );
- },
- //
- // Adds mouse events to maction items in an enriched jax.
- //
- AddMouseEvents: function(node) {
- sre.HighlighterFactory.addEvents(
- node,
- {'mouseover': Explorer.MouseOver,
- 'mouseout': Explorer.MouseOut},
- {renderer: MathJax.Hub.outputJax['jax/mml'][0].id,
- browser: MathJax.Hub.Browser.name}
- );
- },
- MouseOver: function(event) {
- if (Assistive.getOption('highlight') === 'none') return;
- if (Assistive.getOption('highlight') === 'hover') {
- var frame = event.currentTarget;
- Explorer.GetHighlighter(.1);
- Explorer.highlighter.highlight([frame]);
- Explorer.hoverer = true;
- }
- FALSE(event);
- },
- MouseOut: function(event) {
- if (Explorer.hoverer) {
- Explorer.highlighter.unhighlight();
- Explorer.hoverer = false;
- }
- return FALSE(event);
- },
- //
- // Activates Flaming
- //
- Flame: function(node) {
- if (Assistive.getOption('highlight') === 'flame') {
- Explorer.GetHighlighter(.05);
- Explorer.highlighter.highlightAll(node);
- Explorer.flamer = true;
- return;
- }
- },
- UnFlame: function() {
- if (Explorer.flamer) {
- Explorer.highlighter.unhighlightAll();
- Explorer.flamer = null;
- }
- },
- FlameEnriched: function() {
- Explorer.UnFlame();
- for (var i = 0, all = MathJax.Hub.getAllJax(), jax; jax = all[i]; i++) {
- Explorer.Flame(jax.SourceElement().previousSibling);
- }
- },
- //
- // Activates the walker.
- //
- Walkers: {
- 'syntactic': sre.SyntaxWalker,
- 'semantic': sre.SemanticWalker,
- 'none': sre.DummyWalker
- },
- ActivateWalker: function(math, jax) {
- var speechOn = Assistive.getOption('speech');
- var constructor = Explorer.Walkers[Assistive.getOption('walker')] ||
- Explorer.Walkers['none'];
- var speechGenerator = speechOn ? new sre.DirectSpeechGenerator() :
- new sre.DummySpeechGenerator();
- Explorer.GetHighlighter(.2);
- Explorer.walker = new constructor(
- math, speechGenerator, Explorer.highlighter, jax.root.toMathML());
- if (speechOn && !math.getAttribute('hasspeech')) {
- Explorer.AddSpeechLazy(math);
- }
- Explorer.walker.activate();
- if (speechOn) {
- if (Assistive.getOption('subtitle')) {
- Explorer.liveRegion.Show(math, Explorer.highlighter);
- }
- Explorer.liveRegion.Update(Explorer.walker.speech());
- }
- Explorer.Highlight();
- // A fix for Edge.
- if (Explorer.ignoreFocusOut) {
- setTimeout(function() {Explorer.ignoreFocusOut = false;}, 500);
- }
- },
- //
- // Deactivates the walker.
- //
- DeactivateWalker: function() {
- Explorer.liveRegion.Clear();
- Explorer.liveRegion.Hide();
- Explorer.Unhighlight();
- Explorer.currentHighlight = null;
- Explorer.walker.deactivate();
- Explorer.walker = null;
- },
- //
- // Highlights the focused nodes.
- //
- Highlight: function() {
- Explorer.Unhighlight();
- Explorer.highlighter.highlight(Explorer.walker.getFocus().getNodes());
- },
- //
- // Unhighlights the old nodes.
- //
- Unhighlight: function() {
- Explorer.highlighter.unhighlight();
- },
- //
- // Plays the earcon.
- //
- // Every time we make new Audio element, as some browsers do not allow to
- // play audio elements more than once (e.g., Safari).
- //
- PlayEarcon: function() {
- var audio = new Audio(Explorer.earconFile);
- audio.play();
- },
- //
- // Toggle speech output.
- //
- SpeechOutput: function() {
- Explorer.Reset();
- var speechItems = ['Subtitles', 'Generation'];
- speechItems.forEach(
- function(x) {
- var item = MathJax.Menu.menu.FindId('Accessibility', 'Explorer', x);
- if (item) {
- item.disabled = !item.disabled;
- }});
- Explorer.Regenerate();
- },
- //
- // Regenerates speech.
- //
- Regenerate: function() {
- for (var i = 0, all = MathJax.Hub.getAllJax(), jax; jax = all[i]; i++) {
- var math = document.getElementById(jax.inputID + '-Frame');
- if (math) {
- math.removeAttribute('hasSpeech');
- Explorer.AddSpeech(math);
- }
- }
- },
- Startup: function() {
- var Collapsible = MathJax.Extension.collapsible;
- if (Collapsible) Collapsible.Dependent(Assistive);
- Assistive.addDefaults();
- }
- };
- MathJax.Hub.Register.StartupHook('End Extensions', function() {
- Assistive[SETTINGS.explorer === false ? 'Disable' : 'Enable']();
- MathJax.Hub.Startup.signal.Post('Explorer Ready');
- MathJax.Hub.Register.StartupHook('MathMenu Ready', function() {
- COOKIE = MathJax.Menu.cookie;
- var Switch = function(menu) {
- Assistive[SETTINGS.explorer ? 'Enable' : 'Disable'](true, true);
- MathJax.Menu.saveCookie();
- };
- var ITEM = MathJax.Menu.ITEM,
- MENU = MathJax.Menu.menu;
- var reset = {action: Explorer.Reset};
- var speech = {action: Assistive.speechOption};
- var explorerMenu =
- ITEM.SUBMENU(['Explorer', 'Explorer'],
- ITEM.CHECKBOX(['Active', 'Active'], 'explorer', {action: Switch}),
- ITEM.RULE(),
- ITEM.SUBMENU(['Walker', 'Walker'],
- ITEM.RADIO(['nowalker', 'No walker'], 'Assistive-walker', {value:"none"}),
- ITEM.RADIO(['syntactic', 'Syntax walker'], 'Assistive-walker'),
- ITEM.RADIO(['semantic', 'Semantic walker'], 'Assistive-walker')
- ),
- ITEM.SUBMENU(['Highlight', 'Highlight'],
- ITEM.RADIO(['none', 'None'], 'Assistive-highlight', reset),
- ITEM.RADIO(['hover', 'Hover'], 'Assistive-highlight', reset),
- ITEM.RADIO(['flame', 'Flame'], 'Assistive-highlight', reset)
- ),
- ITEM.SUBMENU(['Background', 'Background'],
- ITEM.RADIO(['blue', 'Blue'], 'Assistive-background', reset),
- ITEM.RADIO(['red', 'Red'], 'Assistive-background', reset),
- ITEM.RADIO(['green', 'Green'], 'Assistive-background', reset),
- ITEM.RADIO(['yellow', 'Yellow'], 'Assistive-background', reset),
- ITEM.RADIO(['cyan', 'Cyan'], 'Assistive-background', reset),
- ITEM.RADIO(['magenta', 'Magenta'], 'Assistive-background', reset),
- ITEM.RADIO(['white', 'White'], 'Assistive-background', reset),
- ITEM.RADIO(['black', 'Black'], 'Assistive-background', reset)
- ),
- ITEM.SUBMENU(['Foreground', 'Foreground'],
- ITEM.RADIO(['black', 'Black'], 'Assistive-foreground', reset),
- ITEM.RADIO(['white', 'White'], 'Assistive-foreground', reset),
- ITEM.RADIO(['magenta', 'Magenta'], 'Assistive-foreground', reset),
- ITEM.RADIO(['cyan', 'Cyan'], 'Assistive-foreground', reset),
- ITEM.RADIO(['yellow', 'Yellow'], 'Assistive-foreground', reset),
- ITEM.RADIO(['green', 'Green'], 'Assistive-foreground', reset),
- ITEM.RADIO(['red', 'Red'], 'Assistive-foreground', reset),
- ITEM.RADIO(['blue', 'Blue'], 'Assistive-foreground', reset)
- ),
- ITEM.RULE(),
- ITEM.CHECKBOX(['SpeechOutput', 'Speech Output'],
- 'Assistive-speech', {action: Explorer.SpeechOutput}),
- ITEM.CHECKBOX(['Subtitles', 'Subtitles'], 'Assistive-subtitle',
- {disabled: !SETTINGS['Assistive-speech']}),
- ITEM.SUBMENU(['Generation', 'Generation'],
- {disabled: !SETTINGS['Assistive-speech']},
- ITEM.RADIO(['eager', 'Eager'], 'Assistive-generation',
- {action: Explorer.Regenerate}),
- ITEM.RADIO(['mixed', 'Mixed'], 'Assistive-generation',
- {action: Explorer.Regenerate}),
- ITEM.RADIO(['lazy', 'Lazy'], 'Assistive-generation',
- {action: Explorer.Regenerate})
- ),
- ITEM.RULE(),
- ITEM.SUBMENU(['Mathspeak', 'Mathspeak Rules'],
- ITEM.RADIO(['mathspeak-default', 'Verbose'],
- 'Assistive-ruleset', speech),
- ITEM.RADIO(['mathspeak-brief', 'Brief'], 'Assistive-ruleset', speech),
- ITEM.RADIO(['mathspeak-sbrief', 'Superbrief'],
- 'Assistive-ruleset', speech)
- ),
- ITEM.SUBMENU(['Chromevox', 'ChromeVox Rules'],
- ITEM.RADIO(['chromevox-default', 'Verbose'],
- 'Assistive-ruleset', speech),
- ITEM.RADIO(['chromevox-short', 'Short'], 'Assistive-ruleset',
- speech),
- ITEM.RADIO(['chromevox-alternative', 'Alternative'],
- 'Assistive-ruleset', speech)
- )
- );
- var submenu = (MENU.FindId('Accessibility') || {}).submenu, index;
- if (submenu) {
- index = submenu.IndexOfId('Explorer');
- if (index !== null) {
- submenu.items[index] = explorerMenu;
- } else {
- index = submenu.IndexOfId('CollapsibleMath');
- submenu.items.splice(index + 1, 0, explorerMenu);
- }
- } else {
- index = MENU.IndexOfId('CollapsibleMath');
- MENU.items.splice(index + 1, 0, explorerMenu);
- }
- if (!SETTINGS.explorer) Assistive.DisableMenus(true);
- },20); // Between collapsible and auto-collapse extensions
- },20);
- });
- //
- // Patch problem with SVG getJaxForMath when used from explorer
- // (can be removed after the next release of MathJax).
- //
- MathJax.Hub.Register.StartupHook("SVG Jax Ready",function () {
- MathJax.Hub.Config({SVG: {addMMLclasses: true}});
- var SVG = MathJax.OutputJax.SVG;
- if (parseFloat(SVG.version) < 2.7) {
- var JAXFROMMATH = SVG.getJaxFromMath;
- SVG.Augment({
- getJaxFromMath: function (math) {
- if (math.parentNode.className.match(/MathJax_SVG_Display/)) math = math.parentNode;
- return JAXFROMMATH.call(this,math);
- }
- });
- }
- });
- //
- // Set up the a11y path,if it isn't already in place
- //
- if (!MathJax.Ajax.config.path.a11y) {
- MathJax.Ajax.config.path.a11y = MathJax.Hub.config.root + "/extensions/a11y";
- }
- MathJax.Ajax.Require('[a11y]/collapsible.js');
- MathJax.Hub.Register.StartupHook('Collapsible Ready', function() {
- MathJax.Extension.explorer.Explorer.Startup();
- MathJax.Ajax.loadComplete('[a11y]/explorer.js');
- });
|