Team LiB
Previous Section Next Section

DOM Table Manipulation

The <<table>> tag as defined in HTML 4 has a variety of attributes that have similarly named DOM properties, as we have seen with all HTML elements. In the case of <<table>>, these properties include align, bgColor, border, cellPadding, cellSpacing, and width. Within a <<table>> tag we would expect to find potentially a <<caption>> tag, and one or more table rows defined by the <<tr>> filled with table headers (<<th>>) or data cells (<<td>>). Under HTML 4, tables are extended to support the following structure:

Also, HTML 4 defines the frame attribute for the table, which sets the type of framing the table should have; the rules attribute, which sets where the rules should be placed between rows and columns; and the summary attrribute, which defines what the table is about for non-visual browsers. The simple example here allows you to play with the common properties for (X)HTML tables. A sample rendering of this example is shown in Figure 13-4.

Click To expand
Figure 13-4: Inspecting and changing the <table> tag using the DOM
<<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">>
<<html xmlns="http://www.w3.org/1999/xhtml">>
<<head>>
<<title>>(X)HTML Table Inspector<</title>>
<<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1" />>
<</head>>
<<body>>
<<table border="1" frame="box" id="testTable">>
<<caption>>Test Table<</caption>>
<<thead>>
     <<tr>>
        <<th>>Product<</th>>
        <<th>>SKU<</th>>
        <<th>>Price<</th>>
    <</tr>>
<</thead>>
<<!-- tfoot does indeed come before tbody  -->>
<<tfoot>>
 <<tr>>
      <<th colspan="3">>This has been an HTML 4 table example, thanks for
 reading<</th>>
 <</tr>>
<</tfoot>>
<<tbody>>
  <<tr>>
      <<th colspan="3" align="center">>Robots<</th>>
  <</tr>>
  <<tr>>
      <<td>>Trainer Robot<</td>>
      <<td>>TR-456<</td>>
      <<td>>$56,000<</td>>
  <</tr>>
  <<tr>>
      <<td>>Guard Dog Robot<</td>>
      <<td>>SEC-559<</td>>
      <<td>>$5,000<</td>>
  <</tr>>
  <<tr>>
      <<td>>Friend Robot<</td>>
      <<td>>AG-343<</td>>
      <<td>>$124,000<</td>>
  <</tr>>
<</tbody>>
<<tbody>>
  <<tr>>
      <<th colspan="3" align="center">>Jet Packs<</th>>
  <</tr>>
 
  <<tr>>
      <<td>>Economy<</td>>
      <<td>>JP-3455E6<</td>>
      <<td>>$6,000<</td>>
  <</tr>>
 
  <<tr>>
      <<td>>Deluxe<</td>>
      <<td>>JP-9999d<</td>>
      <<td>>$15,000<</td>>
  <</tr>>
<</tbody>>
<</table>>
<<br clear="all" />><<hr />><<br clear="all" />>
<<script type="text/javascript">>
   var theTable = document.getElementById('testTable');
<</script>>
<<form action="#" method="get">>
<<strong>>Alignment:<</strong>> 
      <<select onchange="theTable.align = this.options[this.selectedIndex].text;">>
            <<option>>left<</option>>
            <<option>>center<</option>>
            <<option>>right<</option>>
      <</select>>
<<strong>>Background Color:<</strong>> 
      <<select onchange="theTable.bgColor =
 this.options[this.selectedIndex].text;">>
            <<option>>white<</option>>
            <<option>>red<</option>>
            <<option>>blue<</option>>
            <<option>>yellow<</option>>
            <<option>>orange<</option>>
            <<option>>green<</option>>
            <<option>>black<</option>>
     <</select>>

<<strong>>Frames:<</strong>> 
     <<select onchange="theTable.frame = this.options[this.selectedIndex].text;">>
            <<option>>above<</option>>
            <<option>>below<</option>>
            <<option>>border<</option>>
            <<option>>box<</option>>
            <<option>>hsides<</option>>
            <<option>>vsides<</option>>
            <<option>>lhs<</option>>
            <<option>>rhs<</option>>
            <<option>>void<</option>>
     <</select>>
<<strong>>Rules:<</strong>> 
     <<select onchange="theTable.rules = this.options[this.selectedIndex].text;">>
            <<option>>all<</option>>
            <<option>>cols<</option>>
            <<option>>groups<</option>>
            <<option>>none<</option>>
            <<option>>rows<</option>>
     <</select>>
<<br />><<br />>
<<strong>>Border:<</strong>>
<<input type="text" size="2" maxlength="2" value="1" onchange="theTable.border =
 this.value;" />>
<<strong>>Cell Padding:<</strong>>
<<input type="text" size="2" maxlength="2" value="1" onchange="theTable.cellPadding
 = this.value;" />>
