Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(136)

Side by Side Diff: chrome/browser/resources/chromeos/chromevox/cvox2/background/cursors.js

Issue 674263003: Add remaining text/caret navigation commands to ChromeVox Next. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@integrate_cursor
Patch Set: Add comments. Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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');
11 goog.provide('cursors.Movement'); 11 goog.provide('cursors.Movement');
12 goog.provide('cursors.Range');
12 goog.provide('cursors.Unit'); 13 goog.provide('cursors.Unit');
13 14
14 goog.require('AutomationUtil'); 15 goog.require('AutomationUtil');
15 16
16 /** 17 /**
17 * The special index that represents a cursor pointing to a node without 18 * The special index that represents a cursor pointing to a node without
18 * pointing to any part of its accessible text. 19 * pointing to any part of its accessible text.
19 */ 20 */
20 cursors.NODE_INDEX = -1; 21 cursors.NODE_INDEX = -1;
21 22
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
123 124
124 /** 125 /**
125 * Makes a Cursor which has been moved from this cursor by the unit in the 126 * Makes a Cursor which has been moved from this cursor by the unit in the
126 * given direction using the given movement type. 127 * given direction using the given movement type.
127 * @param {Unit} unit 128 * @param {Unit} unit
128 * @param {Movement} movement 129 * @param {Movement} movement
129 * @param {Dir} dir 130 * @param {Dir} dir
130 * @return {!cursors.Cursor} The moved cursor. 131 * @return {!cursors.Cursor} The moved cursor.
131 */ 132 */
132 move: function(unit, movement, dir) { 133 move: function(unit, movement, dir) {
133 var newNode, newIndex; 134 var newNode = this.node_;
135 var newIndex = this.index_;
136
137 if (unit != Unit.NODE && newIndex === cursors.NODE_INDEX)
138 newIndex = 0;
139
134 switch (unit) { 140 switch (unit) {
135 case Unit.CHARACTER: 141 case Unit.CHARACTER:
136 // BOUND and DIRECTIONAL are the same for characters. 142 // BOUND and DIRECTIONAL are the same for characters.
137 var node = this.node_; 143 newIndex = dir == Dir.FORWARD ? newIndex + 1 : newIndex - 1;
138 var nextIndex = dir == Dir.FORWARD ? this.index_ + 1 : this.index_ - 1; 144 if (newIndex < 0 || newIndex >= this.getText().length) {
139 if (nextIndex < 0 || nextIndex >= this.getText().length) { 145 newNode = AutomationUtil.findNextNode(
140 node = AutomationUtil.findNextNode( 146 newNode, dir, AutomationPredicate.leafWithText);
141 node, dir, AutomationPredicate.leaf); 147 if (newNode) {
142 if (node) { 148 newIndex =
143 nextIndex = 149 dir == Dir.FORWARD ? 0 : this.getText(newNode).length - 1;
144 dir == Dir.FORWARD ? 0 : this.getText(node).length - 1; 150 newIndex = newIndex == -1 ? 0 : newIndex;
145 } else { 151 } else {
146 node = this.node_; 152 newIndex = this.index_;
147 nextIndex = this.index_;
148 } 153 }
149 } 154 }
150 newNode = node;
151 newIndex = nextIndex;
152 break; 155 break;
153 case Unit.WORD: 156 case Unit.WORD:
154 switch (movement) { 157 switch (movement) {
155 case Movement.BOUND: 158 case Movement.BOUND:
156 if (this.node_.role == Role.inlineTextBox) { 159 if (newNode.role == Role.inlineTextBox) {
157 var start, end; 160 var start, end;
158 for (var i = 0; 161 for (var i = 0; i < newNode.attributes.wordStarts.length; i++) {
159 i < this.node_.attributes.wordStarts.length; 162 if (newIndex >= newNode.attributes.wordStarts[i] &&
160 i++) { 163 newIndex <= newNode.attributes.wordEnds[i]) {
161 if (this.index_ >= this.node_.attributes.wordStarts[i] && 164 start = newNode.attributes.wordStarts[i];
162 this.index_ <= this.node_.attributes.wordEnds[i]) { 165 end = newNode.attributes.wordEnds[i];
163 start = this.node_.attributes.wordStarts[i];
164 end = this.node_.attributes.wordEnds[i];
165 break; 166 break;
166 } 167 }
167 } 168 }
168 if (goog.isDef(start) && goog.isDef(end)) 169 if (goog.isDef(start) && goog.isDef(end))
169 newIndex = dir == Dir.FORWARD ? end : start; 170 newIndex = dir == Dir.FORWARD ? end : start;
170 } else { 171 } else {
171 // TODO(dtseng): Figure out what to do in this case. 172 // TODO(dtseng): Figure out what to do in this case.
172 } 173 }
173 break; 174 break;
174 case Movement.DIRECTIONAL: 175 case Movement.DIRECTIONAL:
175 if (this.node_.role == Role.inlineTextBox) { 176 if (newNode.role == Role.inlineTextBox) {
176 var start, end; 177 var start, end;
177 for (var i = 0; 178 for (var i = 0; i < newNode.attributes.wordStarts.length; i++) {
178 i < this.node_.attributes.wordStarts.length; 179 if (newIndex >= newNode.attributes.wordStarts[i] &&
179 i++) { 180 newIndex <= newNode.attributes.wordEnds[i]) {
180 if (this.index_ >= this.node_.attributes.wordStarts[i] &&
181 this.index_ <= this.node_.attributes.wordEnds[i]) {
182 var nextIndex = dir == Dir.FORWARD ? i + 1 : i - 1; 181 var nextIndex = dir == Dir.FORWARD ? i + 1 : i - 1;
183 start = this.node_.attributes.wordStarts[nextIndex]; 182 start = newNode.attributes.wordStarts[nextIndex];
184 end = this.node_.attributes.wordEnds[nextIndex]; 183 end = newNode.attributes.wordEnds[nextIndex];
185 break; 184 break;
186 } 185 }
187 } 186 }
188 if (goog.isDef(start)) { 187 if (goog.isDef(start)) {
189 newIndex = start; 188 newIndex = start;
190 } else { 189 } else {
191 // The backward case is special at the beginning of nodes. 190 // The backward case is special at the beginning of nodes.
192 if (dir == Dir.BACKWARD && this.index_ != 0) { 191 if (dir == Dir.BACKWARD && newIndex != 0) {
193 this.index_ = 0; 192 newIndex = 0;
194 } else { 193 } else {
195 var node = AutomationUtil.findNextNode(this.node_, dir, 194 newNode = AutomationUtil.findNextNode(newNode, dir,
196 AutomationPredicate.leaf); 195 AutomationPredicate.leaf);
197 if (node) { 196 if (newNode) {
198 newNode = node;
199 newIndex = 0; 197 newIndex = 0;
200 if (dir == Dir.BACKWARD && 198 if (dir == Dir.BACKWARD &&
201 node.role == Role.inlineTextBox) { 199 newNode.role == Role.inlineTextBox) {
202 var starts = node.attributes.wordStarts; 200 var starts = newNode.attributes.wordStarts;
203 newIndex = starts[starts.length - 1] || 0; 201 newIndex = starts[starts.length - 1] || 0;
204 } else { 202 } else {
205 // TODO(dtseng): Figure out what to do for general nodes. 203 // TODO(dtseng): Figure out what to do for general nodes.
206 } 204 }
207 } 205 }
208 } 206 }
209 } 207 }
210 } else { 208 } else {
211 // TODO(dtseng): Figure out what to do in this case. 209 // TODO(dtseng): Figure out what to do in this case.
212 } 210 }
213 } 211 }
214 break; 212 break;
215 case Unit.NODE: 213 case Unit.NODE:
216 switch (movement) { 214 switch (movement) {
217 case Movement.BOUND: 215 case Movement.BOUND:
218 newIndex = dir == Dir.FORWARD ? this.getText().length - 1 : 0; 216 newIndex = dir == Dir.FORWARD ? this.getText().length - 1 : 0;
219 break; 217 break;
220 case Movement.DIRECTIONAL: 218 case Movement.DIRECTIONAL:
221 newNode = AutomationUtil.findNextNode( 219 newNode = AutomationUtil.findNextNode(
222 this.node_, dir, AutomationPredicate.leaf) || this.node_; 220 newNode, dir, AutomationPredicate.leaf) || this.node_;
223 newIndex = cursors.NODE_INDEX; 221 newIndex = cursors.NODE_INDEX;
224 break; 222 break;
225 } 223 }
226 break; 224 break;
227 case Unit.LINE: 225 case Unit.LINE:
228 newIndex = 0; 226 newIndex = 0;
229 switch (movement) { 227 switch (movement) {
230 case Movement.BOUND: 228 case Movement.BOUND:
231 newNode = AutomationUtil.findNodeUntil(this.node_, dir, 229 newNode = AutomationUtil.findNodeUntil(newNode, dir,
232 AutomationPredicate.linebreak, {before: true}); 230 AutomationPredicate.linebreak, {before: true});
233 newNode = newNode || this.node_; 231 newNode = newNode || this.node_;
234 newIndex = 232 newIndex =
235 dir == Dir.FORWARD ? this.getText(newNode).length - 1 : 0; 233 dir == Dir.FORWARD ? this.getText(newNode).length : 0;
236 break; 234 break;
237 case Movement.DIRECTIONAL: 235 case Movement.DIRECTIONAL:
238 newNode = AutomationUtil.findNodeUntil( 236 newNode = AutomationUtil.findNodeUntil(
239 this.node_, dir, AutomationPredicate.linebreak); 237 newNode, dir, AutomationPredicate.linebreak);
240
241 // We stick to the beginning of lines out of convention.
242 if (newNode && dir == Dir.BACKWARD) {
243 newNode = AutomationUtil.findNodeUntil(newNode, dir,
244 AutomationPredicate.linebreak, {before: true}) || node;
245 }
246 break; 238 break;
247 } 239 }
248 break; 240 break;
249 default: 241 default:
250 throw 'Unrecognized unit: ' + unit; 242 throw 'Unrecognized unit: ' + unit;
251 } 243 }
252 newNode = newNode || this.node_; 244 newNode = newNode || this.node_;
253 newIndex = goog.isDef(newIndex) ? newIndex : this.index_; 245 newIndex = goog.isDef(newIndex) ? newIndex : this.index_;
254 return new cursors.Cursor(newNode, newIndex); 246 return new cursors.Cursor(newNode, newIndex);
255 } 247 }
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
309 }, 301 },
310 302
311 /** 303 /**
312 * @return {!cursors.Cursor} 304 * @return {!cursors.Cursor}
313 */ 305 */
314 getEnd: function() { 306 getEnd: function() {
315 return this.end_; 307 return this.end_;
316 }, 308 },
317 309
318 /** 310 /**
311 * Returns whether true if this range covers less than a node.
312 * @return {boolean}
313 */
314 isSubNode: function() {
315 return this.getStart().getNode() === this.getEnd().getNode() &&
316 this.getStart().getIndex() > -1 &&
317 this.getEnd().getIndex() > -1;
318 },
319
320 /**
319 * Makes a Range which has been moved from this range by the given unit and 321 * Makes a Range which has been moved from this range by the given unit and
320 * direction. 322 * direction.
321 * @param {Unit} unit 323 * @param {Unit} unit
322 * @param {Dir} dir 324 * @param {Dir} dir
323 * @return {cursors.Range} 325 * @return {cursors.Range}
324 */ 326 */
325 move: function(unit, dir) { 327 move: function(unit, dir) {
326 var newStart = this.start_; 328 var newStart = this.start_;
327 var newEnd = newStart; 329 var newEnd = newStart;
328 switch (unit) { 330 switch (unit) {
329 case Unit.CHARACTER: 331 case Unit.CHARACTER:
330 newStart = newStart.move(unit, Movement.BOUND, dir); 332 newStart = newStart.move(unit, Movement.BOUND, dir);
331 newEnd = newStart.move(unit, Movement.BOUND, Dir.FORWARD); 333 newEnd = newStart.move(unit, Movement.BOUND, Dir.FORWARD);
332 // Character crossed a node; collapses to the end of the node. 334 // Character crossed a node; collapses to the end of the node.
333 if (newStart.getNode() !== newEnd.getNode()) 335 if (newStart.getNode() !== newEnd.getNode())
334 newEnd = newStart; 336 newEnd = newStart;
335 break; 337 break;
336 case Unit.WORD: 338 case Unit.WORD:
337 case Unit.LINE: 339 case Unit.LINE:
340 newStart = newStart.move(unit, Movement.DIRECTIONAL, dir);
341 newStart = newStart.move(unit, Movement.BOUND, Dir.BACKWARD);
342 newEnd = newStart.move(unit, Movement.BOUND, Dir.FORWARD);
343 break;
338 case Unit.NODE: 344 case Unit.NODE:
339 newEnd = newEnd.move(unit, Movement.DIRECTIONAL, dir); 345 newStart = newStart.move(unit, Movement.DIRECTIONAL, dir);
340 newStart = newEnd; 346 newEnd = newStart;
341 newEnd = newEnd.move(unit, Movement.BOUND, Dir.FORWARD);
342 break; 347 break;
343 } 348 }
344 return new cursors.Range(newStart, newEnd); 349 return new cursors.Range(newStart, newEnd);
345 } 350 }
346 }; 351 };
347 352
348 }); // goog.scope 353 }); // goog.scope
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698