The joy of… JavaScript’s getElementsByTagName()
For what it’s worth the kernel of this article was dictated into my phone on my drive into work this morning. I got the idea, had the framework and figured- why the hell not just talk to myself for a while. It was actually pretty efficient, so I might do more of it and if I get good enough at this sort of extemporaneous dictation I might turn it into a podcast
getElementsByTagName is probably my second favorite JavaScript DOM method behind getElementById. By itself getElementsByTagName is very powerful and a combination of the two can create a powerful tool to access DOM elements anonymously. One of the core tenets in my work as a front end developer is to use semantic xHTML markup with no extraneous hooks which I then manipulate with JavaScript. I try for a clear separation between behavior, content and style, so I hate to create classes or IDs just for script. Unless an ID or Class has a real benefit in terms of CSS or has a real, valid descriptive benefit for the document in a semantic sense, I don’t want to use anything other than plain vanilla HTML elements. I hate to add classes or IDs to my documents unless I absolutely have to. It’s a holdover from the days when I was obsessed with bandwidth (even more than I am now) mixed with a desire to have simple, clean code.
To that end I’ve developed techniques to access objects and collections of objects anonymously. One of the most powerful tools in that toolbox is getElementsByTagName. I rely on it all the time.
Now, the most straightforward use of getElementsByTagName, and the one people are probably most familiar with is document.getElementsByTagName. Pass a TD or A as an argument and it will return a nodeList of all the TDs or Anchor tags in an entire document. That’s great if I want to, for some reason, manipulate every DIV, A or TD on a page. The thing is, I very rarely want to manipulate every single item of a certain type on an entire page. Elements are usually used in multiple ways in a document so, what happens in that situation is there’s a huge collection of elements in an array, which have to be looped through and tested for a certain class or other attribute. If I end up doing something like that, I’d rather use a a DOM helper function like getElementsByClass() or something similar. The interesting thing is, you can DOM methods and a little bit of structural markup you can get similar results as getElementsByClass() without having to create any extraneous classes.
That’s because, with the way that JavaScript inheritance works, document, isn’t the only object that can use the getElementsByTagName method. Any object that represents a document or document fragment (node) can provide scope to getElementsByTagName, so it’s easy to limit the the search to a specific object which will represent a specific node in a document. That will then return all child nodes of that Element type of that limited document node. Say, for example, you have a DIV id of “menu”. And you want to manipulate all of the LIs that sit inside of that DIV. So you’d use:
document.getElementById("menu").getElementsByTagName("li")
With that you’d get a smaller nodeList of just the child LI nodes of that “menu’ DIV. That’s a really neat little collection. from there you can easily manipulate each of those to attach behaviors or to mimic the :hover pseudo class in IE6 with JavaScript or whatever else you need to do.
One other great use of getElementsByTagName is using that method on an XML node. Let’s say I’m using the XMLHttpRequest object and it returns some XML data. JavaScript recognizes that XML data as an object with nodes that you can explore and manipulate. One of the easiest ways to get at that data is to use getElementsByTagName. There are other ways to do it- using childNodes and parentNodes to iterate through the XML to test values and properties and the like is an option, but getElementsByTagName can just grab a collection of XML tags. So say there’s an XML document with some arbitrary tags and the script needs to get their value.
In the XHR script the XML response to the request is set to a variable:
xml_document = http.responseXML;
then getElementsByTagName is used
xml_document.getElementsByTagName("yourtag")
which returns a collection of yourtag nodes from the XML document.
One thing I’ll often do, if I know intimately what I’m getting is pass the method a specific index. So if I know I want to get the value of the tag “city” with a name property of “Abington” and I know in advance in the XML document that represents Massachusetts cities and towns, name=”Abington” is the first member of that array I can pass the 0 index to the method and return just that node. Like this:
xml_document.getElementsByTagName("city") [0]
Another thing available here is, if I set xml_document.getElementsByTagName("city") to a variable cities, I can loop through that nodeList and then again use getElementsByTagName on each member of the cities nodeList to get individual child nodes of that XML document. It’s really powerful to couple it and loop through to create these collections of collections which can be manipulated in a lot of ways.
Once common place I use getElementsByTagName is to turn a block into a clickable area. As with everything script related, I really prefer to do it anonymously. I don’t want to know in advance how many blocks there will be, what the link will be, etc. I don’t want to know any of that. I really want someone doing some markup to be able to just edit a link in HTML and then the script will come in on the backside and make the magic happen.
So there’s a collection of these blocks, and a child node in each of these blocks is an anchor. A real anchor pointing to a real URL. Since, for accessibilities sake, I want to use a real link. I don’t want #s or any of that. So what I would is create a collection of LIs:
menu_lis = document.getElementById("menu").getElementsByTagName("li")
and then loop through that nodeList, using the this keyword and getElementsByTagName to reference the href property of the first A child node of each LI, to build out the JavaScript needed to make the whole block clickable
for (i=0;i< menu_lis s.length;i++) {
setHandler(menu_lis [i],'onclick','document.location=this.getElementsByTagName("a")[0].href');
}
And that’s my piece on getElementsByTagName. What’s next? Whatever strikes me on my drive in…
[updated to add]
I forgot to point out one use of getElementsByTagName()- using the widlcard “*” argument. Passing the wild card to the method returns a collection of every HTML element in the document. Which is useful when you want/need to flatten the hierarchy to search the elements on a page. I use it in an example script where I search through every node in an XML document testing attributes.
Bob Tulloch Says:
Neat informative article. I will definitely be borrowing these techniques ~ I really liked the combination of ById and ByTag.
PS
Please have a look at my site (www.EuropeanHospitalRegister.com) - any suggestions are gratefully received.
Posted: June 8th, 2007 at 1:11 am
Peter Says:
I’m a beginner playing around with Javascript and I’d like to ask you a question.
I realize the power of document.getElementsByTagName, which is how I found your page, and I’m trying to use it for a simple page I’m trying to create.
I have three menu options at the top of this page, which I am successfully using CSS to achieve a mouse rollover effect for each selection.
When a user clicks on one of these options, I want to store the <a> tag name into a variable using Javascript.
Here’s my feeble attempt:
Demographics
Website Traffic
Rates & Availability
And, here’s my feeble attempt at creating a Javascript function–GetTg() to store the a tag reference to a variable name using document.getElementsByTagName.
function GetTg() {
var TgVar = document.getElementsByTagName(’a');
}
Once I can store the anchor tag to a variable, I want to use it in a switch/case statement to display HTML based on the selection.
Any help is appreciated…
Posted: July 21st, 2007 at 12:22 am
Vladimir Orlovsky Says:
document.getElementsByTagName(”city”) [0]
Need help!
No body explain how to handle element: “[0]”
in javascript.
What it is? ‘index’ of some kind.
How do I get it and pass it ?
Thanks.
Vladimir
Posted: August 14th, 2007 at 6:39 pm
rob Says:
this method returns an array, so, yes, [0] is an index. it refers to the first member of the collection (since the count starts at 0). As for how to get it, if you’ve got a valid tag reference passed as an argument, then you’ve “got it.”
At that point you’ve got a reference to the object and can do whatever you want with it.
Posted: August 14th, 2007 at 7:35 pm
orlando Says:
i started to use getElementsByTagName by i can’t figure it out how to access a property of the tag, for example , i have the following xml response:
Test Contract
i put the id property to identify the contract,
when i handle the response i get the inner text ‘Test Contract’ with no problem, but how can i access the ‘id’ property?
thanks,
orlando
Posted: December 14th, 2007 at 12:57 pm
rob Says:
could could try something like
xml_document.getElementsByTagName(”city”) [0].id;
or
xml_document.getElementsByTagName(”city”) [0].getAttribute(”id”);
Posted: December 14th, 2007 at 1:18 pm
Rama Says:
Hi,
Do you have any idea about handling null values which are passed to getElementsByTagName().
For example
var obj = xmlDoc.getElementsByTagName(”x”)[0];
var objerrorcode = obj.getElementsByTagName(”y”)[0];
where in xml , x is the parent of y. and y has some childNodes. if the complete tag ( somestuff ) itself is not passed , how can you handle this when y has some childNodes which have to be accessed ?
Posted: April 26th, 2008 at 3:20 am
rob Says:
Hi Rama, I’m not quite following. Do you have some sample XML I could take a look at?
Posted: April 29th, 2008 at 6:59 am