Through the W3C's Document Object Model (DOM), normally invisible parts of a Web page can be easily made a part of the visible page. The DOM, for example, can be used to reveal the information contained within things like the title attribute in most modern browsers. (This can easily be accomplished onclick="window.open(this.href);return false;">using CSS, but not in Internet Explorer on Windows.)

To see how this works, let's assume there's a page with a bulleted list of news items. Each LI has the date the item was posted in the element's title:

<div id="news">

  <ul>

    <li title="January 1, 2002">Happy New Year's</li>

    <li title="March 17, 2002">Happy St. Patrick's Day</li>

    <li title="April 1, 2002">April Fool's</li>

  </ul>

</div>

Before attempting to access the content, it's important to check the browser's higher-level DOM support:

if((document.createElement) && (document.createTextNode))

(This should be true for IE5+, Konqueror, Netscape 6.x, Mozilla, and other Gecko-based browsers. Opera 5 and 6 should test false.)

Finding the right elements

With the appropriate browsers selected, it's time to collect references to the various LIs.

The page may contain a number of LIs, but, for this example, only ones within the DIV called “news” are needed, so that element, and its contents, are isolated:

var sObj = document.getElementById('news')

This associates the DIV containing the LIs with the variable sObj. With that variable, the LIs can be gathered into an array:

var tag = sObj.getElementsByTagName('LI')

Collecting the information

The next step is to cycle through each LI in the array, creating a new text object filled with the content from the element's title:

for(x=0;x<tag.length;x++) var value = document.createTextNode(tag[x].title)

(An alternate to tag[x].title would be tag[x].getAttribute('title').)

Displaying the content

A new SPAN element will be created to hold the title's content:

var wrap = document.createElement('SPAN')

That content, held in the value variable filled earlier, is placed within the newly created element using appendChild:

wrap.appendChild(value)

Finally, this new node is placed within the appropriate LI:

tag[x].appendChild(wrap)

Styling the content

Like the other elements on the page, this newly created node can be styled by setting the style attribute:

wrap.setAttribute('style','color: #F00;')

Unfortunately Internet Explorer on Windows doesn't recognize styles created using setAttribute so, for that browser, a Microsoft-specific DOM method must be used:

var agt = navigator.userAgent.toLowerCase();

if((agt.indexOf('msie')!=-1) && (agt.indexOf('win')!=-1)){

  document.styleSheets[0].addRule('#news LI SPAN','color: #F00;')

} else { wrap.setAttribute('style','color: #F00;') }

If you have a browser that supports these methods, you can see this script in action.

One generic script

Since this script could be used to pull any attribute information from any element, it makes sense to make the script more universal. So, the previous steps have been combined, with minor alterations, into one generic function.

Here are the variables used in the function (called “writeAttribute”) mapped to the values from this example:

Variable Description Example
i element's id news
sT source tag LI
sA source attribute title
nT new, created tag SPAN
nA new, created attribute style
nAv value for the new attribute color: #F00;

The full script with alterations

One note: the last else if is for Opera 5 and 6 only, and can be safely deleted. The section writes a style rule so Opera can use CSS to duplicate what the script does with the DOM. This additionally functionality will only work in Opera if the new, created attribute (nA) has a value of style.

function writeAttribute(i,sT,sA,nT,nA,nAv){

  var d = document;

  var agt = navigator.userAgent.toLowerCase();

  if((d.createElement) && (d.createTextNode)){

    var sObj = d.getElementById(i);

    var tag = sObj.getElementsByTagName(sT);

    for(x=0;x<tag.length;x++){

      var value = d.createTextNode(' '+tag[x].getAttribute(sA));

      var wrap = d.createElement(nT);

      wrap.appendChild(value);

      tag[x].appendChild(wrap);

      if((nA='style') && (agt.indexOf('msie')!=-1) && (agt.indexOf('win')!=-1) && (parseInt(navigator.appVersion)==4)) d.styleSheets[0].addRule('#'+i+' '+sT+' '+nT,nAv);

      else wrap.setAttribute(nA,nAv);

    }

  } else if((agt.indexOf("opera")!=-1) && (nA="style")){

    d.write("<style type=\"text\/css\" media=\"screen\">"+

    "#"+i+" "+sT+"["+sA+"]:after { content: ' 'attr("+sA+")''; "+nAv+"; }"+

    "</style>")

  }

}

Putting writeAttribute to work

Because the function reads the elements within the document, it can't be called from within the head. To keep the page organized, place the writeAttribute call immediately after the elements you want to access, and fill in the relevant variables:

<div id="news">

...

</div>

<script type="text/javascript">

<!--

  writeAttribute('news','LI','title','SPAN','style','color: #F00')

//-->

</script>

Growing the code

This is just one example of how the DOM can be used to access previously unavailable elements of a Web page. With some imagination, the writeAttribute function could be used to add images or create CSS-based rollover effects using the information already contained within a page.