math_util.js revision cedac228d2dd51db4b79ea1e72c7f249408ee061
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 9goog.provide('cvox.MathUtil'); 10 11goog.require('cvox.ChromeVox'); 12goog.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 */ 22cvox.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 */ 34cvox.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 */ 52cvox.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 */ 63cvox.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 */ 78cvox.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 */ 87cvox.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 */ 109cvox.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 */ 118cvox.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 */ 139cvox.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 */ 148cvox.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 */ 164cvox.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 */ 173cvox.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 */ 191cvox.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 */ 202cvox.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 */ 215cvox.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 */ 226cvox.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 */ 236cvox.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 */ 248cvox.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 */ 261cvox.MathUtil.union = function(a, b) { 262 return a.concat(b.filter(function(x) {return a.indexOf(x) < 0;})); 263}; 264