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.
6 * @fileoverview An abstract class for walking at the sub-element level.
7 * For example, walking at the sentence, word, or character level.
8 * This class is an adapter around TraverseContent which exposes the interface
9 * required by walkers. Subclasses must override the this.grain attribute
14 goog
.provide('cvox.AbstractSelectionWalker');
16 goog
.require('cvox.AbstractWalker');
17 goog
.require('cvox.BareObjectWalker');
18 goog
.require('cvox.DescriptionUtil');
19 goog
.require('cvox.DomUtil');
20 goog
.require('cvox.Spannable');
21 goog
.require('cvox.TraverseContent');
25 * @extends {cvox.AbstractWalker}
27 cvox
.AbstractSelectionWalker = function() {
28 cvox
.AbstractWalker
.call(this);
29 this.objWalker_
= new cvox
.BareObjectWalker();
30 this.tc_
= cvox
.TraverseContent
.getInstance();
31 this.grain
/** @protected */ = ''; // child must override
33 goog
.inherits(cvox
.AbstractSelectionWalker
, cvox
.AbstractWalker
);
38 cvox
.AbstractSelectionWalker
.prototype.next = function(sel
) {
39 var r
= sel
.isReversed();
40 this.tc_
.syncToCursorSelection(sel
.clone().setReversed(false));
41 var ret
= r
? this.tc_
.prevElement(this.grain
) :
42 this.tc_
.nextElement(this.grain
);
44 // Unfortunately, we can't trust TraverseContent; fall back to ObjectWalker.
45 return this.objWalker_
.next(sel
);
47 var retSel
= this.tc_
.getCurrentCursorSelection().setReversed(r
);
48 var objSel
= this.objWalker_
.next(sel
);
49 objSel
= objSel
? objSel
.setReversed(r
) : null;
51 // ObjectWalker wins when there's a discrepancy between it and
52 // TraverseContent. The only exception is with an end cursor on a text node.
53 // In all other cases, this makes sure we visit the same selections as
56 (retSel
.end
.node
.constructor.name
!= 'Text' ||
57 objSel
.end
.node
.constructor.name
!= 'Text') &&
58 !cvox
.DomUtil
.isDescendantOfNode(retSel
.end
.node
, sel
.end
.node
) &&
59 !cvox
.DomUtil
.isDescendantOfNode(retSel
.end
.node
, objSel
.end
.node
)) {
68 cvox
.AbstractSelectionWalker
.prototype.sync = function(sel
) {
69 var r
= sel
.isReversed();
71 if (sel
.start
.equals(sel
.end
) && sel
.start
.node
.constructor.name
!= 'Text') {
72 var node
= sel
.start
.node
;
74 // Find the deepest visible node; written specifically here because we want
75 // to move across siblings if necessary and take the deepest node which can
78 cvox
.DomUtil
.directedFirstChild(node
, r
) &&
79 !cvox
.TraverseUtil
.treatAsLeafNode(node
)) {
80 var child
= cvox
.DomUtil
.directedFirstChild(node
, r
);
82 // Find the first visible child.
84 if (cvox
.DomUtil
.isVisible(child
,
85 {checkAncestors
: false, checkDescendants
: false})) {
89 child
= cvox
.DomUtil
.directedNextSibling(child
, r
);
93 // node has no visible children; it's therefore the deepest visible node.
98 newSel
= cvox
.CursorSelection
.fromNode(node
);
100 newSel
= sel
.clone();
102 newSel
.start
= newSel
.end
;
104 newSel
.end
= newSel
.start
;
108 // This.next places us at the correct initial position (except below).
109 newSel
= this.next(newSel
.setReversed(false));
111 // ObjectWalker wins when there's a discrepancy between it and
112 // TraverseContent. The only exception is with an end cursor on a text node.
113 // In all other cases, this makes sure we visit the same selections as
115 var objSel
= this.objWalker_
.sync(sel
);
116 objSel
= objSel
? objSel
.setReversed(r
) : null;
122 newSel
.setReversed(r
);
125 (newSel
.end
.node
.constructor.name
!= 'Text' ||
126 objSel
.end
.node
.constructor.name
!= 'Text') &&
127 !cvox
.DomUtil
.isDescendantOfNode(newSel
.end
.node
, sel
.end
.node
) &&
128 !cvox
.DomUtil
.isDescendantOfNode(newSel
.end
.node
, objSel
.end
.node
)) {
137 cvox
.AbstractSelectionWalker
.prototype.getDescription = function(prevSel
, sel
) {
138 var description
= cvox
.DescriptionUtil
.getDescriptionFromAncestors(
139 cvox
.DomUtil
.getUniqueAncestors(prevSel
.end
.node
, sel
.start
.node
),
141 cvox
.ChromeVox
.verbosity
);
142 description
.text
= sel
.getText() || description
.text
;
143 return [description
];
149 cvox
.AbstractSelectionWalker
.prototype.getBraille = function(prevSel
, sel
) {
150 var node
= sel
.absStart().node
;
151 var text
= cvox
.TraverseUtil
.getNodeText(node
);
152 var spannable
= new cvox
.Spannable(text
);
153 spannable
.setSpan(node
, 0, text
.length
);
154 return new cvox
.NavBraille({
156 startIndex
: sel
.absStart().index
,
157 endIndex
: sel
.absEnd().index