| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 /** | 5 /** |
| 6 * @fileoverview A collection of JavaScript utilities used to simplify working | 6 * @fileoverview A collection of JavaScript utilities used to simplify working |
| 7 * with the DOM. | 7 * with the DOM. |
| 8 */ | 8 */ |
| 9 | 9 |
| 10 | 10 |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 101 'AUDIO' : 'tag_audio', | 101 'AUDIO' : 'tag_audio', |
| 102 'BUTTON' : 'tag_button', | 102 'BUTTON' : 'tag_button', |
| 103 'SELECT' : 'tag_select', | 103 'SELECT' : 'tag_select', |
| 104 'TABLE' : 'tag_table', | 104 'TABLE' : 'tag_table', |
| 105 'TEXTAREA' : 'tag_textarea', | 105 'TEXTAREA' : 'tag_textarea', |
| 106 'VIDEO' : 'tag_video' | 106 'VIDEO' : 'tag_video' |
| 107 }; | 107 }; |
| 108 | 108 |
| 109 /** | 109 /** |
| 110 * These tags are treated as text formatters. | 110 * These tags are treated as text formatters. |
| 111 * @type {Array.<string>} | 111 * @type {Array<string>} |
| 112 */ | 112 */ |
| 113 cvox.DomUtil.FORMATTING_TAGS = | 113 cvox.DomUtil.FORMATTING_TAGS = |
| 114 ['B', 'BIG', 'CITE', 'CODE', 'DFN', 'EM', 'I', 'KBD', 'SAMP', 'SMALL', | 114 ['B', 'BIG', 'CITE', 'CODE', 'DFN', 'EM', 'I', 'KBD', 'SAMP', 'SMALL', |
| 115 'SPAN', 'STRIKE', 'STRONG', 'SUB', 'SUP', 'U', 'VAR']; | 115 'SPAN', 'STRIKE', 'STRONG', 'SUB', 'SUP', 'U', 'VAR']; |
| 116 | 116 |
| 117 /** | 117 /** |
| 118 * Determine if the given node is visible on the page. This does not check if | 118 * Determine if the given node is visible on the page. This does not check if |
| 119 * it is inside the document view-port as some sites try to communicate with | 119 * it is inside the document view-port as some sites try to communicate with |
| 120 * screen readers with such elements. | 120 * screen readers with such elements. |
| 121 * @param {Node} node The node to determine as visible or not. | 121 * @param {Node} node The node to determine as visible or not. |
| (...skipping 817 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 939 } | 939 } |
| 940 return text; | 940 return text; |
| 941 }; | 941 }; |
| 942 | 942 |
| 943 | 943 |
| 944 /** | 944 /** |
| 945 * Search the whole page for any aria-labelledby attributes and collect | 945 * Search the whole page for any aria-labelledby attributes and collect |
| 946 * the complete set of ids they map to, so that we can skip elements that | 946 * the complete set of ids they map to, so that we can skip elements that |
| 947 * just label other elements and not double-speak them. We cache this | 947 * just label other elements and not double-speak them. We cache this |
| 948 * result and then throw it away at the next event loop. | 948 * result and then throw it away at the next event loop. |
| 949 * @return {Object.<string, boolean>} Set of all ids that are mapped | 949 * @return {Object<string, boolean>} Set of all ids that are mapped |
| 950 * by aria-labelledby. | 950 * by aria-labelledby. |
| 951 */ | 951 */ |
| 952 cvox.DomUtil.getLabelledByTargets = function() { | 952 cvox.DomUtil.getLabelledByTargets = function() { |
| 953 if (cvox.labelledByTargets) { | 953 if (cvox.labelledByTargets) { |
| 954 return cvox.labelledByTargets; | 954 return cvox.labelledByTargets; |
| 955 } | 955 } |
| 956 | 956 |
| 957 // Start by getting all elements with | 957 // Start by getting all elements with |
| 958 // aria-labelledby on the page since that's probably a short list, | 958 // aria-labelledby on the page since that's probably a short list, |
| 959 // then see if any of those ids overlap with an id in this element's | 959 // then see if any of those ids overlap with an id in this element's |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1172 | 1172 |
| 1173 return true; | 1173 return true; |
| 1174 }; | 1174 }; |
| 1175 | 1175 |
| 1176 | 1176 |
| 1177 /** | 1177 /** |
| 1178 * Returns a list of all the ancestors of a given node. The last element | 1178 * Returns a list of all the ancestors of a given node. The last element |
| 1179 * is the current node. | 1179 * is the current node. |
| 1180 * | 1180 * |
| 1181 * @param {Node} targetNode The node to get ancestors for. | 1181 * @param {Node} targetNode The node to get ancestors for. |
| 1182 * @return {Array.<Node>} An array of ancestors for the targetNode. | 1182 * @return {Array<Node>} An array of ancestors for the targetNode. |
| 1183 */ | 1183 */ |
| 1184 cvox.DomUtil.getAncestors = function(targetNode) { | 1184 cvox.DomUtil.getAncestors = function(targetNode) { |
| 1185 var ancestors = new Array(); | 1185 var ancestors = new Array(); |
| 1186 while (targetNode) { | 1186 while (targetNode) { |
| 1187 ancestors.push(targetNode); | 1187 ancestors.push(targetNode); |
| 1188 targetNode = targetNode.parentNode; | 1188 targetNode = targetNode.parentNode; |
| 1189 } | 1189 } |
| 1190 ancestors.reverse(); | 1190 ancestors.reverse(); |
| 1191 while (ancestors.length && !ancestors[0].tagName && !ancestors[0].nodeValue) { | 1191 while (ancestors.length && !ancestors[0].tagName && !ancestors[0].nodeValue) { |
| 1192 ancestors.shift(); | 1192 ancestors.shift(); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1224 /** | 1224 /** |
| 1225 * Returns an array of ancestors that are unique for the currentNode when | 1225 * Returns an array of ancestors that are unique for the currentNode when |
| 1226 * compared to the previousNode. Having such an array is useful in generating | 1226 * compared to the previousNode. Having such an array is useful in generating |
| 1227 * the node information (identifying when interesting node boundaries have been | 1227 * the node information (identifying when interesting node boundaries have been |
| 1228 * crossed, etc.). | 1228 * crossed, etc.). |
| 1229 * | 1229 * |
| 1230 * @param {Node} previousNode The previous node. | 1230 * @param {Node} previousNode The previous node. |
| 1231 * @param {Node} currentNode The current node. | 1231 * @param {Node} currentNode The current node. |
| 1232 * @param {boolean=} opt_fallback True returns node's ancestors in the case | 1232 * @param {boolean=} opt_fallback True returns node's ancestors in the case |
| 1233 * where node's ancestors is a subset of previousNode's ancestors. | 1233 * where node's ancestors is a subset of previousNode's ancestors. |
| 1234 * @return {Array.<Node>} An array of unique ancestors for the current node | 1234 * @return {Array<Node>} An array of unique ancestors for the current node |
| 1235 * (inclusive). | 1235 * (inclusive). |
| 1236 */ | 1236 */ |
| 1237 cvox.DomUtil.getUniqueAncestors = function( | 1237 cvox.DomUtil.getUniqueAncestors = function( |
| 1238 previousNode, currentNode, opt_fallback) { | 1238 previousNode, currentNode, opt_fallback) { |
| 1239 var prevAncestors = cvox.DomUtil.getAncestors(previousNode); | 1239 var prevAncestors = cvox.DomUtil.getAncestors(previousNode); |
| 1240 var currentAncestors = cvox.DomUtil.getAncestors(currentNode); | 1240 var currentAncestors = cvox.DomUtil.getAncestors(currentNode); |
| 1241 var divergence = cvox.DomUtil.compareAncestors(prevAncestors, | 1241 var divergence = cvox.DomUtil.compareAncestors(prevAncestors, |
| 1242 currentAncestors); | 1242 currentAncestors); |
| 1243 var diff = currentAncestors.slice(divergence); | 1243 var diff = currentAncestors.slice(divergence); |
| 1244 return (diff.length == 0 && opt_fallback) ? currentAncestors : diff; | 1244 return (diff.length == 0 && opt_fallback) ? currentAncestors : diff; |
| (...skipping 716 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1961 * is not. | 1961 * is not. |
| 1962 */ | 1962 */ |
| 1963 cvox.DomUtil.getContainingTable = function(node, kwargs) { | 1963 cvox.DomUtil.getContainingTable = function(node, kwargs) { |
| 1964 var ancestors = cvox.DomUtil.getAncestors(node); | 1964 var ancestors = cvox.DomUtil.getAncestors(node); |
| 1965 return cvox.DomUtil.findTableNodeInList(ancestors, kwargs); | 1965 return cvox.DomUtil.findTableNodeInList(ancestors, kwargs); |
| 1966 }; | 1966 }; |
| 1967 | 1967 |
| 1968 | 1968 |
| 1969 /** | 1969 /** |
| 1970 * Extracts a table node from a list of nodes. | 1970 * Extracts a table node from a list of nodes. |
| 1971 * @param {Array.<Node>} nodes The list of nodes. | 1971 * @param {Array<Node>} nodes The list of nodes. |
| 1972 * @param {{allowCaptions: (undefined|boolean)}=} kwargs Optional named args. | 1972 * @param {{allowCaptions: (undefined|boolean)}=} kwargs Optional named args. |
| 1973 * allowCaptions: If true, will return true even if inside a caption. False | 1973 * allowCaptions: If true, will return true even if inside a caption. False |
| 1974 * by default. | 1974 * by default. |
| 1975 * @return {Node} The table node if the list of nodes contains a table node. | 1975 * @return {Node} The table node if the list of nodes contains a table node. |
| 1976 * Null if it does not. | 1976 * Null if it does not. |
| 1977 */ | 1977 */ |
| 1978 cvox.DomUtil.findTableNodeInList = function(nodes, kwargs) { | 1978 cvox.DomUtil.findTableNodeInList = function(nodes, kwargs) { |
| 1979 kwargs = kwargs || {allowCaptions: false}; | 1979 kwargs = kwargs || {allowCaptions: false}; |
| 1980 // Don't include the caption node because it is actually rendered outside | 1980 // Don't include the caption node because it is actually rendered outside |
| 1981 // of the table. | 1981 // of the table. |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2204 cvox.DomUtil.findNodes_(root, p, rv, false, 10000); | 2204 cvox.DomUtil.findNodes_(root, p, rv, false, 10000); |
| 2205 return rv.length; | 2205 return rv.length; |
| 2206 }; | 2206 }; |
| 2207 | 2207 |
| 2208 | 2208 |
| 2209 /** | 2209 /** |
| 2210 * Finds the first or all the descendant nodes that match the filter function, | 2210 * Finds the first or all the descendant nodes that match the filter function, |
| 2211 * using a depth first search. | 2211 * using a depth first search. |
| 2212 * @param {Node} root The root of the tree to search. | 2212 * @param {Node} root The root of the tree to search. |
| 2213 * @param {function(Node) : boolean} p The filter function. | 2213 * @param {function(Node) : boolean} p The filter function. |
| 2214 * @param {Array.<Node>} rv The found nodes are added to this array. | 2214 * @param {Array<Node>} rv The found nodes are added to this array. |
| 2215 * @param {boolean} findOne If true we exit after the first found node. | 2215 * @param {boolean} findOne If true we exit after the first found node. |
| 2216 * @param {number} maxChildCount The max child count. This is used as a kill | 2216 * @param {number} maxChildCount The max child count. This is used as a kill |
| 2217 * switch - if there are more nodes than this, terminate the search. | 2217 * switch - if there are more nodes than this, terminate the search. |
| 2218 * @return {boolean} Whether the search is complete or not. True in case | 2218 * @return {boolean} Whether the search is complete or not. True in case |
| 2219 * findOne is true and the node is found. False otherwise. This is the | 2219 * findOne is true and the node is found. False otherwise. This is the |
| 2220 * findNodes_ function from goog.dom: | 2220 * findNodes_ function from goog.dom: |
| 2221 * http://code.google.com/p/closure-library/source/browse/trunk/closure/goog/dom
/dom.js. | 2221 * http://code.google.com/p/closure-library/source/browse/trunk/closure/goog/dom
/dom.js. |
| 2222 * @private | 2222 * @private |
| 2223 */ | 2223 */ |
| 2224 cvox.DomUtil.findNodes_ = function(root, p, rv, findOne, maxChildCount) { | 2224 cvox.DomUtil.findNodes_ = function(root, p, rv, findOne, maxChildCount) { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 2252 for (var i = 0; i < nodeList.length; i++) { | 2252 for (var i = 0; i < nodeList.length; i++) { |
| 2253 nodeArray.push(nodeList[i]); | 2253 nodeArray.push(nodeList[i]); |
| 2254 } | 2254 } |
| 2255 return nodeArray; | 2255 return nodeArray; |
| 2256 }; | 2256 }; |
| 2257 | 2257 |
| 2258 | 2258 |
| 2259 /** | 2259 /** |
| 2260 * Creates a new element with the same attributes and no children. | 2260 * Creates a new element with the same attributes and no children. |
| 2261 * @param {Node|Text} node A node to clone. | 2261 * @param {Node|Text} node A node to clone. |
| 2262 * @param {Object.<string, boolean>} skipattrs Set the attribute to true to | 2262 * @param {Object<string, boolean>} skipattrs Set the attribute to true to |
| 2263 * skip it during cloning. | 2263 * skip it during cloning. |
| 2264 * @return {Node|Text} The cloned node. | 2264 * @return {Node|Text} The cloned node. |
| 2265 */ | 2265 */ |
| 2266 cvox.DomUtil.shallowChildlessClone = function(node, skipattrs) { | 2266 cvox.DomUtil.shallowChildlessClone = function(node, skipattrs) { |
| 2267 if (node.nodeName == '#text') { | 2267 if (node.nodeName == '#text') { |
| 2268 return document.createTextNode(node.nodeValue); | 2268 return document.createTextNode(node.nodeValue); |
| 2269 } | 2269 } |
| 2270 | 2270 |
| 2271 if (node.nodeName == '#comment') { | 2271 if (node.nodeName == '#comment') { |
| 2272 return document.createComment(node.nodeValue); | 2272 return document.createComment(node.nodeValue); |
| 2273 } | 2273 } |
| 2274 | 2274 |
| 2275 var ret = document.createElement(node.nodeName); | 2275 var ret = document.createElement(node.nodeName); |
| 2276 for (var i = 0; i < node.attributes.length; ++i) { | 2276 for (var i = 0; i < node.attributes.length; ++i) { |
| 2277 var attr = node.attributes[i]; | 2277 var attr = node.attributes[i]; |
| 2278 if (skipattrs && skipattrs[attr.nodeName]) { | 2278 if (skipattrs && skipattrs[attr.nodeName]) { |
| 2279 continue; | 2279 continue; |
| 2280 } | 2280 } |
| 2281 ret.setAttribute(attr.nodeName, attr.nodeValue); | 2281 ret.setAttribute(attr.nodeName, attr.nodeValue); |
| 2282 } | 2282 } |
| 2283 return ret; | 2283 return ret; |
| 2284 }; | 2284 }; |
| 2285 | 2285 |
| 2286 | 2286 |
| 2287 /** | 2287 /** |
| 2288 * Creates a new element with the same attributes and clones of children. | 2288 * Creates a new element with the same attributes and clones of children. |
| 2289 * @param {Node|Text} node A node to clone. | 2289 * @param {Node|Text} node A node to clone. |
| 2290 * @param {Object.<string, boolean>} skipattrs Set the attribute to true to | 2290 * @param {Object<string, boolean>} skipattrs Set the attribute to true to |
| 2291 * skip it during cloning. | 2291 * skip it during cloning. |
| 2292 * @return {Node|Text} The cloned node. | 2292 * @return {Node|Text} The cloned node. |
| 2293 */ | 2293 */ |
| 2294 cvox.DomUtil.deepClone = function(node, skipattrs) { | 2294 cvox.DomUtil.deepClone = function(node, skipattrs) { |
| 2295 var ret = cvox.DomUtil.shallowChildlessClone(node, skipattrs); | 2295 var ret = cvox.DomUtil.shallowChildlessClone(node, skipattrs); |
| 2296 for (var i = 0; i < node.childNodes.length; ++i) { | 2296 for (var i = 0; i < node.childNodes.length; ++i) { |
| 2297 ret.appendChild(cvox.DomUtil.deepClone(node.childNodes[i], skipattrs)); | 2297 ret.appendChild(cvox.DomUtil.deepClone(node.childNodes[i], skipattrs)); |
| 2298 } | 2298 } |
| 2299 return ret; | 2299 return ret; |
| 2300 }; | 2300 }; |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2369 * Null if it is not. | 2369 * Null if it is not. |
| 2370 */ | 2370 */ |
| 2371 cvox.DomUtil.getContainingMath = function(node) { | 2371 cvox.DomUtil.getContainingMath = function(node) { |
| 2372 var ancestors = cvox.DomUtil.getAncestors(node); | 2372 var ancestors = cvox.DomUtil.getAncestors(node); |
| 2373 return cvox.DomUtil.findMathNodeInList(ancestors); | 2373 return cvox.DomUtil.findMathNodeInList(ancestors); |
| 2374 }; | 2374 }; |
| 2375 | 2375 |
| 2376 | 2376 |
| 2377 /** | 2377 /** |
| 2378 * Extracts a math node from a list of nodes. | 2378 * Extracts a math node from a list of nodes. |
| 2379 * @param {Array.<Node>} nodes The list of nodes. | 2379 * @param {Array<Node>} nodes The list of nodes. |
| 2380 * @return {Node} The math node if the list of nodes contains a math node. | 2380 * @return {Node} The math node if the list of nodes contains a math node. |
| 2381 * Null if it does not. | 2381 * Null if it does not. |
| 2382 */ | 2382 */ |
| 2383 cvox.DomUtil.findMathNodeInList = function(nodes) { | 2383 cvox.DomUtil.findMathNodeInList = function(nodes) { |
| 2384 for (var i = 0, node; node = nodes[i]; i++) { | 2384 for (var i = 0, node; node = nodes[i]; i++) { |
| 2385 if (cvox.DomUtil.isMath(node)) { | 2385 if (cvox.DomUtil.isMath(node)) { |
| 2386 return node; | 2386 return node; |
| 2387 } | 2387 } |
| 2388 } | 2388 } |
| 2389 return null; | 2389 return null; |
| 2390 }; | 2390 }; |
| 2391 | 2391 |
| 2392 | 2392 |
| 2393 /** | 2393 /** |
| 2394 * Checks to see wether a node is a math node. | 2394 * Checks to see wether a node is a math node. |
| 2395 * @param {Node} node The node to be tested. | 2395 * @param {Node} node The node to be tested. |
| 2396 * @return {boolean} Whether or not a node is a math node. | 2396 * @return {boolean} Whether or not a node is a math node. |
| 2397 */ | 2397 */ |
| 2398 cvox.DomUtil.isMath = function(node) { | 2398 cvox.DomUtil.isMath = function(node) { |
| 2399 return cvox.DomUtil.isMathml(node) || | 2399 return cvox.DomUtil.isMathml(node) || |
| 2400 cvox.DomUtil.isMathJax(node) || | 2400 cvox.DomUtil.isMathJax(node) || |
| 2401 cvox.DomUtil.isMathImg(node) || | 2401 cvox.DomUtil.isMathImg(node) || |
| 2402 cvox.AriaUtil.isMath(node); | 2402 cvox.AriaUtil.isMath(node); |
| 2403 }; | 2403 }; |
| 2404 | 2404 |
| 2405 | 2405 |
| 2406 /** | 2406 /** |
| 2407 * Specifies node classes in which we expect maths expressions a alt text. | 2407 * Specifies node classes in which we expect maths expressions a alt text. |
| 2408 * @type {{tex: Array.<string>, | 2408 * @type {{tex: Array<string>, |
| 2409 * asciimath: Array.<string>}} | 2409 * asciimath: Array<string>}} |
| 2410 */ | 2410 */ |
| 2411 // These are the classes for which we assume they contain Maths in the ALT or | 2411 // These are the classes for which we assume they contain Maths in the ALT or |
| 2412 // TITLE attribute. | 2412 // TITLE attribute. |
| 2413 // tex: Wikipedia; | 2413 // tex: Wikipedia; |
| 2414 // latex: Wordpress; | 2414 // latex: Wordpress; |
| 2415 // numberedequation, inlineformula, displayformula: MathWorld; | 2415 // numberedequation, inlineformula, displayformula: MathWorld; |
| 2416 cvox.DomUtil.ALT_MATH_CLASSES = { | 2416 cvox.DomUtil.ALT_MATH_CLASSES = { |
| 2417 tex: ['tex', 'latex'], | 2417 tex: ['tex', 'latex'], |
| 2418 asciimath: ['numberedequation', 'inlineformula', 'displayformula'] | 2418 asciimath: ['numberedequation', 'inlineformula', 'displayformula'] |
| 2419 }; | 2419 }; |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2533 if (node.nodeType == Node.ELEMENT_NODE) { | 2533 if (node.nodeType == Node.ELEMENT_NODE) { |
| 2534 return node.tagName; | 2534 return node.tagName; |
| 2535 } | 2535 } |
| 2536 return ''; | 2536 return ''; |
| 2537 }; | 2537 }; |
| 2538 | 2538 |
| 2539 | 2539 |
| 2540 /** | 2540 /** |
| 2541 * Cleaning up a list of nodes to remove empty text nodes. | 2541 * Cleaning up a list of nodes to remove empty text nodes. |
| 2542 * @param {NodeList} nodes The nodes list. | 2542 * @param {NodeList} nodes The nodes list. |
| 2543 * @return {!Array.<Node|string|null>} The cleaned up list of nodes. | 2543 * @return {!Array<Node|string|null>} The cleaned up list of nodes. |
| 2544 */ | 2544 */ |
| 2545 cvox.DomUtil.purgeNodes = function(nodes) { | 2545 cvox.DomUtil.purgeNodes = function(nodes) { |
| 2546 return cvox.DomUtil.toArray(nodes). | 2546 return cvox.DomUtil.toArray(nodes). |
| 2547 filter(function(node) { | 2547 filter(function(node) { |
| 2548 return node.nodeType != Node.TEXT_NODE || | 2548 return node.nodeType != Node.TEXT_NODE || |
| 2549 !node.textContent.match(/^\s+$/);}); | 2549 !node.textContent.match(/^\s+$/);}); |
| 2550 }; | 2550 }; |
| 2551 | 2551 |
| 2552 | 2552 |
| 2553 /** | 2553 /** |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2597 var describedNode = document.getElementById(describedById); | 2597 var describedNode = document.getElementById(describedById); |
| 2598 if (describedNode) { | 2598 if (describedNode) { |
| 2599 desc += ' ' + cvox.DomUtil.getName( | 2599 desc += ' ' + cvox.DomUtil.getName( |
| 2600 describedNode, true, true, true); | 2600 describedNode, true, true, true); |
| 2601 } | 2601 } |
| 2602 } | 2602 } |
| 2603 } | 2603 } |
| 2604 } | 2604 } |
| 2605 return desc; | 2605 return desc; |
| 2606 }; | 2606 }; |
| OLD | NEW |