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 An abstract class for walking at the sub-element level. | 6 * @fileoverview An abstract class for walking at the sub-element level. |
7 * For example, walking at the sentence, word, or character level. | 7 * For example, walking at the sentence, word, or character level. |
8 * This class is an adapter around TraverseContent which exposes the interface | 8 * This class is an adapter around TraverseContent which exposes the interface |
9 * required by walkers. Subclasses must override the this.grain attribute | 9 * required by walkers. Subclasses must override the this.grain attribute |
10 * on initialization. | 10 * on initialization. |
(...skipping 10 matching lines...) Expand all Loading... |
21 goog.require('cvox.TraverseContent'); | 21 goog.require('cvox.TraverseContent'); |
22 | 22 |
23 /** | 23 /** |
24 * @constructor | 24 * @constructor |
25 * @extends {cvox.AbstractWalker} | 25 * @extends {cvox.AbstractWalker} |
26 */ | 26 */ |
27 cvox.AbstractSelectionWalker = function() { | 27 cvox.AbstractSelectionWalker = function() { |
28 cvox.AbstractWalker.call(this); | 28 cvox.AbstractWalker.call(this); |
29 this.objWalker_ = new cvox.BareObjectWalker(); | 29 this.objWalker_ = new cvox.BareObjectWalker(); |
30 this.tc_ = cvox.TraverseContent.getInstance(); | 30 this.tc_ = cvox.TraverseContent.getInstance(); |
31 this.grain /** @protected */ = ''; // child must override | 31 this.grain /** @protected */ = ''; // child must override |
32 }; | 32 }; |
33 goog.inherits(cvox.AbstractSelectionWalker, cvox.AbstractWalker); | 33 goog.inherits(cvox.AbstractSelectionWalker, cvox.AbstractWalker); |
34 | 34 |
35 /** | 35 /** |
36 * @override | 36 * @override |
37 */ | 37 */ |
38 cvox.AbstractSelectionWalker.prototype.next = function(sel) { | 38 cvox.AbstractSelectionWalker.prototype.next = function(sel) { |
39 var r = sel.isReversed(); | 39 var r = sel.isReversed(); |
40 this.tc_.syncToCursorSelection(sel.clone().setReversed(false)); | 40 this.tc_.syncToCursorSelection(sel.clone().setReversed(false)); |
41 var ret = r ? this.tc_.prevElement(this.grain) : | 41 var ret = |
42 this.tc_.nextElement(this.grain); | 42 r ? this.tc_.prevElement(this.grain) : this.tc_.nextElement(this.grain); |
43 if (ret == null) { | 43 if (ret == null) { |
44 // Unfortunately, we can't trust TraverseContent; fall back to ObjectWalker. | 44 // Unfortunately, we can't trust TraverseContent; fall back to ObjectWalker. |
45 return this.objWalker_.next(sel); | 45 return this.objWalker_.next(sel); |
46 } | 46 } |
47 var retSel = this.tc_.getCurrentCursorSelection().setReversed(r); | 47 var retSel = this.tc_.getCurrentCursorSelection().setReversed(r); |
48 var objSel = this.objWalker_.next(sel); | 48 var objSel = this.objWalker_.next(sel); |
49 objSel = objSel ? objSel.setReversed(r) : null; | 49 objSel = objSel ? objSel.setReversed(r) : null; |
50 | 50 |
51 // ObjectWalker wins when there's a discrepancy between it and | 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. | 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 | 53 // In all other cases, this makes sure we visit the same selections as |
54 // object walker. | 54 // object walker. |
55 if (objSel && | 55 if (objSel && |
56 (retSel.end.node.constructor.name != 'Text' || | 56 (retSel.end.node.constructor.name != 'Text' || |
57 objSel.end.node.constructor.name != 'Text') && | 57 objSel.end.node.constructor.name != 'Text') && |
58 !cvox.DomUtil.isDescendantOfNode(retSel.end.node, sel.end.node) && | 58 !cvox.DomUtil.isDescendantOfNode(retSel.end.node, sel.end.node) && |
59 !cvox.DomUtil.isDescendantOfNode(retSel.end.node, objSel.end.node)) { | 59 !cvox.DomUtil.isDescendantOfNode(retSel.end.node, objSel.end.node)) { |
60 return objSel; | 60 return objSel; |
61 } | 61 } |
62 return retSel; | 62 return retSel; |
63 }; | 63 }; |
64 | 64 |
65 /** | 65 /** |
66 * @override | 66 * @override |
67 */ | 67 */ |
68 cvox.AbstractSelectionWalker.prototype.sync = function(sel) { | 68 cvox.AbstractSelectionWalker.prototype.sync = function(sel) { |
69 var r = sel.isReversed(); | 69 var r = sel.isReversed(); |
70 var newSel = null; | 70 var newSel = null; |
71 if (sel.start.equals(sel.end) && sel.start.node.constructor.name != 'Text') { | 71 if (sel.start.equals(sel.end) && sel.start.node.constructor.name != 'Text') { |
72 var node = sel.start.node; | 72 var node = sel.start.node; |
73 | 73 |
74 // Find the deepest visible node; written specifically here because we want | 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 | 75 // to move across siblings if necessary and take the deepest node which can |
76 // be BODY. | 76 // be BODY. |
77 while (node && | 77 while (node && cvox.DomUtil.directedFirstChild(node, r) && |
78 cvox.DomUtil.directedFirstChild(node, r) && | 78 !cvox.TraverseUtil.treatAsLeafNode(node)) { |
79 !cvox.TraverseUtil.treatAsLeafNode(node)) { | |
80 var child = cvox.DomUtil.directedFirstChild(node, r); | 79 var child = cvox.DomUtil.directedFirstChild(node, r); |
81 | 80 |
82 // Find the first visible child. | 81 // Find the first visible child. |
83 while (child) { | 82 while (child) { |
84 if (cvox.DomUtil.isVisible(child, | 83 if (cvox.DomUtil.isVisible( |
85 {checkAncestors: false, checkDescendants: false})) { | 84 child, {checkAncestors: false, checkDescendants: false})) { |
86 node = child; | 85 node = child; |
87 break; | 86 break; |
88 } else { | 87 } else { |
89 child = cvox.DomUtil.directedNextSibling(child, r); | 88 child = cvox.DomUtil.directedNextSibling(child, r); |
90 } | 89 } |
91 } | 90 } |
92 | 91 |
93 // node has no visible children; it's therefore the deepest visible node. | 92 // node has no visible children; it's therefore the deepest visible node. |
94 if (!child) { | 93 if (!child) { |
95 break; | 94 break; |
(...skipping 20 matching lines...) Expand all Loading... |
116 objSel = objSel ? objSel.setReversed(r) : null; | 115 objSel = objSel ? objSel.setReversed(r) : null; |
117 | 116 |
118 if (!newSel) { | 117 if (!newSel) { |
119 return objSel; | 118 return objSel; |
120 } | 119 } |
121 | 120 |
122 newSel.setReversed(r); | 121 newSel.setReversed(r); |
123 | 122 |
124 if (objSel && | 123 if (objSel && |
125 (newSel.end.node.constructor.name != 'Text' || | 124 (newSel.end.node.constructor.name != 'Text' || |
126 objSel.end.node.constructor.name != 'Text') && | 125 objSel.end.node.constructor.name != 'Text') && |
127 !cvox.DomUtil.isDescendantOfNode(newSel.end.node, sel.end.node) && | 126 !cvox.DomUtil.isDescendantOfNode(newSel.end.node, sel.end.node) && |
128 !cvox.DomUtil.isDescendantOfNode(newSel.end.node, objSel.end.node)) { | 127 !cvox.DomUtil.isDescendantOfNode(newSel.end.node, objSel.end.node)) { |
129 return objSel; | 128 return objSel; |
130 } | 129 } |
131 return newSel; | 130 return newSel; |
132 }; | 131 }; |
133 | 132 |
134 /** | 133 /** |
135 * @override | 134 * @override |
136 */ | 135 */ |
137 cvox.AbstractSelectionWalker.prototype.getDescription = function(prevSel, sel) { | 136 cvox.AbstractSelectionWalker.prototype.getDescription = function(prevSel, sel) { |
138 var description = cvox.DescriptionUtil.getDescriptionFromAncestors( | 137 var description = cvox.DescriptionUtil.getDescriptionFromAncestors( |
139 cvox.DomUtil.getUniqueAncestors(prevSel.end.node, sel.start.node), | 138 cvox.DomUtil.getUniqueAncestors(prevSel.end.node, sel.start.node), true, |
140 true, | |
141 cvox.ChromeVox.verbosity); | 139 cvox.ChromeVox.verbosity); |
142 description.text = sel.getText() || description.text; | 140 description.text = sel.getText() || description.text; |
143 return [description]; | 141 return [description]; |
144 }; | 142 }; |
145 | 143 |
146 /** | 144 /** |
147 * @override | 145 * @override |
148 */ | 146 */ |
149 cvox.AbstractSelectionWalker.prototype.getBraille = function(prevSel, sel) { | 147 cvox.AbstractSelectionWalker.prototype.getBraille = function(prevSel, sel) { |
150 var node = sel.absStart().node; | 148 var node = sel.absStart().node; |
151 var text = cvox.TraverseUtil.getNodeText(node); | 149 var text = cvox.TraverseUtil.getNodeText(node); |
152 var spannable = new Spannable(text); | 150 var spannable = new Spannable(text); |
153 spannable.setSpan(node, 0, text.length); | 151 spannable.setSpan(node, 0, text.length); |
154 return new cvox.NavBraille({ | 152 return new cvox.NavBraille({ |
155 text: spannable, | 153 text: spannable, |
156 startIndex: sel.absStart().index, | 154 startIndex: sel.absStart().index, |
157 endIndex: sel.absEnd().index | 155 endIndex: sel.absEnd().index |
158 }); | 156 }); |
159 }; | 157 }; |
OLD | NEW |