Home » Tutorials Advanced Tutorial

How to Develop Web Applications with Ajax: Pt. 2 - page 3

Not rated
Rate:

Jonathan Fenocchi
February 17, 2006


Jonathan Fenocchi
Jonathan Fenocchi is a talented young developer coming at you from southern TX, USA. Accessibility advocate, proficient programmer, and determined designer, Jonathan spends his free time researching new technologies, developing new ideas, playing video games and listening to rock music. Jonathan runs a Slightly Remarkable blog where he focuses on web-related content, and continues to pursue his goals as an aspiring web developer."

Jonathan Fenocchi has written 20 tutorials for JavaScriptSearch.
View all tutorials by Jonathan Fenocchi...

The next change comes inside of the for loop: we set values to the subAry and subAryLen variables. The subAry variable becomes an array of the <task> elements of the current <pet>. The subAryLen variable becomes the length of that array until it changes again (when the outer for loop starts over with the next <pet>).

We create an inner for loop to process all the <task> elements, one at a time. Basically, we create a new data cell, input a comma-delimited list of tasks in it, then close the data cell and the current row. Specifically, the current <task> element’s node data (the task itself; for example, “Feed”) is placed into a data cell inside the “insertData” variable.

After that, we check to see if there are any more tasks for the current <pet>. If there are more, we append a comma (,) to the insertData variable so that each task is delimited with a comma (as “a, b, c” instead of “a, b, c,” – note the last comma on the second task, which we do not want). This is done by checking the length of the subAry array against the for loop's “j” variable plus one. Since the loop increments “j,” in the next loop, the “j” will equal one more than it does at the time of the check. Therefore, if “j+1” (or, “what j will equal when and if the loop starts again”) equals subAryLen (the number of <task> nodes within the current <pet> node), the loop won’t run again. If the loop doesn’t run again, we don’t want to add another comma to separate the tasks. So if “j+1” is NOT equal to subAryLen, we know that we can safely add a comma to “insertData” in preparation for the next <task>.

Once the inner for loop has ended, we close the task data cell and that pet’s row. The outer loop starts over by creating a new row and moving to the next <pet>. This process repeats until all <pet> elements (and all <task> elements for each pet) have been processed.

Is There Another Way?

You might be thinking: “That JavaScript can get pretty complex, but it only gets more complex each time the XML gets more complex. Maybe we can simplify the XML to, in turn, simplify the JavaScript.” If you are, that’s great, because you’re absolutely correct. Of the different methods I showed earlier, the one I chose to elaborate on might appear to be the least desirable. What if we chose to use attributes for both the pet and the corresponding tasks? What would the XML look like?

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

Wow! This is much simpler. Let’s look at how our processXML function will change:

      function processXML(obj){
        var dataArray = obj.getElementsByTagName('pet');
        var dataArrayLen = dataArray.length;
        var insertData = '<table><tr><th>'
         + 'Pets</th><th>Tasks</th></tr>';
        for (var i=0; i<dataArrayLen; i++){
            insertData += '<tr><td>' + dataArray[i].getAttribute('type')             + '</td>'
    + '<td>' + dataArray[i].getAttribute('tasks') + '</td></tr>';
        }
        insertData += '</table>';
        document.getElementById ('dataArea').innerHTML = insertData;
    }

As you may have suspected, the function is much simpler. When code is simpler, it’s usually more efficient. The only difference between this and one of our older functions is that the insertData variable now gets more HTML inserted into it, specifically two new attributes: “type” and “tasks.” As we learned earlier, these are the attributes we gave to the <pet> elements in our XML document, and each pet’s attributes has different values. This is probably the easiest way to modify the XML yourself to fit fluctuations in your schedule. e.g., If you finally get rid of your cat’s fleas, you can easily remove “Comb for fleas” from the list of daily tasks for your cat, whereas with the XML we used earlier, that would have been confusing to implement.

The last XML formatting method is a mixture of two. Here, we’ll use attributes and different tags. Let’s have a look at some example XML:

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

This is probably the most comprehensible XML yet. Let's analyze the changes we'll need to make to our processXML function in order for everything to work:

      function processXML(obj){
        var dataArray = obj.getElementsByTagName('pets')[0].childNodes;
        var dataArrayLen = dataArray.length;
        var insertData = '<table><tr><th>'
         + 'Pets</th><th>Tasks</th></tr>';
        for (var i=0; i<dataArrayLen; i++){
          if(dataArray[i].tagName){
            insertData += '<tr><td>' + dataArray[i].tagName + '</td>'
                + '<td>' + dataArray[i].getAttribute('tasks') + '</td></tr>';
          }
      }
      insertData += '</table>';
      document.getElementById ('dataArea').innerHTML = insertData;
    }

The “dataArray” now references the <pets> child nodes as an array. (In other words, dataArray is now an array of all the nodes within the <pets> node.) This is because each tag is different (<Cat />, <Dog />, and <Fish />), so we can’t search for these elements by their name (as we could with <pet>, since they were all <pet> elements).

Once again, there is whitespace between these nodes, so text nodes need to be eliminated from our processing. We can do this by checking to see if a tag name is present – text nodes are nodes but not tags, while the <Cat />, <Dog /> and <Fish /> nodes are all tags. If a tag name is present, we can insert new data into the insertData variable. The data we insert is a table row and two table data cells. The first cell is the tag name, which is the type of pet (Cat, Dog or Fish), and the second cell is the value of the “tasks” attribute for that specific animal (such as “Feed or Water”).

Closing Notes

There are many more variations of the examples I’ve demonstrated in this article, so feel free to test them to see which is right for you. Just remember that XML is “eXtensible” so there’s no “wrong” way to group your data, though there’s often a “best” way. Also, keep in mind that your XML should be well-formed. Bear in mind that most problems come from forgetting to close a tag (as in <Dog /> instead of <Dog>; unless you have data that goes inside that node, in which case you would put <Dog>data here</Dog>).

It’s my intention that this use of XML and JavaScript isn’t confusing, but enlightening. By gradually learning to deal with more data, you can put Ajax to greater use. I’d love to see more of Ajax on corporate sites, etc., so if you’ve put this knowledge into practice, I'd like to know about your experiences.


Add commentAdd comment (Comments: 0)  

Advertisement

Partners

Related Resources

Other Resources

arrow