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 goog.provide('cvox.TraverseMath'); | 5 goog.provide('cvox.TraverseMath'); |
6 | 6 |
7 goog.require('cvox.ChromeVox'); | 7 goog.require('cvox.ChromeVox'); |
8 goog.require('cvox.DomUtil'); | 8 goog.require('cvox.DomUtil'); |
9 goog.require('cvox.SemanticTree'); | 9 goog.require('cvox.SemanticTree'); |
10 | 10 |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
124 // If a node has a cvoxid attribute we know that it contains a LaTeX | 124 // If a node has a cvoxid attribute we know that it contains a LaTeX |
125 // expression that we have rewritten into its corresponding MathML | 125 // expression that we have rewritten into its corresponding MathML |
126 // representation, which we can speak and walk. | 126 // representation, which we can speak and walk. |
127 if (!node.hasAttribute('cvoxid')) { | 127 if (!node.hasAttribute('cvoxid')) { |
128 return; | 128 return; |
129 } | 129 } |
130 var cvoxid = node.getAttribute('cvoxid'); | 130 var cvoxid = node.getAttribute('cvoxid'); |
131 node = this.allTexs_[cvoxid]; | 131 node = this.allTexs_[cvoxid]; |
132 } | 132 } |
133 if (cvox.DomUtil.isMathJax(node)) { | 133 if (cvox.DomUtil.isMathJax(node)) { |
134 this.activeMathmlHost = this.allMathjaxs_[node.getAttribute('id')]; | 134 this.activeMathmlHost = this.allMathjaxs_[node.getAttribute('id')]; |
135 } | 135 } |
136 this.activeMath = this.activeMathmlHost || node; | 136 this.activeMath = this.activeMathmlHost || node; |
137 this.activeNode = this.activeMathmlHost || node; | 137 this.activeNode = this.activeMathmlHost || node; |
138 if (this.activeNode && cvox.TraverseMath.setSemantic_ && | 138 if (this.activeNode && cvox.TraverseMath.setSemantic_ && |
139 this.activeNode.nodeType == Node.ELEMENT_NODE) { | 139 this.activeNode.nodeType == Node.ELEMENT_NODE) { |
140 this.activeNode = | 140 this.activeNode = |
141 (new cvox.SemanticTree(/** @type {!Element} */ (this.activeNode))).xml()
; | 141 (new cvox.SemanticTree(/** @type {!Element} */ (this.activeNode))) |
| 142 .xml(); |
142 } | 143 } |
143 }; | 144 }; |
144 | 145 |
145 | 146 |
146 /** | 147 /** |
147 * Adds a mapping of a MathJax node to its MathML representation to the | 148 * Adds a mapping of a MathJax node to its MathML representation to the |
148 * dictionary of MathJax elements. | 149 * dictionary of MathJax elements. |
149 * @param {!Node} mml The MathML node. | 150 * @param {!Node} mml The MathML node. |
150 * @param {string} id The MathJax node id. | 151 * @param {string} id The MathJax node id. |
151 */ | 152 */ |
152 cvox.TraverseMath.prototype.addMathjax = function(mml, id) { | 153 cvox.TraverseMath.prototype.addMathjax = function(mml, id) { |
153 var spanId = cvox.DomUtil.getMathSpanId(id); | 154 var spanId = cvox.DomUtil.getMathSpanId(id); |
154 if (spanId) { | 155 if (spanId) { |
155 this.allMathjaxs_[spanId] = mml; | 156 this.allMathjaxs_[spanId] = mml; |
156 } else { | 157 } else { |
157 this.redoMathjaxs(mml, id); | 158 this.redoMathjaxs(mml, id); |
158 } | 159 } |
159 }; | 160 }; |
160 | 161 |
161 | 162 |
162 /** | 163 /** |
163 * Retries to compute MathML representations of MathJax elements, if | 164 * Retries to compute MathML representations of MathJax elements, if |
164 * they have not been filled in during rendering. | 165 * they have not been filled in during rendering. |
165 * @param {!Node} mml The MathML node. | 166 * @param {!Node} mml The MathML node. |
166 * @param {string} id The MathJax node id. | 167 * @param {string} id The MathJax node id. |
167 */ | 168 */ |
168 cvox.TraverseMath.prototype.redoMathjaxs = function(mml, id) { | 169 cvox.TraverseMath.prototype.redoMathjaxs = function(mml, id) { |
169 var fetch = goog.bind(function() {this.addMathjax(mml, id);}, this); | 170 var fetch = goog.bind(function() { |
| 171 this.addMathjax(mml, id); |
| 172 }, this); |
170 setTimeout(fetch, 500); | 173 setTimeout(fetch, 500); |
171 }; | 174 }; |
172 | 175 |
173 | 176 |
174 /** | 177 /** |
175 * Initializes the MathJax to MathML mapping. | 178 * Initializes the MathJax to MathML mapping. |
176 * We first try to get all MathJax elements that are already being rendered. | 179 * We first try to get all MathJax elements that are already being rendered. |
177 * Secondly, we register a signal to get updated on all elements that are | 180 * Secondly, we register a signal to get updated on all elements that are |
178 * rendered or re-rendered later. | 181 * rendered or re-rendered later. |
179 */ | 182 */ |
180 cvox.TraverseMath.prototype.initializeMathjaxs = function() { | 183 cvox.TraverseMath.prototype.initializeMathjaxs = function() { |
181 var callback = | 184 var callback = goog.bind(function(mml, id) { |
182 goog.bind(function(mml, id) { | 185 this.addMathjax(mml, id); |
183 this.addMathjax(mml, id); | 186 }, this); |
184 }, this); | 187 cvox.ChromeVox.mathJax.isMathjaxActive(function(bool) { |
185 cvox.ChromeVox.mathJax.isMathjaxActive( | 188 if (bool) { |
186 function(bool) { | 189 cvox.ChromeVox.mathJax.getAllJax(callback); |
187 if (bool) { | 190 cvox.ChromeVox.mathJax.registerSignal(callback, 'New Math'); |
188 cvox.ChromeVox.mathJax.getAllJax(callback); | 191 } |
189 cvox.ChromeVox.mathJax.registerSignal(callback, 'New Math'); | 192 }); |
190 } | |
191 }); | |
192 }; | 193 }; |
193 | 194 |
194 | 195 |
195 /** | 196 /** |
196 * Initializes the elements in the page that we identify as potentially | 197 * Initializes the elements in the page that we identify as potentially |
197 * containing tex or asciimath alt text. | 198 * containing tex or asciimath alt text. |
198 */ | 199 */ |
199 cvox.TraverseMath.prototype.initializeAltMaths = function() { | 200 cvox.TraverseMath.prototype.initializeAltMaths = function() { |
200 if (!document.querySelector( | 201 if (!document.querySelector( |
201 cvox.DomUtil.altMathQuerySelector('tex') + ', ' + | 202 cvox.DomUtil.altMathQuerySelector('tex') + ', ' + |
202 cvox.DomUtil.altMathQuerySelector('asciimath'))) { | 203 cvox.DomUtil.altMathQuerySelector('asciimath'))) { |
203 return; | 204 return; |
204 } | 205 } |
205 var callback = goog.bind( | 206 var callback = goog.bind(function(mml, id) { |
206 function(mml, id) { | 207 this.allTexs_[id] = mml; |
207 this.allTexs_[id] = mml; | 208 }, this); |
208 }, this); | |
209 // Inject a minimalistic version of MathJax into the page. | 209 // Inject a minimalistic version of MathJax into the page. |
210 cvox.ChromeVox.mathJax.injectScripts(); | 210 cvox.ChromeVox.mathJax.injectScripts(); |
211 // Once MathJax is injected we harvest all Latex and AsciiMath in alt | 211 // Once MathJax is injected we harvest all Latex and AsciiMath in alt |
212 // attributes and translate them to MathML expression. | 212 // attributes and translate them to MathML expression. |
213 cvox.ChromeVox.mathJax.isMathjaxActive( | 213 cvox.ChromeVox.mathJax.isMathjaxActive(function(active) { |
214 function(active) { | 214 if (active) { |
215 if (active) { | 215 cvox.ChromeVox.mathJax.configMediaWiki(); |
216 cvox.ChromeVox.mathJax.configMediaWiki(); | 216 cvox.ChromeVox.mathJax.getAllTexs(callback); |
217 cvox.ChromeVox.mathJax.getAllTexs(callback); | 217 cvox.ChromeVox.mathJax.getAllAsciiMaths(callback); |
218 cvox.ChromeVox.mathJax.getAllAsciiMaths(callback); | 218 } |
219 } | 219 }); |
220 }); | |
221 }; | 220 }; |
222 | 221 |
223 | 222 |
224 /** | 223 /** |
225 * Moves to the next leaf node in the current Math expression if it exists. | 224 * Moves to the next leaf node in the current Math expression if it exists. |
226 * @param {boolean} reverse True if reversed. False by default. | 225 * @param {boolean} reverse True if reversed. False by default. |
227 * @param {function(!Node):boolean} pred Predicate deciding what a leaf is. | 226 * @param {function(!Node):boolean} pred Predicate deciding what a leaf is. |
228 * @return {Node} The next node. | 227 * @return {Node} The next node. |
229 */ | 228 */ |
230 cvox.TraverseMath.prototype.nextLeaf = function(reverse, pred) { | 229 cvox.TraverseMath.prototype.nextLeaf = function(reverse, pred) { |
231 if (this.activeNode && this.activeMath) { | 230 if (this.activeNode && this.activeMath) { |
232 var next = pred(this.activeNode) ? | 231 var next = pred(this.activeNode) ? |
233 cvox.DomUtil.directedFindNextNode( | 232 cvox.DomUtil.directedFindNextNode( |
234 this.activeNode, this.activeMath, reverse, pred) : | 233 this.activeNode, this.activeMath, reverse, pred) : |
235 cvox.DomUtil.directedFindFirstNode(this.activeNode, reverse, pred); | 234 cvox.DomUtil.directedFindFirstNode(this.activeNode, reverse, pred); |
236 if (next) { | 235 if (next) { |
237 this.activeNode = next; | 236 this.activeNode = next; |
238 } | 237 } |
239 } | 238 } |
240 return this.activeNode; | 239 return this.activeNode; |
241 }; | 240 }; |
242 | 241 |
243 | 242 |
244 // TODO (sorge) Refactor this logic into single walkers. | 243 // TODO (sorge) Refactor this logic into single walkers. |
245 /** | 244 /** |
246 * Returns a string with the content of the active node. | 245 * Returns a string with the content of the active node. |
247 * @return {string} The active content. | 246 * @return {string} The active content. |
248 */ | 247 */ |
249 cvox.TraverseMath.prototype.activeContent = function() { | 248 cvox.TraverseMath.prototype.activeContent = function() { |
250 return this.activeNode.textContent; | 249 return this.activeNode.textContent; |
251 }; | 250 }; |
252 | 251 |
253 | 252 |
254 /** | 253 /** |
255 * Moves to the next subtree from a given node in a depth first fashion. | 254 * Moves to the next subtree from a given node in a depth first fashion. |
256 * @param {boolean} reverse True if reversed. False by default. | 255 * @param {boolean} reverse True if reversed. False by default. |
257 * @param {function(!Node):boolean} pred Predicate deciding what a subtree is. | 256 * @param {function(!Node):boolean} pred Predicate deciding what a subtree is. |
258 * @return {Node} The next subtree. | 257 * @return {Node} The next subtree. |
259 */ | 258 */ |
260 cvox.TraverseMath.prototype.nextSubtree = function(reverse, pred) { | 259 cvox.TraverseMath.prototype.nextSubtree = function(reverse, pred) { |
261 if (!this.activeNode || !this.activeMath) { | 260 if (!this.activeNode || !this.activeMath) { |
262 return null; | 261 return null; |
263 } | 262 } |
264 if (!reverse) { | 263 if (!reverse) { |
265 var child = cvox.DomUtil.directedFindFirstNode( | 264 var child = |
266 this.activeNode, reverse, pred); | 265 cvox.DomUtil.directedFindFirstNode(this.activeNode, reverse, pred); |
267 if (child) { | 266 if (child) { |
268 this.activeNode = child; | 267 this.activeNode = child; |
269 } else { | 268 } else { |
270 var next = cvox.DomUtil.directedFindNextNode( | 269 var next = cvox.DomUtil.directedFindNextNode( |
271 this.activeNode, this.activeMath, reverse, pred); | 270 this.activeNode, this.activeMath, reverse, pred); |
272 if (next) { | 271 if (next) { |
273 this.activeNode = next; | 272 this.activeNode = next; |
274 } | 273 } |
275 } | 274 } |
276 } else { | 275 } else { |
277 if (this.activeNode == this.activeMath) { | 276 if (this.activeNode == this.activeMath) { |
278 var child = cvox.DomUtil.directedFindDeepestNode( | 277 var child = |
279 this.activeNode, reverse, pred); | 278 cvox.DomUtil.directedFindDeepestNode(this.activeNode, reverse, pred); |
280 if (child != this.activeNode) { | 279 if (child != this.activeNode) { |
281 this.activeNode = child; | 280 this.activeNode = child; |
282 return this.activeNode; | 281 return this.activeNode; |
283 } | 282 } |
284 } | 283 } |
285 var prev = cvox.DomUtil.directedFindNextNode( | 284 var prev = cvox.DomUtil.directedFindNextNode( |
286 this.activeNode, this.activeMath, reverse, pred, true, true); | 285 this.activeNode, this.activeMath, reverse, pred, true, true); |
287 if (prev) { | 286 if (prev) { |
288 this.activeNode = prev; | 287 this.activeNode = prev; |
289 } | 288 } |
290 } | 289 } |
291 return this.activeNode; | 290 return this.activeNode; |
292 }; | 291 }; |
293 | 292 |
294 | 293 |
295 /** | 294 /** |
296 * left or right in the math expression. | 295 * left or right in the math expression. |
297 * Navigation is bounded by the presence of a sibling. | 296 * Navigation is bounded by the presence of a sibling. |
298 * @param {boolean} r True to move left; false to move right. | 297 * @param {boolean} r True to move left; false to move right. |
299 * @return {Node} The result. | 298 * @return {Node} The result. |
300 */ | 299 */ |
301 cvox.TraverseMath.prototype.nextSibling = function(r) { | 300 cvox.TraverseMath.prototype.nextSibling = function(r) { |
302 if (!this.activeNode || !this.activeMath) { | 301 if (!this.activeNode || !this.activeMath) { |
303 return null; | 302 return null; |
304 } | 303 } |
305 var node = this.activeNode; | 304 var node = this.activeNode; |
306 node = r ? node.previousSibling : node.nextSibling; | 305 node = r ? node.previousSibling : node.nextSibling; |
307 if (!node) { | 306 if (!node) { |
308 return null; | 307 return null; |
309 } | 308 } |
310 this.activeNode = node; | 309 this.activeNode = node; |
311 return this.activeNode; | 310 return this.activeNode; |
312 }; | 311 }; |
313 | 312 |
314 | 313 |
315 /** | 314 /** |
316 * Moves up or down the math expression. | 315 * Moves up or down the math expression. |
(...skipping 18 matching lines...) Expand all Loading... |
335 }; | 334 }; |
336 | 335 |
337 | 336 |
338 /** | 337 /** |
339 * Adds a list of domains and styles to the existing one. | 338 * Adds a list of domains and styles to the existing one. |
340 * @param {Array<string>} domains List of domain names. | 339 * @param {Array<string>} domains List of domain names. |
341 * @param {Array<string>} styles List of style names. | 340 * @param {Array<string>} styles List of style names. |
342 */ | 341 */ |
343 cvox.TraverseMath.prototype.addDomainsAndStyles = function(domains, styles) { | 342 cvox.TraverseMath.prototype.addDomainsAndStyles = function(domains, styles) { |
344 this.allDomains.push.apply( | 343 this.allDomains.push.apply( |
345 this.allDomains, | 344 this.allDomains, domains.filter(goog.bind(function(x) { |
346 domains.filter( | 345 return this.allDomains.indexOf(x) < 0; |
347 goog.bind(function(x) {return this.allDomains.indexOf(x) < 0;}, | 346 }, this))); |
348 this))); | |
349 this.allStyles.push.apply( | 347 this.allStyles.push.apply( |
350 this.allStyles, | 348 this.allStyles, styles.filter(goog.bind(function(x) { |
351 styles.filter( | 349 return this.allStyles.indexOf(x) < 0; |
352 goog.bind(function(x) {return this.allStyles.indexOf(x) < 0;}, | 350 }, this))); |
353 this))); | |
354 }; | 351 }; |
355 | 352 |
356 | 353 |
357 /** | 354 /** |
358 * Gets a list of domains and styles from the symbol and function mappings. | 355 * Gets a list of domains and styles from the symbol and function mappings. |
359 * Depending on the platform they either live in the background page or | 356 * Depending on the platform they either live in the background page or |
360 * in the android math map. | 357 * in the android math map. |
361 */ | 358 */ |
362 cvox.TraverseMath.prototype.initDomainsAndStyles = function() { | 359 cvox.TraverseMath.prototype.initDomainsAndStyles = function() { |
363 if (cvox.ChromeVox.host['mathMap']) { | 360 if (cvox.ChromeVox.host['mathMap']) { |
364 this.addDomainsAndStyles( | 361 this.addDomainsAndStyles( |
365 cvox.ChromeVox.host['mathMap'].allDomains, | 362 cvox.ChromeVox.host['mathMap'].allDomains, |
366 cvox.ChromeVox.host['mathMap'].allStyles); | 363 cvox.ChromeVox.host['mathMap'].allStyles); |
367 } else { | 364 } else { |
368 cvox.ChromeVox.host.sendToBackgroundPage( | 365 cvox.ChromeVox.host.sendToBackgroundPage( |
369 {'target': 'Math', | 366 {'target': 'Math', 'action': 'getDomains'}); |
370 'action': 'getDomains'}); | 367 } |
371 } | |
372 }; | 368 }; |
373 | 369 |
374 | 370 |
375 /** | 371 /** |
376 * Sets the domain for the TraverseMath object to the next one in the list | 372 * Sets the domain for the TraverseMath object to the next one in the list |
377 * restarting from the first, if necessary. | 373 * restarting from the first, if necessary. |
378 * @return {string} The name of the newly set domain. | 374 * @return {string} The name of the newly set domain. |
379 */ | 375 */ |
380 cvox.TraverseMath.prototype.cycleDomain = function() { | 376 cvox.TraverseMath.prototype.cycleDomain = function() { |
381 this.initDomainsAndStyles(); | 377 this.initDomainsAndStyles(); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
437 * @return {Node} The active node, if it exists. | 433 * @return {Node} The active node, if it exists. |
438 */ | 434 */ |
439 cvox.TraverseMath.prototype.getAttachedActiveNode = function() { | 435 cvox.TraverseMath.prototype.getAttachedActiveNode = function() { |
440 var node = this.activeNode; | 436 var node = this.activeNode; |
441 if (!node || node.nodeType != Node.ELEMENT_NODE) { | 437 if (!node || node.nodeType != Node.ELEMENT_NODE) { |
442 return null; | 438 return null; |
443 } | 439 } |
444 var id = node.getAttribute('spanID'); | 440 var id = node.getAttribute('spanID'); |
445 return document.getElementById(id); | 441 return document.getElementById(id); |
446 }; | 442 }; |
OLD | NEW |