| 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 |