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 Classes related to cursors that point to and select parts of | 6 * @fileoverview Classes related to cursors that point to and select parts of |
7 * the automation tree. | 7 * the automation tree. |
8 */ | 8 */ |
9 | 9 |
10 goog.provide('cursors.Cursor'); | 10 goog.provide('cursors.Cursor'); |
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
248 } | 248 } |
249 break; | 249 break; |
250 case Unit.NODE: | 250 case Unit.NODE: |
251 case Unit.DOM_NODE: | 251 case Unit.DOM_NODE: |
252 switch (movement) { | 252 switch (movement) { |
253 case Movement.BOUND: | 253 case Movement.BOUND: |
254 newIndex = dir == Dir.FORWARD ? this.getText().length - 1 : 0; | 254 newIndex = dir == Dir.FORWARD ? this.getText().length - 1 : 0; |
255 break; | 255 break; |
256 case Movement.DIRECTIONAL: | 256 case Movement.DIRECTIONAL: |
257 var pred = unit == Unit.NODE ? | 257 var pred = unit == Unit.NODE ? |
258 AutomationPredicate.leaf : AutomationPredicate.element; | 258 AutomationPredicate.leaf : AutomationPredicate.object; |
259 newNode = AutomationUtil.findNextNode( | 259 newNode = AutomationUtil.findNextNode( |
260 newNode, dir, pred) || this.node_; | 260 newNode, dir, pred) || this.node_; |
261 newIndex = cursors.NODE_INDEX; | 261 newIndex = cursors.NODE_INDEX; |
262 break; | 262 break; |
263 } | 263 } |
264 break; | 264 break; |
265 case Unit.LINE: | 265 case Unit.LINE: |
266 newIndex = 0; | 266 newIndex = 0; |
267 switch (movement) { | 267 switch (movement) { |
268 case Movement.BOUND: | 268 case Movement.BOUND: |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
319 }; | 319 }; |
320 | 320 |
321 cursors.WrappingCursor.prototype = { | 321 cursors.WrappingCursor.prototype = { |
322 __proto__: cursors.Cursor.prototype, | 322 __proto__: cursors.Cursor.prototype, |
323 | 323 |
324 /** @override */ | 324 /** @override */ |
325 move: function(unit, movement, dir) { | 325 move: function(unit, movement, dir) { |
326 var result = this; | 326 var result = this; |
327 | 327 |
328 // Regular movement. | 328 // Regular movement. |
329 if (!AutomationUtil.isTraversalRoot(this.node) || dir == Dir.FORWARD) | 329 if (!AutomationPredicate.root(this.node) || dir == Dir.FORWARD) |
330 result = cursors.Cursor.prototype.move.call(this, unit, movement, dir); | 330 result = cursors.Cursor.prototype.move.call(this, unit, movement, dir); |
331 | 331 |
332 // There are two cases for wrapping: | 332 // There are two cases for wrapping: |
333 // 1. moving forwards from the last element. | 333 // 1. moving forwards from the last element. |
334 // 2. moving backwards from the document root. | 334 // 2. moving backwards from the first element. |
335 // Both result in |move| returning the same cursor. | 335 // Both result in |move| returning the same cursor. |
336 // For 1, simply place the new cursor on the document node. | 336 // For 1, simply place the new cursor on the document node. |
337 // For 2, try to descend to the first leaf-like object. | 337 // For 2, place range on the root (if not already there). If at root, |
| 338 // try to descend to the first leaf-like object. |
338 if (movement == Movement.DIRECTIONAL && result.equals(this)) { | 339 if (movement == Movement.DIRECTIONAL && result.equals(this)) { |
339 var pred = unit == Unit.DOM_NODE ? | 340 var pred = unit == Unit.DOM_NODE ? |
340 AutomationPredicate.element : AutomationPredicate.leaf; | 341 AutomationPredicate.object : AutomationPredicate.leaf; |
341 var endpoint = this.node; | 342 var endpoint = this.node; |
342 | 343 |
343 // Case 1: forwards (find the root-like node). | 344 // Case 1: forwards (find the root-like node). |
344 while (!AutomationUtil.isTraversalRoot(endpoint) && endpoint.parent) | 345 while (!AutomationPredicate.root(endpoint) && endpoint.parent) |
345 endpoint = endpoint.parent; | 346 endpoint = endpoint.parent; |
346 | 347 |
347 // Case 2: backward (sync downwards to a leaf). | 348 // Always play a wrap earcon when moving forward. |
348 if (dir == Dir.BACKWARD) | 349 var playEarcon = dir == Dir.FORWARD; |
349 endpoint = AutomationUtil.findNodePre(endpoint, dir, pred) || endpoint; | |
350 | 350 |
351 cvox.ChromeVox.earcons.playEarcon(cvox.Earcon.WRAP); | 351 // Case 2: backward (sync downwards to a leaf), if already on the root. |
352 return new cursors.WrappingCursor(endpoint, cursors.NODE_INDEX); | 352 if (dir == Dir.BACKWARD && endpoint == this.node_) { |
| 353 playEarcon = true; |
| 354 endpoint = AutomationUtil.findNodePre(endpoint, |
| 355 dir, |
| 356 function(n) { |
| 357 return pred(n) && !AutomationPredicate.shouldIgnoreNode(n); |
| 358 }) || endpoint; |
| 359 } |
353 | 360 |
| 361 if (playEarcon) |
| 362 cvox.ChromeVox.earcons.playEarcon(cvox.Earcon.WRAP); |
| 363 |
| 364 return new cursors.WrappingCursor(endpoint, cursors.NODE_INDEX); |
354 } | 365 } |
355 return new cursors.WrappingCursor(result.node, result.index); | 366 return new cursors.WrappingCursor(result.node, result.index); |
356 } | 367 } |
357 }; | 368 }; |
358 | 369 |
359 /** | 370 /** |
360 * Represents a range in the automation tree. There is no visible selection on | 371 * Represents a range in the automation tree. There is no visible selection on |
361 * the page caused by usage of this object. | 372 * the page caused by usage of this object. |
362 * It is assumed that the caller provides |start| and |end| in document order. | 373 * It is assumed that the caller provides |start| and |end| in document order. |
363 * @param {!cursors.Cursor} start | 374 * @param {!cursors.Cursor} start |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
467 * direction. | 478 * direction. |
468 * @param {Unit} unit | 479 * @param {Unit} unit |
469 * @param {Dir} dir | 480 * @param {Dir} dir |
470 * @return {cursors.Range} | 481 * @return {cursors.Range} |
471 */ | 482 */ |
472 move: function(unit, dir) { | 483 move: function(unit, dir) { |
473 var newStart = this.start_; | 484 var newStart = this.start_; |
474 var newEnd; | 485 var newEnd; |
475 switch (unit) { | 486 switch (unit) { |
476 case Unit.CHARACTER: | 487 case Unit.CHARACTER: |
477 newStart = newStart.move(unit, Movement.BOUND, dir); | 488 newStart = newStart.move(unit, Movement.DIRECTIONAL, dir); |
478 newEnd = newStart.move(unit, Movement.BOUND, Dir.FORWARD); | 489 newEnd = newStart.move(unit, Movement.DIRECTIONAL, Dir.FORWARD); |
479 // Character crossed a node; collapses to the end of the node. | 490 // Character crossed a node; collapses to the end of the node. |
480 if (newStart.node !== newEnd.node) | 491 if (newStart.node !== newEnd.node) |
481 newEnd = new cursors.Cursor(newStart.node, newStart.index + 1); | 492 newEnd = new cursors.Cursor(newStart.node, newStart.index + 1); |
482 break; | 493 break; |
483 case Unit.WORD: | 494 case Unit.WORD: |
484 case Unit.LINE: | 495 case Unit.LINE: |
485 newStart = newStart.move(unit, Movement.DIRECTIONAL, dir); | 496 newStart = newStart.move(unit, Movement.DIRECTIONAL, dir); |
486 newStart = newStart.move(unit, Movement.BOUND, Dir.BACKWARD); | 497 newStart = newStart.move(unit, Movement.BOUND, Dir.BACKWARD); |
487 newEnd = newStart.move(unit, Movement.BOUND, Dir.FORWARD); | 498 newEnd = newStart.move(unit, Movement.BOUND, Dir.FORWARD); |
488 break; | 499 break; |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
542 /** | 553 /** |
543 * Returns whether this range has valid start and end cursors. | 554 * Returns whether this range has valid start and end cursors. |
544 * @return {boolean} | 555 * @return {boolean} |
545 */ | 556 */ |
546 isValid: function() { | 557 isValid: function() { |
547 return this.start.isValid() && this.end.isValid(); | 558 return this.start.isValid() && this.end.isValid(); |
548 } | 559 } |
549 }; | 560 }; |
550 | 561 |
551 }); // goog.scope | 562 }); // goog.scope |
OLD | NEW |