Wrox Home  
Search
Web Standards Programmer's Reference: HTML, CSS, JavaScript, Perl, Python, and PHP


Sorting Elements Using the Document Object Model

You can also rearrange elements in a document using JavaScript and the DOM, as shown in the following example.

Example: Sorting Elements Using the DOM

This example shows how an ordered list (OL node) can have its items (LIs) sorted using the DOM.

Source

This example uses functions used in previous examples but expands upon them by using a sort routine to sort the OL node's children.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<title>DOM Data Sort</title><style type="text/css">  
  div.div1 { background-color: #999999; }
  div.div2 { background-color: #BBBBBB; }  
  table, table * { border: thin solid black; }
  table { border-collapse: collapse; }
  td { padding: 5px; }</style>
  <script type="text/JavaScript">
  function findNode(startnode,nodename,nodeid) 
  {  var foundNode = false;  
  // Check our starting node for what we are looking for
  if ( startnode.nodeName == nodename &&
       startnode.id == nodeid ) {
    foundNode = startnode;
  } else {
    // If not found, look through children
    look_thru_children:
    if ( startnode.hasChildNodes() ) {
      var children = startnode.childNodes;
      for (var i = 0; i < children.length; i++) {
        foundNode = findNode(children[i],nodename,nodeid);
         // Return when found
         if (foundNode) { break look_thru_children; }
      }
    }
  }
  return foundNode;
}
function sortlist(node) {  // Does object have at least 2 children?
    if (node.hasChildNodes() && node.firstChild.nextSibling != null) {    
	for (i = 1; i < node.childNodes.length; i++) {
      // Only sort LIs
      if (node.childNodes[i].nodeName != "LI") { continue; }      
	  for (j = i+1; j < node.childNodes.length; j++) {
        // Only sort LIs
        if (node.childNodes[j].nodeName != "LI") { continue; }        
		// Sort needed?
        if (node.childNodes[i].firstChild.nodeValue >
            node.childNodes[j].firstChild.nodeValue) {
          // Use temporary nodes to swap nodes
          tempnode_i = node.childNodes[i].cloneNode(true);
          tempnode_j = node.childNodes[j].cloneNode(true);
          node.replaceChild(tempnode_i, node.childNodes[j]);
          node.replaceChild(tempnode_j, node.childNodes[i]);
        }      }    }  }}
function dofindNsort() {
  alert("Click OK to sort list");
  // Find and sort node
  var node = findNode(document,"OL","sortme");
  sortlist(node);
}</script></head>
<body onload="dofindNsort()">
<div class="div1">
  <h1>Heading 1</h1>
  <table>
    <tr><td>Cell 1</td><td>Cell 2</td></tr>
    <tr><td>Cell 3</td><td>Cell 4</td></tr>
  </table>
  <p>Lorem ipsum dolor sit amet, consectetuer adipiscing
  elit, sed diam <b>nonummy nibh euismod</b> tincidunt ut laoreet
  dolore magna aliquam erat volutpat. Ut wisi enim ad minim
  veniam, quis nostrud exerci tation ullamcorper suscipit
  lobortis nisl ut aliquip ex ea commodo consequat.</p>
</div>
<div class="div2">
  <h1>Heading 2</h1>
  <p>Lorem ipsum dolor sit amet, consectetuer adipiscing
  elit, sed diam nonummy nibh euismod tincidunt ut laoreet
  dolore magna aliquam erat volutpat. Ut wisi enim ad minim
  veniam, quis nostrud exerci tation ullamcorper suscipit
  lobortis nisl ut aliquip ex ea commodo consequat.</p>
  <ol id="sortme">An ordered list
    <li>Gamma</li>
    <li>Alpha</li>
    <li>Beta</li>
  </ol>
</div>
</body>
</html>

This example works similarly to that of previous examples. After the node is found, its LI children are sorted in ascending order. Note the checks built into the sort routine to ensure only the LIs are sorted — the text of the OL and other non-LI children is ignored in the sort routine. This is necessary because you can't always predict the elements a user agent identifies as nodes.

For an example of how user agent's differ in reporting nodes, compare the DOM from Mozilla's Firefox browser shown in Figure 5 to that of Microsoft's Internet Explorer shown in Figure 4.


Figure 4

Figure 5

Notice the extra text elements scattered throughout the Firefox DOM (Figure 5), especially between elements like the LI nodes. If the script didn't check for valid LI nodeNames, the text nodes would be sorted into the LIs, disrupting the structure.

Also note that temporary nodes are used to swap the node contents. The swap could not be done using traditional methods (one temporary value) using the replaceChild() function:

          tempnode = node.childNodes[j].cloneNode(true);
          node.replaceChild(node.childNodes[i], node.childNodes[j]);
          node.replaceChild(tempnode, node.childNodes[i]);

The second line in the preceding code removes node.childNodes[i] from the document to replace node.childNodes[j]. Therefore, that node ([i]) would not exist for the third line of the code to operate on.

Output

The output of this script is shown in Figure 6. Note how the OL node's LI children have been sorted into ascending order.


Figure 6

Summary

Although the W3C DOM isn't used as much as the DHTML DOM implemented by both major browser developers, the W3C DOM is used by both browser developers and contains much power to manipulate documents using minimal scripting. This series showed you how to use JavaScript to traverse the DOM, locate particular nodes, and change/rearrange the document's contents.

This article is adapted from Web Standards Programmer's Reference: HTML, CSS, JavaScript, Perl, Python, and PHP by Steven M. Schafer (Wrox, 2005, ISBN: 0-7645-8820-6), from Chapter 21 "The Document Object Model." This is the third of a three-part series of articles on this topic which began with this Part I and Part II. Steve programs in several languages and technologies, with extensive experience in Linux and related open-source platforms.