JavaScript Editor Free JavaScript Editor     JavaScript Debugger 




Main Page

Previous Page
Next Page

6.8. XML Data Islands

For readers who are unfamiliar with the term XML Data Islands, they refer to the real estate that is usually purchased with the profits from one's first book. You know, the kind of real estate that isn't there when the tide is in. Oops, my mistake: wrong definition.

Take two!

For those readers who are unfamiliar with the term XML Data Islands, they are XML that is embedded with the body of an HTML document. Although this sounds simple enough, there is a little more to it than that; Microsoft Internet Explorer hides the XML, whereas Firefox and other Geckobased web browsers do not.

6.8.1. Internet Explorer

Because Microsoft Internet Explorer has built-in support for XML data islands, it is simply a matter of embedding the XML in a web page, as described in more detail in Chapter 8. Binding the XML to the HTML is merely a matter of defining the datasrc and the datafld, where the datasrc is the ID from the XML element and the datafld is either an element or an attribute. The idea is that because the HTML is bound to the XML, changes in one are reflected in the other, which can be a real timesaver when developing a web application.

6.8.2. Firefox

With Gecko-based web browsers such as Firefox, Flock, Netscape, or Mozilla XML, data islands require a bit more work to pull off. Let's look at an example of a Cascading Style Sheet shown here in Listing 6-13. Its purpose is to prevent the XML data island from being rendered, which solved only part of the problem.

Listing 6-13. CSS to Hide XML

xml
{
display: none;
font-size: 0px
}

The rest of the problem, the binding, was resolved using JavaScript and HTML as originally shown in Listing 4-7 and again is shown in Listing 6-14.

Listing 6-14. Cross-Browser Binding XML

<html>
    <head>
             <title>XML Data Island Test</title>
             <style type="text/css">

xml
{
      display: none;
      font-size: 0px
}
            </style>
            <script language="JavaScript">
var _IE = (new RegExp('internet explorer','gi')).test(navigator.appName);

/*
    Function:     _bind
    Programmer: Edmond Woychowsky
    Purpose:    Handle the logic necessary to bind HTML elements
to XML nodes.  Note that in some instances this
binding is a two-way street. For example, if the value in
a text box should change the corresponding value in the
XML data island will also change.
*/
function _bind() {
  if(arguments.length == 0) {
    doBind(document.body.getElementsByTagName('div'));
    doBind(document.body.getElementsByTagName('input'));
    doBind(document.body.getElementsByTagName('select'));
    doBind(document.body.getElementsByTagName('span'));
    doBind(document.body.getElementsByTagName('textarea'));
  } else {
    applyChange(arguments[0],arguments[1]);
    _bind();                                // Re-bind
  }

  /*
        Function: doBind
        Programmer: Edmond Woychowsky
        Purpose: To handle data-binds for specific nodes
  based upon HTML element type and browser type.
  */
  function doBind(objects) {
    var strTag;                       // HTML tag
    var strDI;                        // XML data island id
    var strNode;                      // XML node name
    var strValue;                     // XML node value

    for(var i=0;i < objects.length;i++) {
      strTag = objects[i].tagName;
      strDI = objects[i].getAttribute('xmldi');
      strNode = objects[i].getAttribute('xmlnode');

      if(_IE)
        strValue =
document.getElementById(strDI).XMLDocument.selectNodes('//' +
strNode).item(i).text;
    else

        strValue =
document.getElementById(strDI).getElementsByTagName(strNode)[i].innerHTML;

      switch(strTag) {
        case('DIV'):
        case('SPAN'):
            objects[i].innerHTML = strValue;

            break;
        case('INPUT'):
            switch(objects[i].type) {
                case('text'):
                case('hidden'):
                case('password'):
                    objects[i].value = strValue;
                    objects[i].onchange = new Function("_bind(this," +
i.toString() + ")");
                    break;
                case('checkbox'):
                    if(objects[i].value == strValue)
                        objects[i].checked = true;
                    else
                        objects[i].checked = false;

                    objects[i].onclick = new Function("_bind(this," +
i.toString() + ")");
                    break;
                case('radio'):
                    if(_IE)
                        strValue =
document.getElementById(strDI).XMLDocument.selectNodes('//' +
strNode).item(0).text;
                    else
                        strValue =
document.getElementById(strDI).getElementsByTagName(strNode)[0].innerHTML;

                   if(objects[i].value == strValue)
                       objects[i].checked = true;
                   else
                       objects[i].checked = false;

                   objects[i].onclick = new Function("_bind(this,0)");

                   break;
    }

    break;
case('SELECT'):
case('TEXTAREA'):
    objects[i].value = strValue;

            objects[i].onchange = new Function("_bind(this," +
i.toString() + ")");

            break;
      }
    }
  }

  /*
        Function:   applyChange
        Programmer: Edmond Woychowsky
        Purpose:    To handle changes to the bound HTML elements and apply
                    those changes to the appropriate XML node.
  */
  function applyChange(obj,index) {
    var strDI = obj.getAttribute('xmldi');
    var strNode = obj.getAttribute('xmlnode');
    var strValue = obj.value;

    if(obj.type == 'checkbox')
        if(obj.checked)
            strValue = obj.value;
        else
            strValue = '';

    if(_IE)
        document.getElementById(strDI).XMLDocument.selectNodes('//' +
strNode).item(index).text = strValue;
    else

document.getElementById(strDI).getElementsByTagName(strNode)[index].innerH
TML = strValue;
  }
}
            </script>
      </head>
      <body onload="_bind()">
            <xml id="xmlDI">
                <a>
                <b>
                   <c>one</c>
                </b>
                <b>
                   <c>two</c>
                </b>
                <b>
                   <c>three</c>
                </b>
            </a>
            </xml>
            <b>XML Data Island Test</b>
            <br />

            <div xmldi="xmlDI" xmlnode="c"></div>
            <br />
            <div xmldi="xmlDI" xmlnode="c"></div>
            <br />
            <div xmldi="xmlDI" xmlnode="c"></div>
            <br />
            <input type="text" xmldi="xmlDI" xmlnode="c" value="" />
            <br />
            <input type="text" xmldi="xmlDI" xmlnode="c" value="" />
            <br />
            <input type="text" xmldi="xmlDI" xmlnode="c" value="" />
            <br />
      </body>
</html>

Essentially, the code in this listing searches the HTML document for tags of the type that can be bound to the XML. As they are encountered, the next value from the XML is used and a change event handler is attached to the HTML. This way, when the visitor changes the value, the XML Data Island is updated.

Talk about lazy! No need to code-change event handlers by hand. This leads to the possibility of simply refreshing the XML Data Island from the server and rebinding to display updates. Pretty useful when the user requests another page of information, not only the next page or the previous page, but maybe even a search.


Previous Page
Next Page




JavaScript Editor Free JavaScript Editor     JavaScript Debugger


©