www

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

AssistiveMML.js (5942B)


      1 /* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
      2 /* vim: set ts=2 et sw=2 tw=80: */
      3 
      4 /*************************************************************
      5  *
      6  *  MathJax/extensions/AssistiveMML.js
      7  *  
      8  *  Implements an extension that inserts hidden MathML into the
      9  *  page for screen readers or other asistive technology.
     10  *  
     11  *  ---------------------------------------------------------------------
     12  *  
     13  *  Copyright (c) 2015 The MathJax Consortium
     14  * 
     15  *  Licensed under the Apache License, Version 2.0 (the "License");
     16  *  you may not use this file except in compliance with the License.
     17  *  You may obtain a copy of the License at
     18  * 
     19  *      http://www.apache.org/licenses/LICENSE-2.0
     20  * 
     21  *  Unless required by applicable law or agreed to in writing, software
     22  *  distributed under the License is distributed on an "AS IS" BASIS,
     23  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     24  *  See the License for the specific language governing permissions and
     25  *  limitations under the License.
     26  */
     27 
     28 (function (AJAX,CALLBACK,HUB,HTML) {
     29   var SETTINGS = HUB.config.menuSettings;
     30   
     31   var AssistiveMML = MathJax.Extension["AssistiveMML"] = {
     32     version: "2.6.1",
     33     
     34     config: HUB.CombineConfig("AssistiveMML",{
     35       disabled: false,
     36       styles: {
     37         ".MJX_Assistive_MathML": {
     38           position:"absolute!important",
     39           top: 0, left: 0,
     40           clip: (HUB.Browser.isMSIE && (document.documentMode||0) < 8 ?
     41                  "rect(1px 1px 1px 1px)" : "rect(1px, 1px, 1px, 1px)"),
     42           padding: "1px 0 0 0!important",
     43           border: "0!important",
     44           height: "1px!important",
     45           width: "1px!important",
     46           overflow: "hidden!important",
     47           display:"block!important",
     48           //
     49           //  Don't allow the assistive MathML become part of the selection
     50           //
     51           "-webkit-touch-callout": "none",
     52           "-webkit-user-select": "none",
     53           "-khtml-user-select": "none",
     54           "-moz-user-select": "none",
     55           "-ms-user-select": "none",
     56           "user-select": "none"
     57         },
     58         ".MJX_Assistive_MathML.MJX_Assistive_MathML_Block": {
     59           width: "100%!important"
     60         }
     61       }
     62     }),
     63     
     64     Config: function () {
     65       if (!this.config.disabled && SETTINGS.assistiveMML == null)
     66         HUB.Config({menuSettings:{assistiveMML:true}});
     67       AJAX.Styles(this.config.styles);
     68       HUB.Register.MessageHook("End Math",function (msg) {
     69         if (SETTINGS.assistiveMML) return AssistiveMML.AddAssistiveMathML(msg[1])
     70       });
     71     },
     72     
     73     //
     74     //  This sets up a state object that lists the jax and index into the jax,
     75     //    and a dummy callback that is used to synchronizing with MathJax.
     76     //    It will be called when the jax are all processed, and that will
     77     //    let the MathJax queue continue (it will block until then).
     78     //
     79     AddAssistiveMathML: function (node) {
     80       var state = {
     81         jax: HUB.getAllJax(node), i: 0,
     82         callback: MathJax.Callback({})
     83       };
     84       this.HandleMML(state);
     85       return state.callback;
     86     },
     87 
     88     //
     89     //  This removes the data-mathml attribute and the assistive MathML from
     90     //  all the jax.
     91     //
     92     RemoveAssistiveMathML: function (node) {
     93       var jax = HUB.getAllJax(node), frame;
     94       for (var i = 0, m = jax.length; i < m; i++) {
     95         frame = document.getElementById(jax[i].inputID+"-Frame");
     96         if (frame && frame.getAttribute("data-mathml")) {
     97           frame.removeAttribute("data-mathml");
     98           if (frame.lastChild && frame.lastChild.className.match(/MJX_Assistive_MathML/))
     99             frame.removeChild(frame.lastChild);
    100         }
    101       }
    102     },
    103 
    104     //
    105     //  For each jax in the state, look up the frame.
    106     //  If the jax doesn't use NativeMML and hasn't already been handled:
    107     //    Get the MathML for the jax, taking resets into account.
    108     //    Add a data-mathml attribute to the frame, and
    109     //    Create a span that is not visible on screen and put the MathML in it,
    110     //      and add it to the frame.
    111     //  When all the jax are processed, call the callback.
    112     //
    113     HandleMML: function (state) {
    114       var m = state.jax.length, jax, mml, frame, span;
    115       while (state.i < m) {
    116         jax = state.jax[state.i];
    117         frame = document.getElementById(jax.inputID+"-Frame");
    118         if (jax.outputJax !== "NativeMML" && frame && !frame.getAttribute("data-mathml")) {
    119           try {
    120             mml = jax.root.toMathML("").replace(/\n */g,"").replace(/<!--.*?-->/g,"");
    121           } catch (err) {
    122             if (!err.restart) throw err; // an actual error
    123             return MathJax.Callback.After(["HandleMML",this,state],err.restart);
    124           }
    125           frame.setAttribute("data-mathml",mml);
    126           span = HTML.addElement(frame,"span",{
    127             isMathJax: true, unselectable: "on",
    128             className: "MJX_Assistive_MathML"
    129               + (jax.root.Get("display") === "block" ? " MJX_Assistive_MathML_Block" : "")
    130           });
    131           span.innerHTML = mml;
    132           frame.style.position = "relative";
    133           frame.setAttribute("role","presentation");
    134           frame.firstChild.setAttribute("aria-hidden","true");
    135           span.setAttribute("role","presentation");
    136         }
    137         state.i++;
    138       }
    139       state.callback();
    140     }
    141     
    142   };
    143 
    144   HUB.Startup.signal.Post("AssistiveMML Ready");
    145 
    146 })(MathJax.Ajax,MathJax.Callback,MathJax.Hub,MathJax.HTML);
    147 
    148 //
    149 //  Make sure the toMathML extension is loaded before we signal
    150 //  the load complete for this extension.  Then wait for the end
    151 //  of the user configuration before configuring this extension. 
    152 //
    153 MathJax.Callback.Queue(
    154   ["Require",MathJax.Ajax,"[MathJax]/extensions/toMathML.js"],
    155   ["loadComplete",MathJax.Ajax,"[MathJax]/extensions/AssistiveMML.js"],
    156   function () {
    157     MathJax.Hub.Register.StartupHook("End Config",["Config",MathJax.Extension.AssistiveMML]);
    158   }
    159 );
    160