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 A class for walking tables. | 6 * @fileoverview A class for walking tables. |
7 * NOTE: This class has a very different interface than the other walkers. | 7 * NOTE: This class has a very different interface than the other walkers. |
8 * This means it does not lend itself easily to e.g. decorators. | 8 * This means it does not lend itself easily to e.g. decorators. |
9 * TODO (stoarca): This might be able to be fixed by breaking it up into | 9 * TODO (stoarca): This might be able to be fixed by breaking it up into |
10 * separate walkers for cell, row and column. | 10 * separate walkers for cell, row and column. |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
42 cvox.TableWalker.prototype.next = function(sel) { | 42 cvox.TableWalker.prototype.next = function(sel) { |
43 // TODO (stoarca): See bug 6677953 | 43 // TODO (stoarca): See bug 6677953 |
44 return this.nextRow(sel); | 44 return this.nextRow(sel); |
45 }; | 45 }; |
46 | 46 |
47 /** | 47 /** |
48 * @override | 48 * @override |
49 */ | 49 */ |
50 cvox.TableWalker.prototype.sync = function(sel) { | 50 cvox.TableWalker.prototype.sync = function(sel) { |
51 return this.goTo_(sel, goog.bind(function(position) { | 51 return this.goTo_(sel, goog.bind(function(position) { |
52 return this.tt.goToCell(position); | 52 return this.tt.goToCell(position); |
53 }, this)); | 53 }, this)); |
54 }; | 54 }; |
55 | 55 |
56 /** | 56 /** |
57 * @override | 57 * @override |
58 * @suppress {checkTypes} actual parameter 2 of | 58 * @suppress {checkTypes} actual parameter 2 of |
59 * Msgs.prototype.getMsg does not match formal parameter | 59 * Msgs.prototype.getMsg does not match formal parameter |
60 * found : Array<number> | 60 * found : Array<number> |
61 * required: (Array<string>|null|undefined) | 61 * required: (Array<string>|null|undefined) |
62 */ | 62 */ |
63 cvox.TableWalker.prototype.getDescription = function(prevSel, sel) { | 63 cvox.TableWalker.prototype.getDescription = function(prevSel, sel) { |
64 var position = this.syncPosition_(sel); | 64 var position = this.syncPosition_(sel); |
65 if (!position) { | 65 if (!position) { |
66 return []; | 66 return []; |
67 } | 67 } |
68 this.tt.goToCell(position); | 68 this.tt.goToCell(position); |
69 var descs = cvox.DescriptionUtil.getCollectionDescription(prevSel, sel); | 69 var descs = cvox.DescriptionUtil.getCollectionDescription(prevSel, sel); |
70 if (descs.length == 0) { | 70 if (descs.length == 0) { |
71 descs.push(new cvox.NavDescription({ | 71 descs.push( |
72 annotation: Msgs.getMsg('empty_cell') | 72 new cvox.NavDescription({annotation: Msgs.getMsg('empty_cell')})); |
73 })); | |
74 } | 73 } |
75 return descs; | 74 return descs; |
76 }; | 75 }; |
77 | 76 |
78 /** | 77 /** |
79 * @override | 78 * @override |
80 */ | 79 */ |
81 cvox.TableWalker.prototype.getBraille = function(prevSel, sel) { | 80 cvox.TableWalker.prototype.getBraille = function(prevSel, sel) { |
82 var ret = new cvox.NavBraille({}); | 81 var ret = new cvox.NavBraille({}); |
83 var position = this.syncPosition_(sel); | 82 var position = this.syncPosition_(sel); |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
172 | 171 |
173 /** | 172 /** |
174 * Returns the first cell in the row after the current selection. | 173 * Returns the first cell in the row after the current selection. |
175 * @param {!cvox.CursorSelection} sel The selection. | 174 * @param {!cvox.CursorSelection} sel The selection. |
176 * @return {cvox.CursorSelection} The selection for the first cell in the next | 175 * @return {cvox.CursorSelection} The selection for the first cell in the next |
177 * row. | 176 * row. |
178 * @export | 177 * @export |
179 */ | 178 */ |
180 cvox.TableWalker.prototype.nextRow = function(sel) { | 179 cvox.TableWalker.prototype.nextRow = function(sel) { |
181 return this.goTo_(sel, goog.bind(function(position) { | 180 return this.goTo_(sel, goog.bind(function(position) { |
182 return this.tt.goToCell([position[0] + (sel.isReversed() ? -1 : 1), | 181 return this.tt.goToCell( |
183 position[1]]); | 182 [position[0] + (sel.isReversed() ? -1 : 1), position[1]]); |
184 }, this)); | 183 }, this)); |
185 }; | 184 }; |
186 | 185 |
187 /** | 186 /** |
188 * Returns the first cell in the column after the current selection. | 187 * Returns the first cell in the column after the current selection. |
189 * @param {!cvox.CursorSelection} sel The selection. | 188 * @param {!cvox.CursorSelection} sel The selection. |
190 * @return {cvox.CursorSelection} The selection for the first cell in the | 189 * @return {cvox.CursorSelection} The selection for the first cell in the |
191 * next col. | 190 * next col. |
192 * @export | 191 * @export |
193 */ | 192 */ |
194 cvox.TableWalker.prototype.nextCol = function(sel) { | 193 cvox.TableWalker.prototype.nextCol = function(sel) { |
195 return this.goTo_(sel, goog.bind(function(position) { | 194 return this.goTo_(sel, goog.bind(function(position) { |
196 return this.tt.goToCell([position[0], | 195 return this.tt.goToCell( |
197 position[1] + (sel.isReversed() ? -1 : 1)]); | 196 [position[0], position[1] + (sel.isReversed() ? -1 : 1)]); |
198 }, this)); | 197 }, this)); |
199 }; | 198 }; |
200 | 199 |
201 /** | 200 /** |
202 * @param {!cvox.CursorSelection} sel The current selection. | 201 * @param {!cvox.CursorSelection} sel The current selection. |
203 * @return {cvox.CursorSelection} The resulting selection. | 202 * @return {cvox.CursorSelection} The resulting selection. |
204 * @export | 203 * @export |
205 */ | 204 */ |
206 cvox.TableWalker.prototype.announceHeaders = function(sel) { | 205 cvox.TableWalker.prototype.announceHeaders = function(sel) { |
207 cvox.ChromeVox.tts.speak(this.getHeaderText_(sel), | 206 cvox.ChromeVox.tts.speak( |
208 cvox.QueueMode.FLUSH, | 207 this.getHeaderText_(sel), cvox.QueueMode.FLUSH, |
209 cvox.AbstractTts.PERSONALITY_ANNOTATION); | 208 cvox.AbstractTts.PERSONALITY_ANNOTATION); |
210 return sel; | 209 return sel; |
211 }; | 210 }; |
212 | 211 |
213 /** | 212 /** |
214 * @param {!cvox.CursorSelection} sel The current selection. | 213 * @param {!cvox.CursorSelection} sel The current selection. |
215 * @return {cvox.CursorSelection} The resulting selection. | 214 * @return {cvox.CursorSelection} The resulting selection. |
216 * @export | 215 * @export |
217 */ | 216 */ |
218 cvox.TableWalker.prototype.speakTableLocation = function(sel) { | 217 cvox.TableWalker.prototype.speakTableLocation = function(sel) { |
219 cvox.ChromeVox.navigationManager.speakDescriptionArray( | 218 cvox.ChromeVox.navigationManager.speakDescriptionArray( |
220 this.getLocationDescription_(sel), | 219 this.getLocationDescription_(sel), cvox.QueueMode.FLUSH, null); |
221 cvox.QueueMode.FLUSH, | |
222 null); | |
223 return sel; | 220 return sel; |
224 }; | 221 }; |
225 | 222 |
226 | 223 |
227 /** | 224 /** |
228 * @param {!cvox.CursorSelection} sel The current selection. | 225 * @param {!cvox.CursorSelection} sel The current selection. |
229 * @return {cvox.CursorSelection} The resulting selection. | 226 * @return {cvox.CursorSelection} The resulting selection. |
230 * @export | 227 * @export |
231 */ | 228 */ |
232 cvox.TableWalker.prototype.exitShifterContent = function(sel) { | 229 cvox.TableWalker.prototype.exitShifterContent = function(sel) { |
(...skipping 18 matching lines...) Expand all Loading... |
251 cvox.TableWalker.prototype.getHeaderText_ = function(sel) { | 248 cvox.TableWalker.prototype.getHeaderText_ = function(sel) { |
252 this.tt.initialize(this.getTableNode_(sel)); | 249 this.tt.initialize(this.getTableNode_(sel)); |
253 var position = this.tt.findNearestCursor(sel.start.node); | 250 var position = this.tt.findNearestCursor(sel.start.node); |
254 if (!position) { | 251 if (!position) { |
255 return Msgs.getMsg('not_inside_table'); | 252 return Msgs.getMsg('not_inside_table'); |
256 } | 253 } |
257 if (!this.tt.goToCell(position)) { | 254 if (!this.tt.goToCell(position)) { |
258 return Msgs.getMsg('not_inside_table'); | 255 return Msgs.getMsg('not_inside_table'); |
259 } | 256 } |
260 return ( | 257 return ( |
261 this.getRowHeaderText_(position) + | 258 this.getRowHeaderText_(position) + ' ' + |
262 ' ' + | |
263 this.getColHeaderText_(position)); | 259 this.getColHeaderText_(position)); |
264 }; | 260 }; |
265 | 261 |
266 /** | 262 /** |
267 * Returns the location description. | 263 * Returns the location description. |
268 * @param {!cvox.CursorSelection} sel A valid selection. | 264 * @param {!cvox.CursorSelection} sel A valid selection. |
269 * @return {Array<cvox.NavDescription>} The location description. | 265 * @return {Array<cvox.NavDescription>} The location description. |
270 * @suppress {checkTypes} actual parameter 2 of | 266 * @suppress {checkTypes} actual parameter 2 of |
271 * Msgs.prototype.getMsg does not match | 267 * Msgs.prototype.getMsg does not match |
272 * formal parameter | 268 * formal parameter |
273 * found : Array<number> | 269 * found : Array<number> |
274 * required: (Array<string>|null|undefined) | 270 * required: (Array<string>|null|undefined) |
275 * @private | 271 * @private |
276 */ | 272 */ |
277 cvox.TableWalker.prototype.getLocationDescription_ = function(sel) { | 273 cvox.TableWalker.prototype.getLocationDescription_ = function(sel) { |
278 var locationInfo = this.getLocationInfo(sel); | 274 var locationInfo = this.getLocationInfo(sel); |
279 if (locationInfo == null) { | 275 if (locationInfo == null) { |
280 return null; | 276 return null; |
281 } | 277 } |
282 return [new cvox.NavDescription({ | 278 return [new cvox.NavDescription( |
283 text: Msgs.getMsg('table_location', locationInfo) | 279 {text: Msgs.getMsg('table_location', locationInfo)})]; |
284 })]; | |
285 }; | 280 }; |
286 | 281 |
287 /** | 282 /** |
288 * Returns the text content of the row header(s) of the cell that contains sel. | 283 * Returns the text content of the row header(s) of the cell that contains sel. |
289 * @param {!Array<number>} position The selection. | 284 * @param {!Array<number>} position The selection. |
290 * @return {!string} The header text. | 285 * @return {!string} The header text. |
291 * @private | 286 * @private |
292 */ | 287 */ |
293 cvox.TableWalker.prototype.getRowHeaderText_ = function(position) { | 288 cvox.TableWalker.prototype.getRowHeaderText_ = function(position) { |
294 // TODO(stoarca): OPTMZ Replace with join(); | 289 // TODO(stoarca): OPTMZ Replace with join(); |
295 var rowHeaderText = ''; | 290 var rowHeaderText = ''; |
296 | 291 |
297 var rowHeaders = this.tt.getCellRowHeaders(); | 292 var rowHeaders = this.tt.getCellRowHeaders(); |
298 if (rowHeaders.length == 0) { | 293 if (rowHeaders.length == 0) { |
299 var firstCellInRow = this.tt.getCellAt([position[0], 0]); | 294 var firstCellInRow = this.tt.getCellAt([position[0], 0]); |
300 rowHeaderText += cvox.DomUtil.collapseWhitespace( | 295 rowHeaderText += cvox.DomUtil.collapseWhitespace( |
301 cvox.DomUtil.getValue(firstCellInRow) + ' ' + | 296 cvox.DomUtil.getValue(firstCellInRow) + ' ' + |
302 cvox.DomUtil.getName(firstCellInRow)); | 297 cvox.DomUtil.getName(firstCellInRow)); |
303 return Msgs.getMsg('row_header') + rowHeaderText; | 298 return Msgs.getMsg('row_header') + rowHeaderText; |
304 } | 299 } |
305 | 300 |
306 for (var i = 0; i < rowHeaders.length; ++i) { | 301 for (var i = 0; i < rowHeaders.length; ++i) { |
307 rowHeaderText += cvox.DomUtil.collapseWhitespace( | 302 rowHeaderText += cvox.DomUtil.collapseWhitespace( |
308 cvox.DomUtil.getValue(rowHeaders[i]) + ' ' + | 303 cvox.DomUtil.getValue(rowHeaders[i]) + ' ' + |
309 cvox.DomUtil.getName(rowHeaders[i])); | 304 cvox.DomUtil.getName(rowHeaders[i])); |
310 } | 305 } |
311 if (rowHeaderText == '') { | 306 if (rowHeaderText == '') { |
312 return Msgs.getMsg('empty_row_header'); | 307 return Msgs.getMsg('empty_row_header'); |
313 } | 308 } |
314 return Msgs.getMsg('row_header') + rowHeaderText; | 309 return Msgs.getMsg('row_header') + rowHeaderText; |
315 }; | 310 }; |
316 | 311 |
317 /** | 312 /** |
318 * Returns the text content of the col header(s) of the cell that contains sel. | 313 * Returns the text content of the col header(s) of the cell that contains sel. |
319 * @param {!Array<number>} position The selection. | 314 * @param {!Array<number>} position The selection. |
320 * @return {!string} The header text. | 315 * @return {!string} The header text. |
321 * @private | 316 * @private |
322 */ | 317 */ |
323 cvox.TableWalker.prototype.getColHeaderText_ = function(position) { | 318 cvox.TableWalker.prototype.getColHeaderText_ = function(position) { |
324 // TODO(stoarca): OPTMZ Replace with join(); | 319 // TODO(stoarca): OPTMZ Replace with join(); |
325 var colHeaderText = ''; | 320 var colHeaderText = ''; |
326 | 321 |
327 var colHeaders = this.tt.getCellColHeaders(); | 322 var colHeaders = this.tt.getCellColHeaders(); |
328 if (colHeaders.length == 0) { | 323 if (colHeaders.length == 0) { |
329 var firstCellInCol = this.tt.getCellAt([0, position[1]]); | 324 var firstCellInCol = this.tt.getCellAt([0, position[1]]); |
330 colHeaderText += cvox.DomUtil.collapseWhitespace( | 325 colHeaderText += cvox.DomUtil.collapseWhitespace( |
331 cvox.DomUtil.getValue(firstCellInCol) + ' ' + | 326 cvox.DomUtil.getValue(firstCellInCol) + ' ' + |
332 cvox.DomUtil.getName(firstCellInCol)); | 327 cvox.DomUtil.getName(firstCellInCol)); |
333 return Msgs.getMsg('column_header') + colHeaderText; | 328 return Msgs.getMsg('column_header') + colHeaderText; |
334 } | 329 } |
335 | 330 |
336 for (var i = 0; i < colHeaders.length; ++i) { | 331 for (var i = 0; i < colHeaders.length; ++i) { |
337 colHeaderText += cvox.DomUtil.collapseWhitespace( | 332 colHeaderText += cvox.DomUtil.collapseWhitespace( |
338 cvox.DomUtil.getValue(colHeaders[i]) + ' ' + | 333 cvox.DomUtil.getValue(colHeaders[i]) + ' ' + |
339 cvox.DomUtil.getName(colHeaders[i])); | 334 cvox.DomUtil.getName(colHeaders[i])); |
340 } | 335 } |
341 if (colHeaderText == '') { | 336 if (colHeaderText == '') { |
342 return Msgs.getMsg('empty_row_header'); | 337 return Msgs.getMsg('empty_row_header'); |
343 } | 338 } |
344 return Msgs.getMsg('column_header') + colHeaderText; | 339 return Msgs.getMsg('column_header') + colHeaderText; |
345 }; | 340 }; |
346 | 341 |
347 /** | 342 /** |
348 * Returns the location info of sel within the containing table. | 343 * Returns the location info of sel within the containing table. |
349 * @param {!cvox.CursorSelection} sel The selection. | 344 * @param {!cvox.CursorSelection} sel The selection. |
350 * @return {Array<number>} The location info: | 345 * @return {Array<number>} The location info: |
351 * [row index, row count, col index, col count]. | 346 * [row index, row count, col index, col count]. |
352 */ | 347 */ |
353 cvox.TableWalker.prototype.getLocationInfo = function(sel) { | 348 cvox.TableWalker.prototype.getLocationInfo = function(sel) { |
354 this.tt.initialize(this.getTableNode_(sel)); | 349 this.tt.initialize(this.getTableNode_(sel)); |
355 var position = this.tt.findNearestCursor(sel.start.node); | 350 var position = this.tt.findNearestCursor(sel.start.node); |
356 if (!position) { | 351 if (!position) { |
357 return null; | 352 return null; |
358 } | 353 } |
359 // + 1 to account for 0-indexed | 354 // + 1 to account for 0-indexed |
360 return [ | 355 return [ |
361 position[0] + 1, | 356 position[0] + 1, this.tt.rowCount, position[1] + 1, this.tt.colCount |
362 this.tt.rowCount, | 357 ].map(function(x) { |
363 position[1] + 1, | 358 return Msgs.getNumber(x); |
364 this.tt.colCount | 359 }); |
365 ].map(function(x) {return Msgs.getNumber(x);}); | |
366 }; | 360 }; |
367 | 361 |
368 /** | 362 /** |
369 * Returns true if sel is inside a table. | 363 * Returns true if sel is inside a table. |
370 * @param {!cvox.CursorSelection} sel The selection. | 364 * @param {!cvox.CursorSelection} sel The selection. |
371 * @return {boolean} True if inside a table node. | 365 * @return {boolean} True if inside a table node. |
372 */ | 366 */ |
373 cvox.TableWalker.prototype.isInTable = function(sel) { | 367 cvox.TableWalker.prototype.isInTable = function(sel) { |
374 return this.getTableNode_(sel) != null; | 368 return this.getTableNode_(sel) != null; |
375 }; | 369 }; |
(...skipping 13 matching lines...) Expand all Loading... |
389 } | 383 } |
390 this.tt.initialize(this.getTableNode_(sel)); | 384 this.tt.initialize(this.getTableNode_(sel)); |
391 var position = this.tt.findNearestCursor(sel.end.node); | 385 var position = this.tt.findNearestCursor(sel.end.node); |
392 if (!position) { | 386 if (!position) { |
393 return null; | 387 return null; |
394 } | 388 } |
395 this.tt.goToCell(position); | 389 this.tt.goToCell(position); |
396 if (!f(position)) { | 390 if (!f(position)) { |
397 return null; | 391 return null; |
398 } | 392 } |
399 return cvox.CursorSelection.fromNode(this.tt.getCell()). | 393 return cvox.CursorSelection.fromNode(this.tt.getCell()) |
400 setReversed(sel.isReversed()); | 394 .setReversed(sel.isReversed()); |
401 }; | 395 }; |
402 | 396 |
403 /** | 397 /** |
404 * Returns the nearest table node containing the end of the selection | 398 * Returns the nearest table node containing the end of the selection |
405 * @param {!cvox.CursorSelection} sel The selection. | 399 * @param {!cvox.CursorSelection} sel The selection. |
406 * @return {Node} The table node containing sel. null if not in a table. | 400 * @return {Node} The table node containing sel. null if not in a table. |
407 * @private | 401 * @private |
408 */ | 402 */ |
409 cvox.TableWalker.prototype.getTableNode_ = function(sel) { | 403 cvox.TableWalker.prototype.getTableNode_ = function(sel) { |
410 return cvox.DomUtil.getContainingTable(sel.end.node); | 404 return cvox.DomUtil.getContainingTable(sel.end.node); |
411 }; | 405 }; |
412 | 406 |
413 /** | 407 /** |
414 * Sync the backing traversal utility to the given selection. | 408 * Sync the backing traversal utility to the given selection. |
415 * @param {!cvox.CursorSelection} sel The selection. | 409 * @param {!cvox.CursorSelection} sel The selection. |
416 * @return {Array<number>} The position [x, y] of the selection. | 410 * @return {Array<number>} The position [x, y] of the selection. |
417 * @private | 411 * @private |
418 */ | 412 */ |
419 cvox.TableWalker.prototype.syncPosition_ = function(sel) { | 413 cvox.TableWalker.prototype.syncPosition_ = function(sel) { |
420 var tableNode = this.getTableNode_(sel); | 414 var tableNode = this.getTableNode_(sel); |
421 this.tt.initialize(tableNode); | 415 this.tt.initialize(tableNode); |
422 // we need to align the TraverseTable with our sel because our walker | 416 // we need to align the TraverseTable with our sel because our walker |
423 // uses parts of it (for example isSpanned relies on being at a specific cell) | 417 // uses parts of it (for example isSpanned relies on being at a specific cell) |
424 return this.tt.findNearestCursor(sel.end.node); | 418 return this.tt.findNearestCursor(sel.end.node); |
425 }; | 419 }; |
OLD | NEW |