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

Side by Side Diff: chrome/browser/resources/chromeos/chromevox/common/traverse_table.js

Issue 2943193002: Run clang-format on .js files in c/b/r/chromeos/chromevox (Closed)
Patch Set: Created 3 years, 6 months 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 * TODO(stoarca): This class has become obsolete except for the shadow table. 6 * TODO(stoarca): This class has become obsolete except for the shadow table.
7 * Chop most of it away. 7 * Chop most of it away.
8 * @fileoverview A DOM traversal interface for navigating data in tables. 8 * @fileoverview A DOM traversal interface for navigating data in tables.
9 */ 9 */
10 10
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after
230 this.colCount = this.shadowColCount_(); 230 this.colCount = this.shadowColCount_();
231 this.rowCount = this.countRows_(); 231 this.rowCount = this.countRows_();
232 232
233 this.findHeaderCells_(); 233 this.findHeaderCells_();
234 234
235 // Listen for changes to the active table. If the active table changes, 235 // Listen for changes to the active table. If the active table changes,
236 // rebuild the shadow table. 236 // rebuild the shadow table.
237 // TODO (stoarca): Is this safe? When this object goes away, doesn't the 237 // TODO (stoarca): Is this safe? When this object goes away, doesn't the
238 // eventListener stay on the node? Someone with better knowledge of js 238 // eventListener stay on the node? Someone with better knowledge of js
239 // please confirm. If so, this is a leak. 239 // please confirm. If so, this is a leak.
240 this.activeTable_.addEventListener('DOMSubtreeModified', 240 this.activeTable_.addEventListener(
241 goog.bind(function() { 241 'DOMSubtreeModified', goog.bind(function() {
242 this.buildShadowTable_(); 242 this.buildShadowTable_();
243 this.colCount = this.shadowColCount_(); 243 this.colCount = this.shadowColCount_();
244 this.rowCount = this.countRows_(); 244 this.rowCount = this.countRows_();
245 245
246 this.tableRowHeaders = []; 246 this.tableRowHeaders = [];
247 this.tableColHeaders = []; 247 this.tableColHeaders = [];
248 this.findHeaderCells_(); 248 this.findHeaderCells_();
249 249
250 if (this.colCount == 0 && this.rowCount == 0) { 250 if (this.colCount == 0 && this.rowCount == 0) {
251 return; 251 return;
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
288 // DomUtil.findTableNodeInList excluding captions from tables because 288 // DomUtil.findTableNodeInList excluding captions from tables because
289 // it makes them non-contiguous. 289 // it makes them non-contiguous.
290 if (!cvox.DomUtil.getContainingTable(n, {allowCaptions: true})) { 290 if (!cvox.DomUtil.getContainingTable(n, {allowCaptions: true})) {
291 return null; 291 return null;
292 } 292 }
293 } 293 }
294 for (var i = 0; i < this.rowCount; ++i) { 294 for (var i = 0; i < this.rowCount; ++i) {
295 for (var j = 0; j < this.colCount; ++j) { 295 for (var j = 0; j < this.colCount; ++j) {
296 if (this.shadowTable_[i][j]) { 296 if (this.shadowTable_[i][j]) {
297 if (cvox.DomUtil.isDescendantOfNode( 297 if (cvox.DomUtil.isDescendantOfNode(
298 n, this.shadowTable_[i][j].activeCell)) { 298 n, this.shadowTable_[i][j].activeCell)) {
299 return [i, j]; 299 return [i, j];
300 } 300 }
301 } 301 }
302 } 302 }
303 } 303 }
304 return null; 304 return null;
305 }; 305 };
306 306
307 /** 307 /**
308 * Finds the valid cell nearest to the current cell cursor and moves the cell 308 * Finds the valid cell nearest to the current cell cursor and moves the cell
(...skipping 18 matching lines...) Expand all
327 this.currentCellCursor = [currentCursor[0], (currentRow.length - 1)]; 327 this.currentCellCursor = [currentCursor[0], (currentRow.length - 1)];
328 } else { 328 } else {
329 // Current row does not exist anymore. Does current column still exist? 329 // Current row does not exist anymore. Does current column still exist?
330 // Try last cell of current column 330 // Try last cell of current column
331 var numRows = this.shadowTable_.length; 331 var numRows = this.shadowTable_.length;
332 if (numRows == 0) { 332 if (numRows == 0) {
333 // Table has been deleted! 333 // Table has been deleted!
334 this.currentCellCursor = null; 334 this.currentCellCursor = null;
335 return; 335 return;
336 } 336 }
337 var aboveCell = 337 var aboveCell = this.shadowTable_[numRows - 1][currentCursor[1]];
338 this.shadowTable_[numRows - 1][currentCursor[1]];
339 if (aboveCell) { 338 if (aboveCell) {
340 this.currentCellCursor = [(numRows - 1), currentCursor[1]]; 339 this.currentCellCursor = [(numRows - 1), currentCursor[1]];
341 } else { 340 } else {
342 // Current column does not exist anymore either. 341 // Current column does not exist anymore either.
343 // Move cursor to last cell in table. 342 // Move cursor to last cell in table.
344 this.goToLastCell(); 343 this.goToLastCell();
345 } 344 }
346 } 345 }
347 }; 346 };
348 347
(...skipping 23 matching lines...) Expand all
372 // Iterate through active table by row 371 // Iterate through active table by row
373 for (var i = 0; i < allRows.length; i++) { 372 for (var i = 0; i < allRows.length; i++) {
374 var childCells = cvox.TableUtil.getChildCells(allRows[i]); 373 var childCells = cvox.TableUtil.getChildCells(allRows[i]);
375 374
376 // Keep track of position in active table 375 // Keep track of position in active table
377 var activeTableCol = 0; 376 var activeTableCol = 0;
378 // Keep track of position in shadow table 377 // Keep track of position in shadow table
379 var shadowTableCol = 0; 378 var shadowTableCol = 0;
380 379
381 while (activeTableCol < childCells.length) { 380 while (activeTableCol < childCells.length) {
382
383 // Check to make sure we haven't already filled this cell. 381 // Check to make sure we haven't already filled this cell.
384 if (this.shadowTable_[i][shadowTableCol] == null) { 382 if (this.shadowTable_[i][shadowTableCol] == null) {
385
386 var activeTableCell = childCells[activeTableCol]; 383 var activeTableCell = childCells[activeTableCol];
387 384
388 // Default value for colspan and rowspan is 1 385 // Default value for colspan and rowspan is 1
389 var colsSpanned = 1; 386 var colsSpanned = 1;
390 var rowsSpanned = 1; 387 var rowsSpanned = 1;
391 388
392 if (activeTableCell.hasAttribute('colspan')) { 389 if (activeTableCell.hasAttribute('colspan')) {
393 390 colsSpanned = parseInt(activeTableCell.getAttribute('colspan'), 10);
394 colsSpanned =
395 parseInt(activeTableCell.getAttribute('colspan'), 10);
396 391
397 if ((isNaN(colsSpanned)) || (colsSpanned <= 0)) { 392 if ((isNaN(colsSpanned)) || (colsSpanned <= 0)) {
398 // The HTML5 spec defines colspan MUST be greater than 0: 393 // The HTML5 spec defines colspan MUST be greater than 0:
399 // http://dev.w3.org/html5/spec/Overview.html#attr-tdth-colspan 394 // http://dev.w3.org/html5/spec/Overview.html#attr-tdth-colspan
400 // 395 //
401 // This is a change from the HTML4 spec: 396 // This is a change from the HTML4 spec:
402 // http://www.w3.org/TR/html401/struct/tables.html#adef-colspan 397 // http://www.w3.org/TR/html401/struct/tables.html#adef-colspan
403 // 398 //
404 // We will degrade gracefully by treating a colspan=0 as 399 // We will degrade gracefully by treating a colspan=0 as
405 // equivalent to a colspan=1. 400 // equivalent to a colspan=1.
406 // Tested in method testColSpan0 in rowColSpanTable_test.js 401 // Tested in method testColSpan0 in rowColSpanTable_test.js
407 colsSpanned = 1; 402 colsSpanned = 1;
408 } 403 }
409 } 404 }
410 if (activeTableCell.hasAttribute('rowspan')) { 405 if (activeTableCell.hasAttribute('rowspan')) {
411 rowsSpanned = 406 rowsSpanned = parseInt(activeTableCell.getAttribute('rowspan'), 10);
412 parseInt(activeTableCell.getAttribute('rowspan'), 10);
413 407
414 if ((isNaN(rowsSpanned)) || (rowsSpanned <= 0)) { 408 if ((isNaN(rowsSpanned)) || (rowsSpanned <= 0)) {
415 // The HTML5 spec defines that rowspan can be any non-negative 409 // The HTML5 spec defines that rowspan can be any non-negative
416 // integer, including 0: 410 // integer, including 0:
417 // http://dev.w3.org/html5/spec/Overview.html#attr-tdth-rowspan 411 // http://dev.w3.org/html5/spec/Overview.html#attr-tdth-rowspan
418 // 412 //
419 // However, Chromium treats rowspan=0 as rowspan=1. This appears 413 // However, Chromium treats rowspan=0 as rowspan=1. This appears
420 // to be a bug from WebKit: 414 // to be a bug from WebKit:
421 // https://bugs.webkit.org/show_bug.cgi?id=10300 415 // https://bugs.webkit.org/show_bug.cgi?id=10300
422 // Inherited from a bug (since fixed) in KDE: 416 // Inherited from a bug (since fixed) in KDE:
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
481 } 475 }
482 shadowNode.rowGroup = currentRowGroup; 476 shadowNode.rowGroup = currentRowGroup;
483 477
484 // Check and update col group status 478 // Check and update col group status
485 if (colToColGroup.length > 0) { 479 if (colToColGroup.length > 0) {
486 shadowNode.colGroup = colToColGroup[shadowTableCol]; 480 shadowNode.colGroup = colToColGroup[shadowTableCol];
487 } else { 481 } else {
488 shadowNode.colGroup = 0; 482 shadowNode.colGroup = 0;
489 } 483 }
490 484
491 if (! shadowNode.spanned) { 485 if (!shadowNode.spanned) {
492 if (activeTableCell.id != null) { 486 if (activeTableCell.id != null) {
493 this.idToShadowNode_[activeTableCell.id] = shadowNode; 487 this.idToShadowNode_[activeTableCell.id] = shadowNode;
494 } 488 }
495 } 489 }
496 490
497 this.shadowTable_[i + r][shadowTableCol + c] = shadowNode; 491 this.shadowTable_[i + r][shadowTableCol + c] = shadowNode;
498 } 492 }
499 } 493 }
500 shadowTableCol += colsSpanned; 494 shadowTableCol += colsSpanned;
501 activeTableCol++; 495 activeTableCol++;
(...skipping 17 matching lines...) Expand all
519 * rowHeaderCells or colHeaderCells arrays. 513 * rowHeaderCells or colHeaderCells arrays.
520 * 514 *
521 * @private 515 * @private
522 */ 516 */
523 cvox.TraverseTable.prototype.findHeaderCells_ = function() { 517 cvox.TraverseTable.prototype.findHeaderCells_ = function() {
524 // Forming relationships between data cells and header cells: 518 // Forming relationships between data cells and header cells:
525 // http://dev.w3.org/html5/spec/tabular-data.html 519 // http://dev.w3.org/html5/spec/tabular-data.html
526 // #header-and-data-cell-semantics 520 // #header-and-data-cell-semantics
527 521
528 for (var i = 0; i < this.candidateHeaders_.length; i++) { 522 for (var i = 0; i < this.candidateHeaders_.length; i++) {
529
530 var currentShadowNode = this.candidateHeaders_[i]; 523 var currentShadowNode = this.candidateHeaders_[i];
531 var currentCell = currentShadowNode.activeCell; 524 var currentCell = currentShadowNode.activeCell;
532 525
533 var assumedScope = null; 526 var assumedScope = null;
534 var specifiedScope = null; 527 var specifiedScope = null;
535 528
536 if (currentShadowNode.spanned) { 529 if (currentShadowNode.spanned) {
537 continue; 530 continue;
538 } 531 }
539 532
540 if ((currentCell.tagName == 'TH') && 533 if ((currentCell.tagName == 'TH') && !(currentCell.hasAttribute('scope'))) {
541 !(currentCell.hasAttribute('scope'))) {
542 // No scope specified - compute scope ourselves. 534 // No scope specified - compute scope ourselves.
543 // Go left/right - if there's a header node, then this is a column 535 // Go left/right - if there's a header node, then this is a column
544 // header 536 // header
545 if (currentShadowNode.j > 0) { 537 if (currentShadowNode.j > 0) {
546 if (this.shadowTable_[currentShadowNode.i][currentShadowNode.j - 1]. 538 if (this.shadowTable_[currentShadowNode.i][currentShadowNode.j - 1]
547 activeCell.tagName == 'TH') { 539 .activeCell.tagName == 'TH') {
548 assumedScope = 'col'; 540 assumedScope = 'col';
549 } 541 }
550 } else if (currentShadowNode.j < this.shadowTable_[currentShadowNode.i]. 542 } else if (
551 length - 1) { 543 currentShadowNode.j <
552 if (this.shadowTable_[currentShadowNode.i][currentShadowNode.j + 1]. 544 this.shadowTable_[currentShadowNode.i].length - 1) {
553 activeCell.tagName == 'TH') { 545 if (this.shadowTable_[currentShadowNode.i][currentShadowNode.j + 1]
546 .activeCell.tagName == 'TH') {
554 assumedScope = 'col'; 547 assumedScope = 'col';
555 } 548 }
556 } else { 549 } else {
557 // This row has a width of 1 cell, just assume this is a colum header 550 // This row has a width of 1 cell, just assume this is a colum header
558 assumedScope = 'col'; 551 assumedScope = 'col';
559 } 552 }
560 553
561 if (assumedScope == null) { 554 if (assumedScope == null) {
562 // Go up/down - if there's a header node, then this is a row header 555 // Go up/down - if there's a header node, then this is a row header
563 if (currentShadowNode.i > 0) { 556 if (currentShadowNode.i > 0) {
564 if (this.shadowTable_[currentShadowNode.i - 1][currentShadowNode.j]. 557 if (this.shadowTable_[currentShadowNode.i - 1][currentShadowNode.j]
565 activeCell.tagName == 'TH') { 558 .activeCell.tagName == 'TH') {
566 assumedScope = 'row'; 559 assumedScope = 'row';
567 } 560 }
568 } else if (currentShadowNode.i < this.shadowTable_.length - 1) { 561 } else if (currentShadowNode.i < this.shadowTable_.length - 1) {
569 if (this.shadowTable_[currentShadowNode.i + 1][currentShadowNode.j]. 562 if (this.shadowTable_[currentShadowNode.i + 1][currentShadowNode.j]
570 activeCell.tagName == 'TH') { 563 .activeCell.tagName == 'TH') {
571 assumedScope = 'row'; 564 assumedScope = 'row';
572 } 565 }
573 } else { 566 } else {
574 // This column has a height of 1 cell, just assume that this is 567 // This column has a height of 1 cell, just assume that this is
575 // a row header 568 // a row header
576 assumedScope = 'row'; 569 assumedScope = 'row';
577 } 570 }
578 } 571 }
579 } else if (currentCell.hasAttribute('scope')) { 572 } else if (currentCell.hasAttribute('scope')) {
580 specifiedScope = currentCell.getAttribute('scope'); 573 specifiedScope = currentCell.getAttribute('scope');
581 } else if (currentCell.hasAttribute('role') && 574 } else if (
575 currentCell.hasAttribute('role') &&
582 (currentCell.getAttribute('role') == 'rowheader')) { 576 (currentCell.getAttribute('role') == 'rowheader')) {
583 specifiedScope = 'row'; 577 specifiedScope = 'row';
584 } else if (currentCell.hasAttribute('role') && 578 } else if (
579 currentCell.hasAttribute('role') &&
585 (currentCell.getAttribute('role') == 'columnheader')) { 580 (currentCell.getAttribute('role') == 'columnheader')) {
586 specifiedScope = 'col'; 581 specifiedScope = 'col';
587 } 582 }
588 583
589 if ((specifiedScope == 'row') || (assumedScope == 'row')) { 584 if ((specifiedScope == 'row') || (assumedScope == 'row')) {
590 currentShadowNode.isRowHeader = true; 585 currentShadowNode.isRowHeader = true;
591 586
592 // Go right until you hit the edge of the table or a data 587 // Go right until you hit the edge of the table or a data
593 // cell after another header cell. 588 // cell after another header cell.
594 // Add this cell to each shadowNode.rowHeaderCells attribute as you go. 589 // Add this cell to each shadowNode.rowHeaderCells attribute as you go.
595 for (var rightCtr = currentShadowNode.j; 590 for (var rightCtr = currentShadowNode.j;
596 rightCtr < this.shadowTable_[currentShadowNode.i].length; 591 rightCtr < this.shadowTable_[currentShadowNode.i].length;
597 rightCtr++) { 592 rightCtr++) {
598
599 var rightShadowNode = this.shadowTable_[currentShadowNode.i][rightCtr]; 593 var rightShadowNode = this.shadowTable_[currentShadowNode.i][rightCtr];
600 var rightCell = rightShadowNode.activeCell; 594 var rightCell = rightShadowNode.activeCell;
601 595
602 if ((rightCell.tagName == 'TH') || 596 if ((rightCell.tagName == 'TH') || (rightCell.hasAttribute('scope'))) {
603 (rightCell.hasAttribute('scope'))) {
604
605 if (rightCtr < this.shadowTable_[currentShadowNode.i].length - 1) { 597 if (rightCtr < this.shadowTable_[currentShadowNode.i].length - 1) {
606 var checkDataCell = 598 var checkDataCell =
607 this.shadowTable_[currentShadowNode.i][rightCtr + 1]; 599 this.shadowTable_[currentShadowNode.i][rightCtr + 1];
608 } 600 }
609 } 601 }
610 rightShadowNode.rowHeaderCells.push(currentCell); 602 rightShadowNode.rowHeaderCells.push(currentCell);
611 } 603 }
612 this.tableRowHeaders.push(currentCell); 604 this.tableRowHeaders.push(currentCell);
613 } else if ((specifiedScope == 'col') || (assumedScope == 'col')) { 605 } else if ((specifiedScope == 'col') || (assumedScope == 'col')) {
614 currentShadowNode.isColHeader = true; 606 currentShadowNode.isColHeader = true;
615 607
616 // Go down until you hit the edge of the table or a data cell 608 // Go down until you hit the edge of the table or a data cell
617 // after another header cell. 609 // after another header cell.
618 // Add this cell to each shadowNode.colHeaders attribute as you go. 610 // Add this cell to each shadowNode.colHeaders attribute as you go.
619 611
620 for (var downCtr = currentShadowNode.i; 612 for (var downCtr = currentShadowNode.i;
621 downCtr < this.shadowTable_.length; 613 downCtr < this.shadowTable_.length; downCtr++) {
622 downCtr++) {
623
624 var downShadowNode = this.shadowTable_[downCtr][currentShadowNode.j]; 614 var downShadowNode = this.shadowTable_[downCtr][currentShadowNode.j];
625 if (downShadowNode == null) { 615 if (downShadowNode == null) {
626 break; 616 break;
627 } 617 }
628 var downCell = downShadowNode.activeCell; 618 var downCell = downShadowNode.activeCell;
629 619
630 if ((downCell.tagName == 'TH') || 620 if ((downCell.tagName == 'TH') || (downCell.hasAttribute('scope'))) {
631 (downCell.hasAttribute('scope'))) {
632
633 if (downCtr < this.shadowTable_.length - 1) { 621 if (downCtr < this.shadowTable_.length - 1) {
634 var checkDataCell = 622 var checkDataCell =
635 this.shadowTable_[downCtr + 1][currentShadowNode.j]; 623 this.shadowTable_[downCtr + 1][currentShadowNode.j];
636 } 624 }
637 } 625 }
638 downShadowNode.colHeaderCells.push(currentCell); 626 downShadowNode.colHeaderCells.push(currentCell);
639 } 627 }
640 this.tableColHeaders.push(currentCell); 628 this.tableColHeaders.push(currentCell);
641 } else if (specifiedScope == 'rowgroup') { 629 } else if (specifiedScope == 'rowgroup') {
642 currentShadowNode.isRowHeader = true; 630 currentShadowNode.isRowHeader = true;
643 631
644 // This cell is a row header for the rest of the cells in this row group. 632 // This cell is a row header for the rest of the cells in this row group.
645 var currentRowGroup = currentShadowNode.rowGroup; 633 var currentRowGroup = currentShadowNode.rowGroup;
646 634
647 // Get the rest of the cells in this row first 635 // Get the rest of the cells in this row first
648 for (var cellsInRow = currentShadowNode.j + 1; 636 for (var cellsInRow = currentShadowNode.j + 1;
649 cellsInRow < this.shadowTable_[currentShadowNode.i].length; 637 cellsInRow < this.shadowTable_[currentShadowNode.i].length;
650 cellsInRow++) { 638 cellsInRow++) {
651 this.shadowTable_[currentShadowNode.i][cellsInRow]. 639 this.shadowTable_[currentShadowNode.i][cellsInRow].rowHeaderCells.push(
652 rowHeaderCells.push(currentCell); 640 currentCell);
653 } 641 }
654 642
655 // Now propagate to rest of row group 643 // Now propagate to rest of row group
656 for (var downCtr = currentShadowNode.i + 1; 644 for (var downCtr = currentShadowNode.i + 1;
657 downCtr < this.shadowTable_.length; 645 downCtr < this.shadowTable_.length; downCtr++) {
658 downCtr++) {
659
660 if (this.shadowTable_[downCtr][0].rowGroup != currentRowGroup) { 646 if (this.shadowTable_[downCtr][0].rowGroup != currentRowGroup) {
661 break; 647 break;
662 } 648 }
663 649
664 for (var rightCtr = 0; 650 for (var rightCtr = 0; rightCtr < this.shadowTable_[downCtr].length;
665 rightCtr < this.shadowTable_[downCtr].length;
666 rightCtr++) { 651 rightCtr++) {
667 652 this.shadowTable_[downCtr][rightCtr].rowHeaderCells.push(currentCell);
668 this.shadowTable_[downCtr][rightCtr].
669 rowHeaderCells.push(currentCell);
670 } 653 }
671 } 654 }
672 this.tableRowHeaders.push(currentCell); 655 this.tableRowHeaders.push(currentCell);
673 656
674 } else if (specifiedScope == 'colgroup') { 657 } else if (specifiedScope == 'colgroup') {
675 currentShadowNode.isColHeader = true; 658 currentShadowNode.isColHeader = true;
676 659
677 // This cell is a col header for the rest of the cells in this col group. 660 // This cell is a col header for the rest of the cells in this col group.
678 var currentColGroup = currentShadowNode.colGroup; 661 var currentColGroup = currentShadowNode.colGroup;
679 662
680 // Get the rest of the cells in this colgroup first 663 // Get the rest of the cells in this colgroup first
681 for (var cellsInCol = currentShadowNode.j + 1; 664 for (var cellsInCol = currentShadowNode.j + 1;
682 cellsInCol < this.shadowTable_[currentShadowNode.i].length; 665 cellsInCol < this.shadowTable_[currentShadowNode.i].length;
683 cellsInCol++) { 666 cellsInCol++) {
684 if (this.shadowTable_[currentShadowNode.i][cellsInCol].colGroup == 667 if (this.shadowTable_[currentShadowNode.i][cellsInCol].colGroup ==
685 currentColGroup) { 668 currentColGroup) {
686 this.shadowTable_[currentShadowNode.i][cellsInCol]. 669 this.shadowTable_[currentShadowNode.i][cellsInCol]
687 colHeaderCells.push(currentCell); 670 .colHeaderCells.push(currentCell);
688 } 671 }
689 } 672 }
690 673
691 // Now propagate to rest of col group 674 // Now propagate to rest of col group
692 for (var downCtr = currentShadowNode.i + 1; 675 for (var downCtr = currentShadowNode.i + 1;
693 downCtr < this.shadowTable_.length; 676 downCtr < this.shadowTable_.length; downCtr++) {
694 downCtr++) { 677 for (var rightCtr = 0; rightCtr < this.shadowTable_[downCtr].length;
695
696 for (var rightCtr = 0;
697 rightCtr < this.shadowTable_[downCtr].length;
698 rightCtr++) { 678 rightCtr++) {
699
700 if (this.shadowTable_[downCtr][rightCtr].colGroup == 679 if (this.shadowTable_[downCtr][rightCtr].colGroup ==
701 currentColGroup) { 680 currentColGroup) {
702 this.shadowTable_[downCtr][rightCtr]. 681 this.shadowTable_[downCtr][rightCtr].colHeaderCells.push(
703 colHeaderCells.push(currentCell); 682 currentCell);
704 } 683 }
705 } 684 }
706 } 685 }
707 this.tableColHeaders.push(currentCell); 686 this.tableColHeaders.push(currentCell);
708 } 687 }
709 if (currentCell.hasAttribute('headers')) { 688 if (currentCell.hasAttribute('headers')) {
710 this.findAttrbHeaders_(currentShadowNode); 689 this.findAttrbHeaders_(currentShadowNode);
711 } 690 }
712 if (currentCell.hasAttribute('aria-describedby')) { 691 if (currentCell.hasAttribute('aria-describedby')) {
713 this.findAttrbDescribedBy_(currentShadowNode); 692 this.findAttrbDescribedBy_(currentShadowNode);
(...skipping 18 matching lines...) Expand all
732 * that has a 'headers' attribute. 711 * that has a 'headers' attribute.
733 * 712 *
734 * @private 713 * @private
735 */ 714 */
736 cvox.TraverseTable.prototype.findAttrbHeaders_ = function(currentShadowNode) { 715 cvox.TraverseTable.prototype.findAttrbHeaders_ = function(currentShadowNode) {
737 var activeTableCell = currentShadowNode.activeCell; 716 var activeTableCell = currentShadowNode.activeCell;
738 717
739 var idList = activeTableCell.getAttribute('headers').split(' '); 718 var idList = activeTableCell.getAttribute('headers').split(' ');
740 for (var idToken = 0; idToken < idList.length; idToken++) { 719 for (var idToken = 0; idToken < idList.length; idToken++) {
741 // Find cell(s) with this ID, add to header list 720 // Find cell(s) with this ID, add to header list
742 var idCellArray = cvox.TableUtil.getCellWithID(this.activeTable_, 721 var idCellArray =
743 idList[idToken]); 722 cvox.TableUtil.getCellWithID(this.activeTable_, idList[idToken]);
744 723
745 for (var idCtr = 0; idCtr < idCellArray.length; idCtr++) { 724 for (var idCtr = 0; idCtr < idCellArray.length; idCtr++) {
746 if (idCellArray[idCtr].id == activeTableCell.id) { 725 if (idCellArray[idCtr].id == activeTableCell.id) {
747 // Skip if the ID is the same as the current cell's ID 726 // Skip if the ID is the same as the current cell's ID
748 break; 727 break;
749 } 728 }
750 // Check if this list of candidate headers contains a 729 // Check if this list of candidate headers contains a
751 // shadowNode with an active cell with this ID already 730 // shadowNode with an active cell with this ID already
752 var possibleHeaderNode = 731 var possibleHeaderNode = this.idToShadowNode_[idCellArray[idCtr].id];
753 this.idToShadowNode_[idCellArray[idCtr].id]; 732 if (!cvox.TableUtil.checkIfHeader(possibleHeaderNode.activeCell)) {
754 if (! cvox.TableUtil.checkIfHeader(possibleHeaderNode.activeCell)) {
755 // This listed header cell will not be handled later. 733 // This listed header cell will not be handled later.
756 // Determine whether this is a row or col header for 734 // Determine whether this is a row or col header for
757 // the active table cell 735 // the active table cell
758 736
759 var iDiff = Math.abs(possibleHeaderNode.i - currentShadowNode.i); 737 var iDiff = Math.abs(possibleHeaderNode.i - currentShadowNode.i);
760 var jDiff = Math.abs(possibleHeaderNode.j - currentShadowNode.j); 738 var jDiff = Math.abs(possibleHeaderNode.j - currentShadowNode.j);
761 if ((iDiff == 0) || (iDiff < jDiff)) { 739 if ((iDiff == 0) || (iDiff < jDiff)) {
762 cvox.TableUtil.pushIfNotContained(currentShadowNode.rowHeaderCells, 740 cvox.TableUtil.pushIfNotContained(
763 possibleHeaderNode.activeCell); 741 currentShadowNode.rowHeaderCells, possibleHeaderNode.activeCell);
764 cvox.TableUtil.pushIfNotContained(this.tableRowHeaders, 742 cvox.TableUtil.pushIfNotContained(
765 possibleHeaderNode.activeCell); 743 this.tableRowHeaders, possibleHeaderNode.activeCell);
766 } else { 744 } else {
767 // This is a column header 745 // This is a column header
768 cvox.TableUtil.pushIfNotContained(currentShadowNode.colHeaderCells, 746 cvox.TableUtil.pushIfNotContained(
769 possibleHeaderNode.activeCell); 747 currentShadowNode.colHeaderCells, possibleHeaderNode.activeCell);
770 cvox.TableUtil.pushIfNotContained(this.tableColHeaders, 748 cvox.TableUtil.pushIfNotContained(
771 possibleHeaderNode.activeCell); 749 this.tableColHeaders, possibleHeaderNode.activeCell);
772 } 750 }
773 } 751 }
774 } 752 }
775 } 753 }
776 }; 754 };
777 755
778 756
779 /** 757 /**
780 * Finds header cells from the 'aria-describedby' attribute of a given shadow 758 * Finds header cells from the 'aria-describedby' attribute of a given shadow
781 * node's active cell and classifies them in two ways: 759 * node's active cell and classifies them in two ways:
782 * -- Identifies them for the entire table by adding them to 760 * -- Identifies them for the entire table by adding them to
783 * this.tableRowHeaders and this.tableColHeaders. 761 * this.tableRowHeaders and this.tableColHeaders.
784 * -- Identifies them for the shadow table node by adding them to the node's 762 * -- Identifies them for the shadow table node by adding them to the node's
785 * rowHeaderCells or colHeaderCells arrays. 763 * rowHeaderCells or colHeaderCells arrays.
786 * 764 *
787 * Please note that header cells found through the 'aria-describedby' attribute 765 * Please note that header cells found through the 'aria-describedby' attribute
788 * must have the role='rowheader' or role='columnheader' attributes in order to 766 * must have the role='rowheader' or role='columnheader' attributes in order to
789 * be considered header cells. 767 * be considered header cells.
790 * 768 *
791 * @param {ShadowTableNode} currentShadowNode A shadow node with an active cell 769 * @param {ShadowTableNode} currentShadowNode A shadow node with an active cell
792 * that has an 'aria-describedby' attribute. 770 * that has an 'aria-describedby' attribute.
793 * 771 *
794 * @private 772 * @private
795 */ 773 */
796 cvox.TraverseTable.prototype.findAttrbDescribedBy_ = 774 cvox.TraverseTable.prototype.findAttrbDescribedBy_ = function(
797 function(currentShadowNode) { 775 currentShadowNode) {
798 var activeTableCell = currentShadowNode.activeCell; 776 var activeTableCell = currentShadowNode.activeCell;
799 777
800 var idList = activeTableCell.getAttribute('aria-describedby').split(' '); 778 var idList = activeTableCell.getAttribute('aria-describedby').split(' ');
801 for (var idToken = 0; idToken < idList.length; idToken++) { 779 for (var idToken = 0; idToken < idList.length; idToken++) {
802 // Find cell(s) with this ID, add to header list 780 // Find cell(s) with this ID, add to header list
803 var idCellArray = cvox.TableUtil.getCellWithID(this.activeTable_, 781 var idCellArray =
804 idList[idToken]); 782 cvox.TableUtil.getCellWithID(this.activeTable_, idList[idToken]);
805 783
806 for (var idCtr = 0; idCtr < idCellArray.length; idCtr++) { 784 for (var idCtr = 0; idCtr < idCellArray.length; idCtr++) {
807 if (idCellArray[idCtr].id == activeTableCell.id) { 785 if (idCellArray[idCtr].id == activeTableCell.id) {
808 // Skip if the ID is the same as the current cell's ID 786 // Skip if the ID is the same as the current cell's ID
809 break; 787 break;
810 } 788 }
811 // Check if this list of candidate headers contains a 789 // Check if this list of candidate headers contains a
812 // shadowNode with an active cell with this ID already 790 // shadowNode with an active cell with this ID already
813 var possibleHeaderNode = 791 var possibleHeaderNode = this.idToShadowNode_[idCellArray[idCtr].id];
814 this.idToShadowNode_[idCellArray[idCtr].id]; 792 if (!cvox.TableUtil.checkIfHeader(possibleHeaderNode.activeCell)) {
815 if (! cvox.TableUtil.checkIfHeader(possibleHeaderNode.activeCell)) {
816 // This listed header cell will not be handled later. 793 // This listed header cell will not be handled later.
817 // Determine whether this is a row or col header for 794 // Determine whether this is a row or col header for
818 // the active table cell 795 // the active table cell
819 796
820 if (possibleHeaderNode.activeCell.hasAttribute('role') && 797 if (possibleHeaderNode.activeCell.hasAttribute('role') &&
821 (possibleHeaderNode.activeCell.getAttribute('role') == 798 (possibleHeaderNode.activeCell.getAttribute('role') ==
822 'rowheader')) { 799 'rowheader')) {
823 cvox.TableUtil.pushIfNotContained(currentShadowNode.rowHeaderCells, 800 cvox.TableUtil.pushIfNotContained(
824 possibleHeaderNode.activeCell); 801 currentShadowNode.rowHeaderCells, possibleHeaderNode.activeCell);
825 cvox.TableUtil.pushIfNotContained(this.tableRowHeaders, 802 cvox.TableUtil.pushIfNotContained(
826 possibleHeaderNode.activeCell); 803 this.tableRowHeaders, possibleHeaderNode.activeCell);
827 } else if (possibleHeaderNode.activeCell.hasAttribute('role') && 804 } else if (
805 possibleHeaderNode.activeCell.hasAttribute('role') &&
828 (possibleHeaderNode.activeCell.getAttribute('role') == 806 (possibleHeaderNode.activeCell.getAttribute('role') ==
829 'columnheader')) { 807 'columnheader')) {
830 cvox.TableUtil.pushIfNotContained(currentShadowNode.colHeaderCells, 808 cvox.TableUtil.pushIfNotContained(
831 possibleHeaderNode.activeCell); 809 currentShadowNode.colHeaderCells, possibleHeaderNode.activeCell);
832 cvox.TableUtil.pushIfNotContained(this.tableColHeaders, 810 cvox.TableUtil.pushIfNotContained(
833 possibleHeaderNode.activeCell); 811 this.tableColHeaders, possibleHeaderNode.activeCell);
834 } 812 }
835 } 813 }
836 } 814 }
837 } 815 }
838 }; 816 };
839 817
840 818
841 /** 819 /**
842 * Gets the current cell or null if there is no current cell. 820 * Gets the current cell or null if there is no current cell.
843 * @return {?Node} The cell <TD> or <TH> or role='gridcell' node. 821 * @return {?Node} The cell <TD> or <TH> or role='gridcell' node.
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
936 914
937 /** 915 /**
938 * Gets the active column, represented as an array of <TH> or <TD> nodes that 916 * Gets the active column, represented as an array of <TH> or <TD> nodes that
939 * make up a column. In this context, "active" means that this is the column 917 * make up a column. In this context, "active" means that this is the column
940 * that contains the cell the user is currently looking at. 918 * that contains the cell the user is currently looking at.
941 * @return {Array} An array of <TH> or <TD> or role='gridcell' nodes. 919 * @return {Array} An array of <TH> or <TD> or role='gridcell' nodes.
942 */ 920 */
943 cvox.TraverseTable.prototype.getCol = function() { 921 cvox.TraverseTable.prototype.getCol = function() {
944 var colArray = []; 922 var colArray = [];
945 for (var i = 0; i < this.shadowTable_.length; i++) { 923 for (var i = 0; i < this.shadowTable_.length; i++) {
946
947 if (this.shadowTable_[i][this.currentCellCursor[1]]) { 924 if (this.shadowTable_[i][this.currentCellCursor[1]]) {
948 var shadowEntry = this.shadowTable_[i][this.currentCellCursor[1]]; 925 var shadowEntry = this.shadowTable_[i][this.currentCellCursor[1]];
949 926
950 if (shadowEntry.colSpan && shadowEntry.rowSpan) { 927 if (shadowEntry.colSpan && shadowEntry.rowSpan) {
951 // Look at the last element in the column cell aray. 928 // Look at the last element in the column cell aray.
952 var prev = colArray[colArray.length - 1]; 929 var prev = colArray[colArray.length - 1];
953 if (prev != 930 if (prev != shadowEntry.activeCell) {
954 shadowEntry.activeCell) {
955 // Watch out for positions spanned by a cell with rowspan and 931 // Watch out for positions spanned by a cell with rowspan and
956 // colspan. We don't want the same cell showing up multiple times 932 // colspan. We don't want the same cell showing up multiple times
957 // in per-column cell lists. 933 // in per-column cell lists.
958 colArray.push( 934 colArray.push(shadowEntry.activeCell);
959 shadowEntry.activeCell);
960 } 935 }
961 } else if ((shadowEntry.colSpan) || (!shadowEntry.rowSpan)) { 936 } else if ((shadowEntry.colSpan) || (!shadowEntry.rowSpan)) {
962 colArray.push( 937 colArray.push(shadowEntry.activeCell);
963 shadowEntry.activeCell);
964 } 938 }
965 } 939 }
966 } 940 }
967 return colArray; 941 return colArray;
968 }; 942 };
969 943
970 944
971 /** 945 /**
972 * Gets the active row <TR> node. In this context, "active" means that this is 946 * Gets the active row <TR> node. In this context, "active" means that this is
973 * the row that contains the cell the user is currently looking at. 947 * the row that contains the cell the user is currently looking at.
(...skipping 24 matching lines...) Expand all
998 972
999 /** 973 /**
1000 * Gets the table caption text. 974 * Gets the table caption text.
1001 * 975 *
1002 * @return {?string} Either: 976 * @return {?string} Either:
1003 * 1) The table caption text 977 * 1) The table caption text
1004 * 2) Null if the table does not include a caption tag. 978 * 2) Null if the table does not include a caption tag.
1005 */ 979 */
1006 cvox.TraverseTable.prototype.captionText = function() { 980 cvox.TraverseTable.prototype.captionText = function() {
1007 // If there's more than one outer <caption> element, choose the first one. 981 // If there's more than one outer <caption> element, choose the first one.
1008 var captionNodes = cvox.XpathUtil.evalXPath('caption\[1]', 982 var captionNodes = cvox.XpathUtil.evalXPath('caption\[1]', this.activeTable_);
1009 this.activeTable_);
1010 if (captionNodes.length > 0) { 983 if (captionNodes.length > 0) {
1011 return captionNodes[0].innerHTML; 984 return captionNodes[0].innerHTML;
1012 } else { 985 } else {
1013 return null; 986 return null;
1014 } 987 }
1015 }; 988 };
1016 989
1017 990
1018 /** 991 /**
1019 * Calculates the number of columns in the shadow table. 992 * Calculates the number of columns in the shadow table.
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1051 * This uses the W3C recommended algorithm for calculating number of 1024 * This uses the W3C recommended algorithm for calculating number of
1052 * columns, but it does not take rowspans or colspans into account. This means 1025 * columns, but it does not take rowspans or colspans into account. This means
1053 * that the number of columns calculated here might be lower than the actual 1026 * that the number of columns calculated here might be lower than the actual
1054 * number of columns in the table if columns are indicated by colspans. 1027 * number of columns in the table if columns are indicated by colspans.
1055 * @return {number} The number of columns in the table. 1028 * @return {number} The number of columns in the table.
1056 * @private 1029 * @private
1057 */ 1030 */
1058 cvox.TraverseTable.prototype.getW3CColCount_ = function() { 1031 cvox.TraverseTable.prototype.getW3CColCount_ = function() {
1059 // See http://www.w3.org/TR/html401/struct/tables.html#h-11.2.4.3 1032 // See http://www.w3.org/TR/html401/struct/tables.html#h-11.2.4.3
1060 1033
1061 var colgroupNodes = cvox.XpathUtil.evalXPath('child::colgroup', 1034 var colgroupNodes =
1062 this.activeTable_); 1035 cvox.XpathUtil.evalXPath('child::colgroup', this.activeTable_);
1063 var colNodes = cvox.XpathUtil.evalXPath('child::col', this.activeTable_); 1036 var colNodes = cvox.XpathUtil.evalXPath('child::col', this.activeTable_);
1064 1037
1065 if ((colgroupNodes.length == 0) && (colNodes.length == 0)) { 1038 if ((colgroupNodes.length == 0) && (colNodes.length == 0)) {
1066 var maxcols = 0; 1039 var maxcols = 0;
1067 var outerChildren = cvox.TableUtil.getChildRows(this.activeTable_); 1040 var outerChildren = cvox.TableUtil.getChildRows(this.activeTable_);
1068 for (var i = 0; i < outerChildren.length; i++) { 1041 for (var i = 0; i < outerChildren.length; i++) {
1069 var childrenCount = cvox.TableUtil.getChildCells(outerChildren[i]); 1042 var childrenCount = cvox.TableUtil.getChildCells(outerChildren[i]);
1070 if (childrenCount.length > maxcols) { 1043 if (childrenCount.length > maxcols) {
1071 maxcols = childrenCount.length; 1044 maxcols = childrenCount.length;
1072 } 1045 }
1073 } 1046 }
1074 return maxcols; 1047 return maxcols;
1075 } else { 1048 } else {
1076 var sum = 0; 1049 var sum = 0;
1077 for (var i = 0; i < colNodes.length; i++) { 1050 for (var i = 0; i < colNodes.length; i++) {
1078 if (colNodes[i].hasAttribute('span')) { 1051 if (colNodes[i].hasAttribute('span')) {
1079 sum += colNodes[i].getAttribute('span'); 1052 sum += colNodes[i].getAttribute('span');
1080 } else { 1053 } else {
1081 sum += 1; 1054 sum += 1;
1082 } 1055 }
1083 } 1056 }
1084 for (i = 0; i < colgroupNodes.length; i++) { 1057 for (i = 0; i < colgroupNodes.length; i++) {
1085 var colChildren = cvox.XpathUtil.evalXPath('child::col', 1058 var colChildren =
1086 colgroupNodes[i]); 1059 cvox.XpathUtil.evalXPath('child::col', colgroupNodes[i]);
1087 if (colChildren.length == 0) { 1060 if (colChildren.length == 0) {
1088 if (colgroupNodes[i].hasAttribute('span')) { 1061 if (colgroupNodes[i].hasAttribute('span')) {
1089 sum += colgroupNodes[i].getAttribute('span'); 1062 sum += colgroupNodes[i].getAttribute('span');
1090 } else { 1063 } else {
1091 sum += 1; 1064 sum += 1;
1092 } 1065 }
1093 } 1066 }
1094 } 1067 }
1095 } 1068 }
1096 return sum; 1069 return sum;
1097 }; 1070 };
1098 1071
1099 1072
1100 /** 1073 /**
1101 * Moves to the next row in the table. Updates the cell cursor. 1074 * Moves to the next row in the table. Updates the cell cursor.
1102 * 1075 *
1103 * @return {boolean} Either: 1076 * @return {boolean} Either:
1104 * 1) True if the update has been made. 1077 * 1) True if the update has been made.
1105 * 2) False if the end of the table has been reached and the update has not 1078 * 2) False if the end of the table has been reached and the update has not
1106 * happened. 1079 * happened.
1107 */ 1080 */
1108 cvox.TraverseTable.prototype.nextRow = function() { 1081 cvox.TraverseTable.prototype.nextRow = function() {
1109 if (!this.currentCellCursor) { 1082 if (!this.currentCellCursor) {
1110 // We have not started moving through the table yet 1083 // We have not started moving through the table yet
1111 return this.goToRow(0); 1084 return this.goToRow(0);
1112 } else { 1085 } else {
1113 return this.goToRow(this.currentCellCursor[0] + 1); 1086 return this.goToRow(this.currentCellCursor[0] + 1);
1114 } 1087 }
1115 1088
1116 }; 1089 };
1117 1090
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
1246 * 1) True if the index is valid and the update has been made. 1219 * 1) True if the index is valid and the update has been made.
1247 * 2) False if the index is not valid (there is no cell at that location). 1220 * 2) False if the index is not valid (there is no cell at that location).
1248 */ 1221 */
1249 cvox.TraverseTable.prototype.goToLastCell = function() { 1222 cvox.TraverseTable.prototype.goToLastCell = function() {
1250 var numRows = this.shadowTable_.length; 1223 var numRows = this.shadowTable_.length;
1251 if (numRows == 0) { 1224 if (numRows == 0) {
1252 return false; 1225 return false;
1253 } 1226 }
1254 var lastRow = this.shadowTable_[numRows - 1]; 1227 var lastRow = this.shadowTable_[numRows - 1];
1255 var lastIndex = [(numRows - 1), (lastRow.length - 1)]; 1228 var lastIndex = [(numRows - 1), (lastRow.length - 1)];
1256 var cell = 1229 var cell = this.shadowTable_[lastIndex[0]][lastIndex[1]];
1257 this.shadowTable_[lastIndex[0]][lastIndex[1]];
1258 if (cell != null) { 1230 if (cell != null) {
1259 this.currentCellCursor = lastIndex; 1231 this.currentCellCursor = lastIndex;
1260 return true; 1232 return true;
1261 } 1233 }
1262 return false; 1234 return false;
1263 }; 1235 };
1264 1236
1265 1237
1266 /** 1238 /**
1267 * Moves to the cell at the last index in the current row of the table. Update 1239 * Moves to the cell at the last index in the current row of the table. Update
1268 * the cell cursor. 1240 * the cell cursor.
1269 * @return {boolean} Either: 1241 * @return {boolean} Either:
1270 * 1) True if the index is valid and the update has been made. 1242 * 1) True if the index is valid and the update has been made.
1271 * 2) False if the index is not valid (there is no cell at that location). 1243 * 2) False if the index is not valid (there is no cell at that location).
1272 */ 1244 */
1273 cvox.TraverseTable.prototype.goToRowLastCell = function() { 1245 cvox.TraverseTable.prototype.goToRowLastCell = function() {
1274 var currentRow = this.currentCellCursor[0]; 1246 var currentRow = this.currentCellCursor[0];
1275 var lastIndex = [currentRow, (this.shadowTable_[currentRow].length - 1)]; 1247 var lastIndex = [currentRow, (this.shadowTable_[currentRow].length - 1)];
1276 var cell = 1248 var cell = this.shadowTable_[lastIndex[0]][lastIndex[1]];
1277 this.shadowTable_[lastIndex[0]][lastIndex[1]];
1278 if (cell != null) { 1249 if (cell != null) {
1279 this.currentCellCursor = lastIndex; 1250 this.currentCellCursor = lastIndex;
1280 return true; 1251 return true;
1281 } 1252 }
1282 return false; 1253 return false;
1283 }; 1254 };
1284 1255
1285 1256
1286 /** 1257 /**
1287 * Moves to the cell at the last index in the current column of the table. 1258 * Moves to the cell at the last index in the current column of the table.
1288 * Update the cell cursor. 1259 * Update the cell cursor.
1289 * @return {boolean} Either: 1260 * @return {boolean} Either:
1290 * 1) True if the index is valid and the update has been made. 1261 * 1) True if the index is valid and the update has been made.
1291 * 2) False if the index is not valid (there is no cell at that location). 1262 * 2) False if the index is not valid (there is no cell at that location).
1292 */ 1263 */
1293 cvox.TraverseTable.prototype.goToColLastCell = function() { 1264 cvox.TraverseTable.prototype.goToColLastCell = function() {
1294 var currentCol = this.getCol(); 1265 var currentCol = this.getCol();
1295 var lastIndex = [(currentCol.length - 1), this.currentCellCursor[1]]; 1266 var lastIndex = [(currentCol.length - 1), this.currentCellCursor[1]];
1296 var cell = 1267 var cell = this.shadowTable_[lastIndex[0]][lastIndex[1]];
1297 this.shadowTable_[lastIndex[0]][lastIndex[1]];
1298 if (cell != null) { 1268 if (cell != null) {
1299 this.currentCellCursor = lastIndex; 1269 this.currentCellCursor = lastIndex;
1300 return true; 1270 return true;
1301 } 1271 }
1302 return false; 1272 return false;
1303 }; 1273 };
1304 1274
1305 1275
1306 /** 1276 /**
1307 * Resets the table cursors. 1277 * Resets the table cursors.
1308 * 1278 *
1309 */ 1279 */
1310 cvox.TraverseTable.prototype.resetCursor = function() { 1280 cvox.TraverseTable.prototype.resetCursor = function() {
1311 this.currentCellCursor = null; 1281 this.currentCellCursor = null;
1312 }; 1282 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698