Home | History | Annotate | Download | only in common
      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
      3 // found in the LICENSE file.
      4 
      5 /**
      6  * @fileoverview DOM utility functions to aid in table navigation.
      7  */
      8 
      9 goog.provide('cvox.TableUtil');
     10 
     11 goog.require('cvox.XpathUtil');
     12 
     13 
     14 /**
     15  * Utility function to check if a particular table cell is a candidate
     16  * header cell.
     17  * @param {Node} cell The table cell.
     18  * @return {boolean} Whether or not the table cell is acting as a header cell.
     19  */
     20 cvox.TableUtil.checkIfHeader = function(cell) {
     21   /*
     22    * Headers are defined here as <TH> or <TD> elements. <TD> elements when
     23    * serving as header cells must have either:
     24    *  - The scope attribute defined
     25    *  - Their IDs referenced in the header content attribute of another <TD> or
     26    *  <TH> element.
     27    * This function does not check whether this cell is referenced by another
     28    * <TD>. So this function by itself will not be able to gather all possible
     29    * header cells when applied across all table cells.
     30    *
     31    * Please Note:
     32    * The HTML5 spec specifies that only header <TH> elements can be headers
     33    * ( http://dev.w3.org/html5/spec/tabular-data.html#row-header ) but the
     34    * HTML4 spec says that <TD> elements can act as headers if they have a
     35    * scope attribute defined
     36    * ( http://www.w3.org/TR/html401/struct/tables.html#h-11.2.6 ). In the
     37    * interest of providing meaningful header information for all tables, here
     38    * we take the position that <TD> elements can act as headers.
     39    */
     40   return ((cell.tagName == 'TH') ||
     41       cell.hasAttribute('scope') || (cell.hasAttribute('role') &&
     42           ((cell.getAttribute('role') == 'rowheader') ||
     43               (cell.getAttribute('role') == 'columnheader'))));
     44 };
     45 
     46 
     47 /**
     48  * Utility function to determine colgroup structure. Builds an array that
     49  * associates a column number to a particular col group.
     50  * @param {Array} colGroups An array of all the colgroup elements in a
     51  * particular table.
     52  * @return {Array} An array that maps indexes representing table columns
     53  * to indexes into the colGroups array.
     54  */
     55 cvox.TableUtil.determineColGroups = function(colGroups) {
     56   var colToColGroup = [];
     57 
     58   if (colGroups.length == 0) {
     59     return colToColGroup;
     60   }
     61   // A colgroup has either a series of col element children or a span
     62   // attribute. If it has col children, ignore the span attribute
     63   for (var colGroupCtr = 0; colGroupCtr < colGroups.length;
     64        colGroupCtr++) {
     65 
     66     var currentColGroup = colGroups[colGroupCtr];
     67 
     68     var childCols = cvox.TableUtil.getColNodes(currentColGroup);
     69     if (childCols.length > 0) {
     70       for (var colNodeCtr = 0; colNodeCtr < childCols.length;
     71           colNodeCtr++) {
     72         var colElement = childCols[colNodeCtr];
     73 
     74         if (colElement.hasAttribute('span')) {
     75           var span = parseInt(colElement.getAttribute('span'), 10);
     76 
     77           for (var s = 0; s < span; s++) {
     78             colToColGroup.push(colGroupCtr);
     79           }
     80         } else {
     81           colToColGroup.push(colGroupCtr);
     82         }
     83       }
     84     } else {
     85       // No children of the current colgroup. Does it have a span attribute?
     86       if (currentColGroup.hasAttribute('span')) {
     87         var span = parseInt(currentColGroup.getAttribute('span'), 10);
     88 
     89         for (var s = 0; s < span; s++) {
     90           colToColGroup.push(colGroupCtr);
     91         }
     92       } else {
     93         // Default span value is 1
     94         colToColGroup.push(colGroupCtr);
     95       }
     96     }
     97   }
     98   return colToColGroup;
     99 
    100 };
    101 
    102 
    103 /**
    104  * Utility function to push an element into a given array only if that element
    105  * is not already contained in the array.
    106  * @param {Array} givenArray The given array.
    107  * @param {Node} givenElement The given element.
    108  */
    109 cvox.TableUtil.pushIfNotContained = function(givenArray, givenElement) {
    110   if (givenArray.indexOf(givenElement) == -1) {
    111     givenArray.push(givenElement);
    112   }
    113 };
    114 
    115 
    116 /**
    117  * Returns a JavaScript array of all the non-nested rows in the given table.
    118  *
    119  * @param {Node} table A table node.
    120  * @return {Array} An array of all the child rows of the active table.
    121  */
    122 cvox.TableUtil.getChildRows = function(table) {
    123   return cvox.XpathUtil.evalXPath('child::tbody/tr | child::thead/tr | ' +
    124       'child::*[attribute::role="row"]', table);
    125 };
    126 
    127 
    128 /**
    129  * Returns a JavaScript array of all the child cell <TD> or <TH> or
    130  * role='gridcell' nodes of the given row.
    131  *
    132  * @param {Node} rowNode The specified row node.
    133  * @return {Array} An array of all the child cells of the given row node.
    134  */
    135 cvox.TableUtil.getChildCells = function(rowNode) {
    136   return cvox.XpathUtil.evalXPath('child::td | child::th | ' +
    137       'child::*[attribute::role="gridcell"] |' +
    138       'child::*[attribute::role="rowheader"] |' +
    139       'child::*[attribute::role="columnheader"]', rowNode);
    140 };
    141 
    142 
    143 /**
    144  * Returns a JavaScript array containing the cell in the active table
    145  * with the given ID.
    146  *
    147  * @param {Node} table A table node.
    148  * @param {string} cellID The specified ID.
    149  * @return {Array} An array containing the cell with the specified ID.
    150  */
    151 cvox.TableUtil.getCellWithID = function(table, cellID) {
    152   return cvox.XpathUtil.evalXPath('id(\'' + cellID + '\')', table);
    153 };
    154 
    155 
    156 /**
    157  * Returns a Javascript array containing the colgroup elements in the
    158  * active table.
    159  *
    160  * @param {Node} table A table node.
    161  * @return {Array} An array of all the colgroup elements in the active table.
    162  */
    163 cvox.TableUtil.getColGroups = function(table) {
    164   return cvox.XpathUtil.evalXPath('child::colgroup', table);
    165 };
    166 
    167 
    168 /**
    169  * Returns a Javascript array containing the child col elements of the given
    170  * colgroup element.
    171  *
    172  * @param {Node} colGroupNode The specified <COLGROUP> element.
    173  * @return {Array} An array of all of the child col elements of the given
    174  * colgroup element.
    175  */
    176 cvox.TableUtil.getColNodes = function(colGroupNode) {
    177   return cvox.XpathUtil.evalXPath('child::col', colGroupNode);
    178 };
    179 
    180