<<strong>>Cell Spacing:<</strong>>
<<input type="text" size="2" maxlength="2" value="1" onchange="theTable.cellSpacing
 = this.value;" />>
<</form>>
<</body>>
<</html>>
Note 

Be aware that even the latest browsers may have spotty support for the values of the rules and frame attributes.

The HTMLTableElement object also contains shorthand references to its typically enclosed elements. For example, tableElement.caption would reference the <<caption>> tag enclosed by the table referenced via tableElement, while tableElement.tHead and tableElement.tFoot would reference the <<thead>> and <<tfoot>> tags, respectively. The collection rows[] provides access to the <<tr>> tags within the table starting with the index of 0 like other collections, while the tBodies[] collection provides access to the <<tbody>> tags. Within these objects we can also look at their individual rows[] collections that contain the objects pointing to the individual <<tr>> tags within the corresponding table sub-element.

Using our previous example, we might write a small script to show the values for our previous table.

<<script type="text/javascript">>
<<!--
   var theTable = document.getElementById('testTable');
   document.writeln("<<pre>>");
   document.writeln("Overall table rows="+theTable.rows.length);
   document.writeln("Number of tbody tags="+theTable.tBodies.length);
   for (i = 0; i << theTable.tBodies.length; i++)
   document.writeln("\t tbody["+i+"] number of rows =
 "+theTable.tBodies[i].rows.length);
 
   document.writeln("Rows in tfoot tag="+theTable.tFoot.rows.length);
   document.writeln("Rows in thead tag="+theTable.tHead.rows.length);
   document.writeln("<</pre>>");
//-->>
<</script>>

The output of this script for our sample HTML 4–style table is shown here:

Click To expand

A variety of methods are also provided to make up the core pieces of a table including createTHead(), createTFoot(), createCaption(), and insertRow(index) where index is the numeric value indicating where to insert the row starting from 0. Corresponding to the creation methods, the HTMLTableElement object also supports deleteCaption(), deleteTHead(), deleteTFoot(), and deleteRowIndex(index). Again, given the previous HTML 4 sample table, we could write some scripts to show how to delete and add items to the table. What you will notice is that while it is easy to delete items from the table, adding is another question. You actually need to add some items to a row before much of anything will take place.

<<script type="text/javascript">>
<<!--
   var theTable = document.getElementById('testTable');
//-->>
<</script>>
<<form name="testForm" id="testForm">>
<<input type="text" name="rowtodelete" id="rowtodelete" size="2" maxlength="2"
 value="1" />>
<<input type="button" value="Delete Row" onclick="if (theTable.rows.length >> 0)
 theTable.deleteRow(document.testForm.rowtodelete.value);" />>
<<br />>
<<input type="button" value="Delete <<thead>>" onclick="theTable.deleteTHead();" />>
<<input type="button" value="Delete <<tfoot>>" onclick="theTable.deleteTFoot();" />>
<<input type="button" value="Delete <<caption>>" onclick="theTable.deleteCaption();"
 />>    

<<input type="text" name="rowtoinsert" id="rowtoinsert" size="2" maxlength="2"
 value="1" />>
<<input type="button" value="Insert Row"
 onclick="theTable.insertRow(document.testForm.rowtoinsert.value);" />>    

<</form>>

A table row defined by <<tr>> in HTML and the HTMLTableRowElement object under the DOM has its normal HTML attribute–related properties such as the core attributes (id, class, style, title, lang, dir) and its specific properties like align, bgColor, ch, chOff (rewrite of charOff attribute), and vAlign. However, there are a few special properties that deserve consideration. For example, rowIndex indicates the index of the row in the overall table. The property sectionRowIndex indicates the index of the row within a <<tbody>>, <<thead>>, or the <<tfoot>> element it belongs to. Last, the cells[] collection for an HTMLTableRowElement is a collection of the cells in the row defined by either <<td>> or <<th>> elements. Within a table row you can also utilize a few useful methods including insertCell(index), which creates an HTMLElement object for a <<td>> tag at a specified column index in the row, and deleteCell(index), which would obviously remove a cell at a specified index.

The actual table cell defined in HTML by the <<td>> tag has few special properties beyond its normal attribute-related ones like abbr, align, axis, bgColor, ch, chOff, height, noWrap, rowSpan, vAlign, and width. One special property worth mentioning is cellIndex, which holds the index of the cell in its current row. This can be useful to pass to the insertCell() and deleteCell() methods. The simple example here shows how to manipulate cells:

<<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">>
<<html xmlns="http://www.w3.org/1999/xhtml">>
<<head>>
<<title>>Table Cell Fun<</title>>
<<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1" />>
<</head>>
<<body>>

<<table id="table1" border="1">>
<<tr id="row1">>
   <<td id="cell1">>Cell 1<</td>>
   <<td id="cell2">>Cell 2<</td>>
<</tr>>
<<tr id="row2">>
   <<td id="cell3">>Cell 3<</td>>
   <<td id="cell4">>Cell 4<</td>>
<</tr>>
<</table>>

<<script type="text/javascript">>
<<!--
var theTable = document.getElementById("table1");   
function doRowInsert(row)
{
  var rowNumber = parseFloat(row);
  if ((rowNumber >>= 0) && (rowNumber <<= theTable.rows.length))
   theTable.insertRow(rowNumber);
}
   
function doCellInsert(row,column)
{
 var rowNumber = parseFloat(row);
 var colNumber = parseFloat(column);
 var numberRowsInTable = theTable.rows.length;
 if ((rowNumber >>= 0 ) && (colNumber >>= 0))
  {
   if (rowNumber >>= numberRowsInTable)
    {
     alert("Can't add beyond defined rows");
     return;
    }      
   if (colNumber >> theTable.rows[rowNumber].cells.length)
    {
     alert("Can't add more than one beyond columns");
     return;
    }  
   theTable.rows[rowNumber].insertCell(colNumber); 
  }
}
   
function doCellModification(row,column,newValue)
{
 var rowNumber = parseFloat(row);
 var colNumber = parseFloat(column);
 var numberRowsInTable = theTable.rows.length;
 if ((rowNumber >>= 0 ) && (colNumber >>= 0))
  {
   if (rowNumber >>= numberRowsInTable)
    {
     alert("Can't modify cells outside the table");
     return;
    }      
   if (colNumber >>= theTable.rows[rowNumber].cells.length)
    {
     alert("Can't modify cells outside the table");
     return;
    }  
   theTable.rows[rowNumber].cells[colNumber].innerHTML = newValue; 
  }
}
   
function doCellDelete(row,column)
{
  var rowNumber = parseFloat(row);
  var colNumber = parseFloat(column);
  var numberRowsInTable = theTable.rows.length;
  if ((rowNumber >>= 0 ) && (colNumber >>= 0))
  {
   if (rowNumber >>= numberRowsInTable)
    {
     alert("Can't delete beyond defined rows");
     return;
    }      
   if (colNumber >>= theTable.rows[rowNumber].cells.length)
    {
     alert("Can't delete beyond the column");
     return;
    } 

   theTable.rows[rowNumber].deleteCell(colNumber); 
  }
}
//-->>
<</script>>
<<form name="testForm" id="testForm" action="#" method="get">>

Row #: <<input type="text" name="rowtoinsert" id="rowtoinsert" size="2"
maxlength="2" value="1" />>
<<input type="button" value="Insert Row"
 onclick="doRowInsert(document.testForm.rowtoinsert.value);" />><<br />>
Row #: <<input type="text" name="insertionRow" id="insertionRow" size="2"
 maxlength="2" value="0" />>
Column #: <<input type="text" name="insertionColumn" id="insertionColumn" size="2"
 maxlength="2" value="0" />>
<<input type="button" value="Insert Cell"
 onclick="doCellInsert(document.testForm.insertionRow.value,document.testForm.
insertionColumn.value);" />><<br />>
Row #: <<input type="text" name="modifyRow" id="modifyRow" size="2" maxlength="2"
 value="0" />>
Column #: <<input type="text" name="modifyColumn" id="modifyColumn" size="2"
 maxlength="2" value="0" />>
New Contents: <<input type="text" name="newContents" id="newContents" size="20"
 maxlength="20" value="" />>
<<input type="button" value="Modify Cell Contents"
 onclick="doCellModification(document.testForm.modifyRow.value,document.testForm.
 modifyColumn.value,document.testForm.newContents.value);" />><<br />>
Row #: <<input type="text" name="deletionRow" id="deletionRow" size="2"
 maxlength="2" value="0" />>
Column #: <<input type="text" name="deletionColumn" id="deletionColumn" size="2"
 maxlength="2" value="0" />>
<<input type="button" value="Delete Cell"
 onclick="doCellDelete(document.testForm.deletionRow.value,document.testForm.
deletionColumn.value);" />><<br />>
<</form>>
<</body>>
<</html>>

The rendering of the preceding example is shown in Figure 13-5.

Click To expand
Figure 13-5: Cell and row manipulation example
Note 

You may notice that the HTML table used did not include all HTML 4 table tags. In most cases you can get away with this form of HTML. However, further breaking HTML “rules” like not closing quotes or tags may produce unpredictable results.


Team LiB
Previous Section Next Section