How to Develop Web Applications with Ajax: Pt. 2 | 2 | WebReference

How to Develop Web Applications with Ajax: Pt. 2 | 2

To page 1current pageTo page 3
[previous][next]

How to Develop Web Applications with Ajax: Pt. 2

Before We Continue...

I'd like to point out a couple of options:

First, you’ll notice we didn’t use the <pets> node. This is because we have only one data group (<pets>) and all the subsequent elements (each <pet> element); contains different data but they have the same name. In our case, this node could be omitted. However, it’s better to have <pet> elements inside a <pets> element, rather than to have a bunch of <pet> elements on their own (but still inside the <data> element).

Another way this could be done is by having a specific tag for each pet. For example:

     <?xml version="1.0" encoding="UTF-8"?>
    <data>
      <pets>
        <Cat />
        <Dog />
        <Fish />
      </pets>
    </data>

Then we could loop through the nodes within the <pets> element. The processXML function would then look like this:

        function processXML(obj){
          var dataArray = obj.getElementsByTagName('pets')[0].childNodes;
          var dataArrayLen = dataArray.length;
          var insertData = '<table style="width:150px; border: solid 1px #000"><tr><th>'
         + 'Pets</th></tr>';
        for (var i=0; i<dataArrayLen; i++){
           if(dataArray[i].tagName){
              insertData += '<tr><td>' + dataArray[i].tagName + '</td></tr>';
           }
        }
        insertData += '</table>';
        document.getElementById ('dataArea').innerHTML = insertData;
      }

What’s changed here is that we refer to the <pets> group element (the “[0]” means the first one, even though it’s the only one) and then its child nodes (the <Cat />, <Dog /> and <Fish /> elements). Since text nodes separate these nodes (the whitespace is considered a node), we need to make sure that only the nodes with tag names (that is, only the tags) get through. Then we output the name of each tag. Since the name of each tag is a pet, we don’t need to have data for each node – the name of the node itself will suffice. Give this a shot to see how it works.

Yet another way to do this is set an attribute value for each <pet> node. Your XML document would look like this:

    <?xml version="1.0" encoding="UTF-8"?>
    <data>
      <pets>
        <pet type="Cat" />
        <pet type="Dog" />
        <pet type="Fish" />
      </pets>
    </data>

You would change your processXML function just slightly, so that it becomes:

        function processXML(obj){
          var dataArray = obj.getElementsByTagName('pet');
          var dataArrayLen = dataArray.length;
          var insertData = '<table style="width:150px; border: solid 1px #000"><tr><th>'
          + 'Pets</th></tr>';
        for (var i=0; i<dataArrayLen; i++){
              insertData += '<tr><td>' + dataArray[i].getAttribute('type') + '</td></tr>';
          }
          insertData += '</table>';
          document.getElementById ('dataArea').innerHTML = insertData;
       }

The key difference here is we get the value from dataArray[i].getAttribute('type'). This takes the value of the current <pet> node's "type" attribute.

Moving On...

Now that we've covered some useful ways to retrieve data from a single group of XML data, let's look at how to retrieve data from multiple groups. Instead of just listing the pets one may own, let's suppose that we have a daily schedule for our pets. Each pet must be taken care of properly, since they have special needs. The caretaker of the animals meets these needs on a daily basis. Here's how to place this into well-formed XML:

    <?xml version="1.0" encoding="UTF-8"?>
    <data>
      <pets>
        <pet>Cat
          <task>Feed</task>
          <task>Water</task>
          <task>Comb out fleas</task>
        </pet>
        <pet>Dog
          <task>Feed</task>
          <task>Water</task>
          <task>Put outside</task>
        </pet>
        <pet>Fish
          <task>Feed</task>
          <task>Check oxygen, water purity, etc.</task>
        </pet>
      </pets>
    </data>

This might seem strange, but what we're creating sub-groups. Each <pet> element is a sub-group of the <pets> group, while each <task> is a sub-element of each <pet> group.

Before I go on, you may wish to format your tables using some CSS, like this:

      <style type="text/css"><!--
      table, tr, th, td {
        border: solid 1px #000;
        border-collapse: collapse;
        padding: 5px;
     }
    --></style>

This makes that table easier to read. Now let's dive into that processXML function:

      function processXML(obj){
        var dataArray = obj.getElementsByTagName('pet');
        var dataArrayLen = dataArray.length;
        var subAry, subAryLen;
        var insertData = '<table><tr><th>'
          + 'Pets</th><th>Tasks</th></tr>';
        for (var i=0; i<dataArrayLen; i++){
              insertData += '<tr><td>' + dataArray[i].firstChild.data + '</td>';
              subAry = dataArray[i].getElementsByTagName('task');
              subAryLen = subAry.length;
              insertData += '<td>';
                for(var j=0; j<subAryLen; j++){
                  insertData += subAry[j].firstChild.data;
                  if( subAryLen != j+1 ) { insertData += ', '; }
                }
            insertData += '</td></tr>';
      }
      insertData += '</table>';
      document.getElementById ('dataArea').innerHTML = insertData;
    }

The first new thing is the declaration of two variables: "subAry" and "subAryLen." These are similar to the "dataArray" and "dataArrayLen" variables, except they reference different arrays (specifically, they will reference the "task" elements, while the "dataArray" and "dataArrayLen" reference the "pet" elements).

We also changed the initial value of the "insertData" variable - we added a new table header (<th>) for our "tasks" column.

To page 1current pageTo page 3
[previous][next]
Created: March 27, 2003
Revised: October 7, 2005

URL: http://webreference.com/programming/javascript/jf/column13/1