explorer.js 20 KB
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417
MathJax.Hub.Register.StartupHook("Sre Ready", function() {
    var o, r, s = MathJax.Hub.config.menuSettings, l = {};
    MathJax.Hub.Register.StartupHook("MathEvents Ready", function() {
        o = MathJax.Extension.MathEvents.Event.False, r = MathJax.Extension.MathEvents.Event.KEY;
    });
    var h = MathJax.Extension.explorer = {
        version: "1.6.0",
        dependents: [],
        defaults: {
            walker: "table",
            highlight: "none",
            background: "blue",
            foreground: "black",
            speech: !0,
            generation: "lazy",
            subtitle: !1,
            ruleset: "mathspeak-default"
        },
        eagerComplexity: 80,
        prefix: "Assistive-",
        hook: null,
        locHook: null,
        oldrules: null,
        addMenuOption: function(e, t) {
            s[h.prefix + e] = t;
        },
        addDefaults: function() {
            for (var e, t = MathJax.Hub.CombineConfig("explorer", h.defaults), a = Object.keys(t), i = 0; e = a[i]; i++) void 0 === s[h.prefix + e] && h.addMenuOption(e, t[e]);
            h.setSpeechOption(), u.Reset();
        },
        setOption: function(e, t) {
            s[h.prefix + e] !== t && (h.addMenuOption(e, t), u.Reset());
        },
        getOption: function(e) {
            return s[h.prefix + e];
        },
        speechOption: function(e) {
            h.oldrules !== e.value && (h.setSpeechOption(), u.Regenerate());
        },
        setSpeechOption: function() {
            var e = s[h.prefix + "ruleset"], t = e.split("-");
            sre.System.getInstance().setupEngine({
                locale: MathJax.Localization.locale,
                domain: h.Domain(t[0]),
                style: t[1]
            }), h.oldrules = e;
        },
        Domain: function(e) {
            switch (e) {
              case "chromevox":
                return "default";

              case "clearspeak":
                return "clearspeak";

              case "mathspeak":
              default:
                return "mathspeak";
            }
        },
        Enable: function(e, t) {
            s.explorer = !0, t && (l.explorer = !0), MathJax.Extension.collapsible.Enable(!1, t), 
            MathJax.Extension.AssistiveMML && (MathJax.Extension.AssistiveMML.config.disabled = !0, 
            s.assistiveMML = !1, t && (l.assistiveMML = !1)), this.DisableMenus(!1), this.hook || (this.hook = MathJax.Hub.Register.MessageHook("New Math", [ "Register", this.Explorer ])), 
            this.locHook || (this.locHook = MathJax.Hub.Register.MessageHook("Locale Reset", [ "RemoveSpeech", this.Explorer ])), 
            e && MathJax.Hub.Queue([ "Reprocess", MathJax.Hub ]);
        },
        Disable: function(e, t) {
            s.explorer = !1, t && (l.explorer = !1), this.DisableMenus(!0), this.hook && (MathJax.Hub.UnRegister.MessageHook(this.hook), 
            this.hook = null);
            for (var a = this.dependents.length - 1; 0 <= a; a--) {
                var i = this.dependents[a];
                i.Disable && i.Disable(!1, t);
            }
        },
        DisableMenus: function(e) {
            if (MathJax.Menu) {
                var t = MathJax.Menu.menu.FindId("Accessibility", "Explorer");
                if (t) {
                    for (var a, i = (t = t.submenu).items, n = 2; a = i[n]; n++) a.disabled = e;
                    e || !t.FindId("SpeechOutput") || s[h.prefix + "speech"] || (t.FindId("Subtitles").disabled = !0);
                }
            }
        },
        Dependent: function(e) {
            this.dependents.push(e);
        }
    }, n = MathJax.Object.Subclass({
        div: null,
        inner: null,
        Init: function() {
            this.div = n.Create("assertive"), this.inner = MathJax.HTML.addElement(this.div, "div");
        },
        Add: function() {
            n.added || (document.body.appendChild(this.div), n.added = !0);
        },
        Show: function(e, t) {
            this.div.classList.add("MJX_LiveRegion_Show");
            var a = e.getBoundingClientRect(), i = a.bottom + 10 + window.pageYOffset, n = a.left + window.pageXOffset;
            this.div.style.top = i + "px", this.div.style.left = n + "px";
            var o = t.colorString();
            this.inner.style.backgroundColor = o.background, this.inner.style.color = o.foreground;
        },
        Hide: function(e) {
            this.div.classList.remove("MJX_LiveRegion_Show");
        },
        Clear: function() {
            this.Update(""), this.inner.style.top = "", this.inner.style.backgroundColor = "";
        },
        Update: function(e) {
            h.getOption("speech") && n.Update(this.inner, e);
        }
    }, {
        ANNOUNCE: "Navigatable Math in page. Explore with enter or shift space and arrow keys. Expand or collapse elements hitting enter.",
        announced: !1,
        added: !1,
        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"
            }
        },
        Create: function(e) {
            var t = MathJax.HTML.Element("div", {
                className: "MJX_LiveRegion"
            });
            return t.setAttribute("aria-live", e), t;
        },
        Update: MathJax.Hub.Browser.isPC ? function(e, t) {
            e.textContent = "", setTimeout(function() {
                e.textContent = t;
            }, 100);
        } : function(e, t) {
            e.textContent = "", e.textContent = t;
        },
        Announce: function() {
            var e;
            h.getOption("speech") && (n.announced = !0, MathJax.Ajax.Styles(n.styles), e = n.Create("polite"), 
            document.body.appendChild(e), n.Update(e, n.ANNOUNCE), setTimeout(function() {
                document.body.removeChild(e);
            }, 1e3));
        }
    });
    MathJax.Extension.explorer.LiveRegion = n;
    var e = MathJax.Ajax.fileURL(MathJax.Ajax.config.path.a11y), u = MathJax.Extension.explorer.Explorer = {
        liveRegion: n(),
        walker: null,
        highlighter: null,
        hoverer: null,
        flamer: null,
        speechDiv: null,
        earconFile: e + "/invalid_keypress" + (-1 !== [ "Firefox", "Chrome", "Opera" ].indexOf(MathJax.Hub.Browser.name) ? ".ogg" : ".mp3"),
        expanded: !1,
        focusoutEvent: MathJax.Hub.Browser.isFirefox ? "blur" : "focusout",
        focusinEvent: "focus",
        ignoreFocusOut: !1,
        jaxCache: {},
        messageID: null,
        Reset: function() {
            u.FlameEnriched();
        },
        Register: function(e) {
            var t, a;
            !h.hook || (t = document.getElementById(e[1])) && t.id && ((a = MathJax.Hub.getJaxFor(t.id)) && a.enriched && (u.StateChange(t.id, a), 
            u.liveRegion.Add(), u.AddEvent(t)));
        },
        StateChange: function(e, t) {
            u.GetHighlighter(.2);
            var a = u.jaxCache[e];
            a && a === t.root || (a && sre.Walker.resetState(e + "-Frame"), u.jaxCache[e] = t.root);
        },
        AddAria: function(e) {
            e.setAttribute("role", "application"), e.setAttribute("aria-label", "Math");
        },
        AddHook: function(i) {
            u.RemoveHook(), u.hook = MathJax.Hub.Register.MessageHook("End Math", function(e) {
                var t = e[1].id + "-Frame", a = document.getElementById(t);
                i && t === u.expanded && (u.ActivateWalker(a, i), a.focus(), u.expanded = !1);
            });
        },
        RemoveHook: function() {
            u.hook && (MathJax.Hub.UnRegister.MessageHook(u.hook), u.hook = null);
        },
        AddMessage: function() {
            return MathJax.Message.Set("Generating Speech Output");
        },
        RemoveMessage: function(e) {
            e && MathJax.Message.Clear(e);
        },
        AddEvent: function(e) {
            var t, a = e.id + "-Frame", i = e.previousSibling;
            i && (t = i.id !== a ? i.firstElementChild : i, u.AddAria(t), u.AddMouseEvents(t), 
            "MathJax_MathML" === t.className && (t = t.firstElementChild), t && (t.onkeydown = u.Keydown, 
            u.Flame(t), t.addEventListener(u.focusinEvent, function(e) {
                h.hook && (n.announced || n.Announce());
            }), t.addEventListener(u.focusoutEvent, function(e) {
                h.hook && (u.ignoreFocusOut && (u.ignoreFocusOut = !1, "enter" === u.walker.moved) ? e.target.focus() : u.walker && u.DeactivateWalker());
            }), h.getOption("speech") && u.AddSpeech(t)));
        },
        AddSpeech: function(e) {
            var t = e.id, a = MathJax.Hub.getJaxFor(t).root.toMathML();
            if (e.getAttribute("haslabel") || u.AddMathLabel(a, t), !e.getAttribute("hasspeech")) switch (MathJax.Hub.config.explorer.generation) {
              case "eager":
                u.AddSpeechEager(a, t);
                break;

              case "mixed":
                e.querySelectorAll("[data-semantic-complexity]").length >= h.eagerComplexity && u.AddSpeechEager(a, t);
            }
        },
        AddSpeechLazy: function(e) {
            var t = new sre.TreeSpeechGenerator();
            t.setRebuilt(u.walker.getRebuilt()), t.getSpeech(u.walker.rootNode, u.walker.getXml()), 
            e.setAttribute("hasspeech", "true");
        },
        AddSpeechEager: function(e, t) {
            u.MakeSpeechTask(e, t, sre.TreeSpeechGenerator, function(e, t) {
                e.setAttribute("hasspeech", "true");
            }, 5);
        },
        AddMathLabel: function(e, t) {
            u.MakeSpeechTask(e, t, sre.SummarySpeechGenerator, function(e, t) {
                e.setAttribute("haslabel", "true"), e.setAttribute("aria-label", t);
            }, 5);
        },
        MakeSpeechTask: function(i, n, o, r, e) {
            var s = u.AddMessage();
            setTimeout(function() {
                var e = new o(), t = document.getElementById(n), a = new sre.DummyWalker(t, e, u.highlighter, i).speech();
                a && r(t, a), u.RemoveMessage(s);
            }, e);
        },
        Keydown: function(e) {
            var t = e.keyCode;
            if (t === r.ESCAPE) {
                if (!u.walker) return;
                return u.RemoveHook(), u.DeactivateWalker(), void o(e);
            }
            if (u.walker && u.walker.isActive()) {
                t = t === r.RETURN ? r.DASH : t, void 0 !== u.walker.modifier && (u.walker.modifier = e.shiftKey);
                var a = u.walker.move(t);
                if (null === a) return;
                if (a) {
                    if ("expand" === u.walker.moved) {
                        if (u.expanded = u.walker.node.id, MathJax.Hub.Browser.isEdge) return u.ignoreFocusOut = !0, 
                        void u.DeactivateWalker();
                        if (MathJax.Hub.Browser.isFirefox || MathJax.Hub.Browser.isMSIE) return void u.DeactivateWalker();
                    }
                    u.liveRegion.Update(u.walker.speech()), u.Highlight();
                } else u.PlayEarcon();
                o(e);
            } else {
                var i = e.target;
                if (t === r.SPACE && !e.shiftKey) return MathJax.Extension.MathEvents.Event.ContextMenu(e, i), 
                void o(e);
                if (h.hook && (t === r.RETURN || t === r.SPACE && e.shiftKey)) {
                    var n = MathJax.Hub.getJaxFor(i);
                    return u.ActivateWalker(i, n), u.AddHook(n), void o(e);
                }
            }
        },
        GetHighlighter: function(e) {
            u.highlighter = sre.HighlighterFactory.highlighter({
                color: h.getOption("background"),
                alpha: e
            }, {
                color: h.getOption("foreground"),
                alpha: 1
            }, {
                renderer: MathJax.Hub.outputJax["jax/mml"][0].id,
                browser: MathJax.Hub.Browser.name
            });
        },
        AddMouseEvents: function(e) {
            sre.HighlighterFactory.addEvents(e, {
                mouseover: u.MouseOver,
                mouseout: u.MouseOut
            }, {
                renderer: MathJax.Hub.outputJax["jax/mml"][0].id,
                browser: MathJax.Hub.Browser.name
            });
        },
        MouseOver: function(e) {
            var t;
            "none" !== h.getOption("highlight") && ("hover" === h.getOption("highlight") && (t = e.currentTarget, 
            u.GetHighlighter(.1), u.highlighter.highlight([ t ]), u.hoverer = !0), o(e));
        },
        MouseOut: function(e) {
            return u.hoverer && (u.highlighter.unhighlight(), u.hoverer = !1), o(e);
        },
        Flame: function(e) {
            if ("flame" === h.getOption("highlight")) return u.GetHighlighter(.05), u.highlighter.highlightAll(e), 
            void (u.flamer = !0);
        },
        UnFlame: function() {
            u.flamer && (u.highlighter.unhighlightAll(), u.flamer = null);
        },
        FlameEnriched: function() {
            u.UnFlame();
            for (var e, t = 0, a = MathJax.Hub.getAllJax(); e = a[t]; t++) u.Flame(e.SourceElement().previousSibling);
        },
        Walkers: {
            syntactic: sre.SyntaxWalker,
            table: sre.TableWalker,
            semantic: sre.SemanticWalker,
            none: sre.DummyWalker
        },
        ActivateWalker: function(e, t) {
            var a = h.getOption("speech"), i = h.getOption("walker") ? u.Walkers[MathJax.Hub.config.explorer.walker] : u.Walkers.none, n = a ? new sre.DirectSpeechGenerator() : new sre.DummySpeechGenerator(), o = sre.System.getInstance().engineSetup();
            n.setOptions({
                locale: o.locale,
                domain: o.domain,
                style: o.style,
                modality: "speech"
            }), u.GetHighlighter(.2), u.walker = new i(e, n, u.highlighter, t.root.toMathML()), 
            a && !e.getAttribute("hasspeech") && u.AddSpeechLazy(e), u.walker.activate(), a && (h.getOption("subtitle") && u.liveRegion.Show(e, u.highlighter), 
            u.liveRegion.Update(u.walker.speech())), u.Highlight(), u.ignoreFocusOut && setTimeout(function() {
                u.ignoreFocusOut = !1;
            }, 500);
        },
        DeactivateWalker: function() {
            var e = sre.System.getInstance().engineSetup(), t = "clearspeak" === e.domain ? "default" : e.style;
            h.setOption("ruleset", e.domain + "-" + t), u.liveRegion.Clear(), u.liveRegion.Hide(), 
            u.Unhighlight(), u.currentHighlight = null, u.walker.deactivate(), u.walker = null;
        },
        Highlight: function() {
            u.Unhighlight(), u.highlighter.highlight(u.walker.getFocus().getNodes());
        },
        Unhighlight: function() {
            u.highlighter.unhighlight();
        },
        PlayEarcon: function() {
            new Audio(u.earconFile).play();
        },
        SpeechOutput: function() {
            u.Reset();
            [ "Subtitles" ].forEach(function(e) {
                var t = MathJax.Menu.menu.FindId("Accessibility", "Explorer", e);
                t && (t.disabled = !t.disabled);
            }), u.Regenerate();
        },
        RemoveSpeech: function() {
            h.setSpeechOption();
            for (var e, t = 0, a = MathJax.Hub.getAllJax(); e = a[t]; t++) {
                var i = document.getElementById(e.inputID + "-Frame");
                i && (i.removeAttribute("hasspeech"), i.removeAttribute("haslabel"));
            }
        },
        Regenerate: function() {
            for (var e, t = 0, a = MathJax.Hub.getAllJax(); e = a[t]; t++) {
                var i = document.getElementById(e.inputID + "-Frame");
                i && (i.removeAttribute("hasspeech"), u.AddSpeech(i));
            }
        },
        Startup: function() {
            var e = MathJax.Extension.collapsible;
            e && e.Dependent(h), h.addDefaults();
        }
    };
    MathJax.Hub.Register.StartupHook("End Extensions", function() {
        h[!1 === s.explorer ? "Disable" : "Enable"](), MathJax.Hub.Startup.signal.Post("Explorer Ready"), 
        MathJax.Hub.Register.StartupHook("MathMenu Ready", function() {
            l = MathJax.Menu.cookie;
            var e, t = MathJax.Menu.ITEM, a = MathJax.Menu.menu, i = {
                action: u.Reset
            }, n = {
                action: h.speechOption
            }, o = t.SUBMENU([ "Explorer", "Explorer" ], t.CHECKBOX([ "Active", "Active" ], "explorer", {
                action: function(e) {
                    h[s.explorer ? "Enable" : "Disable"](!0, !0), MathJax.Menu.saveCookie();
                }
            }), t.RULE(), t.CHECKBOX([ "Walker", "Walker" ], "Assistive-walker"), t.SUBMENU([ "Highlight", "Highlight" ], t.RADIO([ "none", "None" ], "Assistive-highlight", i), t.RADIO([ "hover", "Hover" ], "Assistive-highlight", i), t.RADIO([ "flame", "Flame" ], "Assistive-highlight", i)), t.SUBMENU([ "Background", "Background" ], t.RADIO([ "blue", "Blue" ], "Assistive-background", i), t.RADIO([ "red", "Red" ], "Assistive-background", i), t.RADIO([ "green", "Green" ], "Assistive-background", i), t.RADIO([ "yellow", "Yellow" ], "Assistive-background", i), t.RADIO([ "cyan", "Cyan" ], "Assistive-background", i), t.RADIO([ "magenta", "Magenta" ], "Assistive-background", i), t.RADIO([ "white", "White" ], "Assistive-background", i), t.RADIO([ "black", "Black" ], "Assistive-background", i)), t.SUBMENU([ "Foreground", "Foreground" ], t.RADIO([ "black", "Black" ], "Assistive-foreground", i), t.RADIO([ "white", "White" ], "Assistive-foreground", i), t.RADIO([ "magenta", "Magenta" ], "Assistive-foreground", i), t.RADIO([ "cyan", "Cyan" ], "Assistive-foreground", i), t.RADIO([ "yellow", "Yellow" ], "Assistive-foreground", i), t.RADIO([ "green", "Green" ], "Assistive-foreground", i), t.RADIO([ "red", "Red" ], "Assistive-foreground", i), t.RADIO([ "blue", "Blue" ], "Assistive-foreground", i)), t.RULE(), t.CHECKBOX([ "SpeechOutput", "Speech Output" ], "Assistive-speech", {
                action: u.SpeechOutput
            }), t.CHECKBOX([ "Subtitles", "Subtitles" ], "Assistive-subtitle", {
                disabled: !s["Assistive-speech"]
            }), t.RULE(), t.SUBMENU([ "Mathspeak", "Mathspeak Rules" ], t.RADIO([ "mathspeak-default", "Verbose" ], "Assistive-ruleset", n), t.RADIO([ "mathspeak-brief", "Brief" ], "Assistive-ruleset", n), t.RADIO([ "mathspeak-sbrief", "Superbrief" ], "Assistive-ruleset", n)), t.RADIO([ "clearspeak-default", "Clearspeak Rules" ], "Assistive-ruleset", n), t.SUBMENU([ "Chromevox", "ChromeVox Rules" ], t.RADIO([ "chromevox-default", "Verbose" ], "Assistive-ruleset", n), t.RADIO([ "chromevox-alternative", "Alternative" ], "Assistive-ruleset", n))), r = (a.FindId("Accessibility") || {}).submenu;
            r ? null !== (e = r.IndexOfId("Explorer")) ? r.items[e] = o : (e = r.IndexOfId("CollapsibleMath"), 
            r.items.splice(e + 1, 0, o)) : (e = a.IndexOfId("CollapsibleMath"), a.items.splice(e + 1, 0, o)), 
            s.explorer || h.DisableMenus(!0);
        }, 20);
    }, 20);
}), MathJax.Hub.Register.StartupHook("SVG Jax Ready", function() {
    MathJax.Hub.Config({
        SVG: {
            addMMLclasses: !0
        }
    });
    var t, e = MathJax.OutputJax.SVG;
    parseFloat(e.version) < 2.7 && (t = e.getJaxFromMath, e.Augment({
        getJaxFromMath: function(e) {
            return e.parentNode.className.match(/MathJax_SVG_Display/) && (e = e.parentNode), 
            t.call(this, e);
        }
    }));
}), 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");
});