Home | History | Annotate | Download | only in common
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 /**
      6  * @fileoverview DOM utility functions to aid in math expressions navigation.
      7  */
      8 
      9 goog.provide('cvox.MathUtil');
     10 
     11 goog.require('cvox.ChromeVox');
     12 goog.require('cvox.XpathUtil');
     13 
     14 
     15 /**
     16  * Checks if a node is in a given class of MathML nodes.
     17  * @private
     18  * @param {!Node} node The node to test.
     19  * @param {Array.<string>} tags List of tag names.
     20  * @return {boolean} True if node has a tag name included in tags.
     21  */
     22 cvox.MathUtil.isMathmlNodeOfClass_ = function(node, tags) {
     23   return tags.indexOf(node.tagName.toUpperCase()) != -1;
     24 };
     25 
     26 
     27 /**
     28  * Checks if a node is in a given class of MathJax nodes.
     29  * @private
     30  * @param {!Node} node The node to test.
     31  * @param {Array.<string>} tags List of tag names.
     32  * @return {boolean} True if node has a tag name included in tags.
     33  */
     34 cvox.MathUtil.isMathjaxNodeOfClass_ = function(node, tags) {
     35   if (node.tagName == 'SPAN') {
     36     var classes = node.className.split(' ');
     37     return classes.some(function(x)
     38                         {return tags.indexOf(x.toUpperCase()) != -1;});
     39   }
     40   return false;
     41 };
     42 
     43 
     44 /**
     45  * Checks if a node is an element node that belongs to a given class
     46  * of MathML or MathJax nodes.
     47  * @private
     48  * @param {!Node} node The node to test.
     49  * @param {Array.<string>} tags List of tag names.
     50  * @return {boolean} True if node has a tag name included in tags.
     51  */
     52 cvox.MathUtil.isMathNodeOfClass_ = function(node, tags) {
     53   return (node.nodeType == Node.ELEMENT_NODE &&
     54           (cvox.MathUtil.isMathmlNodeOfClass_(node, tags) ||
     55            cvox.MathUtil.isMathjaxNodeOfClass_(node, tags)));
     56 };
     57 
     58 
     59 /**
     60  * Array of MathML Token Elements.
     61  * @type {!Array.<string>}
     62  */
     63 cvox.MathUtil.TOKEN_LIST = ['MI', 'MN', 'MO', 'MTEXT', 'MSPACE', 'MS'];
     64 
     65 
     66 /**
     67  *  Checks if an element of a math expression is a Token Element.
     68  * Token elements are the following:
     69  * <mi> identifier.
     70  * <mn> number.
     71  * <mo> operator, fence, or separator.
     72  * <mtext> text.
     73  * <mspace> space.
     74  * <ms> string literal.
     75  * @param {!Node} element The element of the math expression.
     76  * @return {boolean} True if element is a token.
     77  */
     78 cvox.MathUtil.isToken = function(element) {
     79   return cvox.MathUtil.isMathNodeOfClass_(element, cvox.MathUtil.TOKEN_LIST);
     80 };
     81 
     82 
     83 /**
     84  * Array of MathML Layout Schemata.
     85  * @type {!Array.<string>}
     86  */
     87 cvox.MathUtil.LAYOUT_LIST = ['MROW', 'MFRAC', 'MSQRT', 'MROOT', 'MSTYLE',
     88                              'MERROR', 'MPADDED', 'MPHANTOM', 'MFENCED',
     89                              'MENCLOSE'];
     90 
     91 
     92 /**
     93  *  Checks if an element of a math expression is a Layout Schema.
     94  * Layout elements are the following:
     95  * <mrow> group any number of sub-expressions horizontally
     96  * <mfrac> form a fraction from two sub-expressions
     97  * <msqrt> form a square root (radical without an index)
     98  * <mroot> form a radical with specified index
     99  * <mstyle> style change
    100  * <merror> enclose a syntax error message from a preprocessor
    101  * <mpadded> adjust space around content
    102  * <mphantom> make content invisible but preserve its size
    103  * <mfenced> surround content with a pair of fences
    104  * <menclose> enclose content with a stretching symbol such as a long
    105  * division sign.
    106  * @param {!Node} element The element of the math expression.
    107  * @return {boolean} True if element is a layout schema.
    108  */
    109 cvox.MathUtil.isLayout = function(element) {
    110   return cvox.MathUtil.isMathNodeOfClass_(element, cvox.MathUtil.LAYOUT_LIST);
    111 };
    112 
    113 
    114 /**
    115  * Array of MathML Script Schemata.
    116  * @type {!Array.<string>}
    117  */
    118 cvox.MathUtil.SCRIPT_LIST = ['MSUB', 'MSUP', 'MSUBSUP', 'MUNDER', 'MOVER',
    119                              'MUNDEROVER', 'MMULTISCRIPTS', 'MPRESCRIPTS'];
    120 
    121 
    122 /**
    123  *  Checks if an element of a math expression is a Script Schema.
    124  * Script elements are the following:
    125  * <msub> attach a subscript to a base.
    126  * <msup> attach a superscript to a base.
    127  * <msubsup> attach a subscript-superscript pair to a base.
    128  * <munder> attach an underscript to a base.
    129  * <mover> attach an overscript to a base.
    130  * <munderover> attach an underscript-overscript pair to a base.
    131  * <mmultiscripts> attach prescripts and tensor indices to a base.
    132  * Prescripts are optional.
    133  * <mprescripts> two elements prescripts of mmultiscripts. Only makes sense
    134  * in that environment (although not illegal outside)!  Two
    135  * arguments mandatory (can be <none/>).
    136  * @param {!Node} element The element of the math expression.
    137  * @return {boolean} True if element is a script schema.
    138  */
    139 cvox.MathUtil.isScript = function(element) {
    140   return cvox.MathUtil.isMathNodeOfClass_(element, cvox.MathUtil.SCRIPT_LIST);
    141 };
    142 
    143 
    144 /**
    145  * Array of MathML Table and Matrix tokens.
    146  * @type {!Array.<string>}
    147  */
    148 cvox.MathUtil.TABLES_LIST = ['MTABLE', 'MLABELEDTR', 'MTR', 'MTD',
    149                              'MALIGNGROUP', 'MALIGNMARK'];
    150 
    151 
    152 /**
    153  *  Checks if an element of a math expression is a Tables Schema.
    154  * Tables elements are the following:
    155  * <mtable> table or matrix.
    156  * <mlabeledtr> row in a table or matrix with a label or equation number.
    157  * <mtr> row in a table or matrix.
    158  * <mtd> one entry in a table or matrix.
    159  * <maligngroup> and
    160  * <malignmark> alignment markers.
    161  * @param {!Node} element The element of the math expression.
    162  * @return {boolean} True if element is a tables schema.
    163  */
    164 cvox.MathUtil.isTables = function(element) {
    165   return cvox.MathUtil.isMathNodeOfClass_(element, cvox.MathUtil.TABLES_LIST);
    166 };
    167 
    168 
    169 /**
    170  * Array of MathML Elementary Layout Schemata.
    171  * @type {!Array.<string>}
    172  */
    173 cvox.MathUtil.ELEMENTARY_LIST = ['MSTACK', 'MLONGDIV', 'MSGROUP', 'MSROW',
    174                                  'MSCARRIES', 'MSCARRY', 'MSLINE'];
    175 
    176 
    177 /**
    178  *  Checks if an element of a math expression is a Elementary Schema.
    179  * Elementary elements are the following:
    180  * <mstack> columns of aligned characters.
    181  * <mlongdiv> similar to msgroup, with the addition of a divisor and result.
    182  * <msgroup> a group of rows in an mstack that are shifted by similar amounts.
    183  * <msrow> a row in an mstack.
    184  * <mscarries> row in an mstack that whose contents represent carries
    185  *             or borrows.
    186  * <mscarry> one entry in an mscarries.
    187  * <msline> horizontal line inside of mstack.
    188  * @param {!Node} element The element of the math expression.
    189  * @return {boolean} True if element is a elementary schema.
    190  */
    191 cvox.MathUtil.isElementary = function(element) {
    192   return cvox.MathUtil.isMathNodeOfClass_(element,
    193                                           cvox.MathUtil.ELEMENTARY_LIST);
    194 };
    195 
    196 
    197 /**
    198  * Array of all valid tags in a MathML expression.
    199  * This is a union of all other token lists.
    200  * @type {!Array.<string>}
    201  */
    202 cvox.MathUtil.MATHML_TAG_LIST = [cvox.MathUtil.TOKEN_LIST,
    203                                  cvox.MathUtil.LAYOUT_LIST,
    204                                  cvox.MathUtil.SCRIPT_LIST,
    205                                  cvox.MathUtil.TABLES_LIST,
    206                                  cvox.MathUtil.ELEMENTARY_LIST].reduce(
    207                                      function(x, y) { return x.concat(y); });
    208 
    209 
    210 /**
    211  * Checks if a node is valid element of a MathML expression.
    212  * @param {!Node} element The element of the math expression.
    213  * @return {boolean} True if element has a valid MathML tag.
    214  */
    215 cvox.MathUtil.isMathmlTag = function(element) {
    216   return cvox.MathUtil.isMathNodeOfClass_(element,
    217                                           cvox.MathUtil.MATHML_TAG_LIST);
    218 };
    219 
    220 
    221 /**
    222  * Array of MathML Whitespace and Alignment tokens.
    223  * These are elements that can occur in the other token lists.
    224  * @type {!Array.<string>}
    225  */
    226 cvox.MathUtil.WHITESPACE_LIST = ['MSROW', 'MROW', 'MSPACE',
    227                                  'MPHANTOM', 'MPADDED'];
    228 
    229 
    230 /**
    231  * Checks if an element of a math expression is whitespace or an
    232  * alignment marker.
    233  * @param {!Node} element The element of the math expression.
    234  * @return {boolean} True if element is a whitespace node.
    235  */
    236 cvox.MathUtil.isWhitespace = function(element) {
    237   return cvox.MathUtil.isMathNodeOfClass_(element,
    238                                           cvox.MathUtil.WHITESPACE_LIST);
    239 };
    240 
    241 
    242 /**
    243  * Checks if an element of a math expression is a legal mathml markup element
    244  * but not a whitespace or an alignment marker.
    245  * @param {!Node} element The element of the math expression.
    246  * @return {boolean} True if element is a non-whitespace node.
    247  */
    248 cvox.MathUtil.isNotWhitespace = function(element) {
    249   return (cvox.MathUtil.isMathmlTag(element) &&
    250           !cvox.MathUtil.isWhitespace(element));
    251 };
    252 
    253 
    254 /**
    255  * Computes the union of two arrays (not in a strictly set theoretical sense
    256  * as all duplicate elements in either array still remain as duplicates!).
    257  * @param {Array} a An array.
    258  * @param {Array} b Another array.
    259  * @return {Array} Union of a and b.
    260  */
    261 cvox.MathUtil.union = function(a, b) {
    262   return a.concat(b.filter(function(x) {return a.indexOf(x) < 0;}));
    263 };
    264