Creating custom collections in NS6

NS 6, with it's scripting engine based on the shiny DOM Level 2, supports a few methods for retrieving elements on the page. The two most prominent ones are:

-document.getElementById(idname)
-document.getElementsByTagName(tagname)

whereby the first method retrieves an element with a specific ID, and the second fetches all elements of a particular TAG. Digging up the remaining methods for element retrieval in NS 6, it seems the browser currently does not have one for the extraction of arbitrary elements into a custom collection. In IE4+, such a task is easily accomplished by assigning the same ID to the elements you wish extracted. IE then automatically creates a custom collection out of these elements. For example:

<img src="1.gif" id="test">
<b>Hello</b>
<span id="test">There</span>

document.all.test.length //returns 2
document.all.test[0] //returns <img src="1.gif">

Custom collections are extremely powerful, since they allow your script to selectively manipulate portions of the page, in a generic manner.

[Red_CurlyC035.gif (995 bytes)] Creating custom collections out of arbitrary elements in NS6

Ok, so NS 6 doesn't support a direct way of filtering out arbitrary elements. Good thing it's just playing hard to get. Using existing DOM features, glued together by some good old fashion JavaScript, we can somewhat get around this limitation.

Here's the basic idea. We know NS 6 is capable of retrieving a specific, singular element, via document.getElementById. A custom collection is merely an assembly of such unique elements. So far so good? By labeling participating elements (via the ID attribute) in a particular manner, along with document.getElementById and a while loop, we have all the ingredients needed to retrieve arbitrary elements and store them into a custom collection.

Let's see just what all this means, in code:

<img src="1.gif" id="test0">
<b>Hello</b>
<span id="test1">There</span>

<script>
var i=0
var customcollect=new Array()

while (document.getElementById("test"+i)!=null){
customcollect[i]= document.getElementById("test"+i)
i++
}

Notice how we labeled the participating elements- with an identical name suffixed with an incrementing number (ie: test0, test1). This is to facilitate the while loop that follows, which generically gathers these elements all up and into an array. Customcollect[] now contains what we want.

The above technique works in any browser that supports DOM 2, and not just NS 6.


[Red_CurlyC035.gif (995 bytes)] So what's the point?

Like many advanced techniques, the usefulness of custom collections may not leap out at you instantly. Essentially, custom collections enable your script to easily reach out to more than just one element on the page. Think of them in terms of parameters and what they do for functions.

A script like the following is fine untouched:

Demo: Hot!

Source:

<b id="red">Hot!</b>

<script>
function redit(){
if (document.getElementById){
if (document.getElementById("red").style.color!="red")
document.getElementById("red").style.color="red"
else
document.getElementById("red").style.color=''
}
}
setInterval("redit()",1000)
</script>

However, if you wish the script to be able to "turn red" multiple text on the page, custom collections can definitely help, by allowing for an elegant, simplistic, and generic way of accomplishing the task:

Demo: The desert is hot. Very very hot!

Source:

The desert is <b id="red0">hot</b>. Very very <b id="red1">hot!</b>

<script>
var redobject=new Array()
var i=0

//create custom collection
//out of elements with id="redx"
if (document.getElementById){
while (document.getElementById("red"+i)!=null){
redobject[i]=document.getElementById("red"+i)
i++
}
}

function redit(which){
if (redobject[which].style.color!="red")
redobject[which].style.color="red"
else
redobject[which].style.color=''
}

//for each element in collection
//call redit() on it
if (document.getElementById){
for (y=0;y<redobject.length;y++){
var temp='setInterval("redit('+y+')",1000)'
eval(temp)
}
}

</script>

The top chunk inside the script gathers up all elements with ID="redx". A modified function redit(which) then manipulates this array of elements. The last chunk is thrown in to "activate" things, by dynamically cycle through all elements within the custom collection, firing off redit() on each element individually, in turn the annoying blinking effect. What's important to realize here is how easy it was to apply the script effect to multiple text- via the ID attribute.