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.

29 thoughts on “The joy of… JavaScript’s getElementsByTagName()

  1. 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.

  2. 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…

  3. 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

  4. 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.

  5. 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

  6. could could try something like

    xml_document.getElementsByTagName(“city”) [0].id;

    or

    xml_document.getElementsByTagName(“city”) [0].getAttribute(“id”);

  7. 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 ?

  8. Regarding your post #4, I have a small nit-pick which might help someone, as it did make something “click” for me in the past.

    getElementsByTagName doesn’t return an array. It’s an “array-like” collection of HTML elements. If you do this:

    alert(document.getElementsByTagName(‘p’));

    in Mozilla, you will be told “[object HTMLCollection]” since that is what it is. In more friendly-speak, it’s known as a node list, but it is NOT an array. For example, the Array object’s concat method won’t work on it because it isn’t an array. However, you can loop through it and it has a length property, which is why it is often confused with an array.

  9. Hi Rafael. Thanks, that’s a great point. I do make the point of calling the return a nodeList in the article. In the case of #4 I consciously chose to call it an “array” because I was thinking Vladimir (#3) was new to JS and would probably be confused by the difference between the two. For most beginners the difference doesn’t matter.

    I actually touch on the differences between nodeLists and arrays several times on the site, most recently in this post on getElementsByClassName

  10. Hi,

    Regarding #7:

    I’m having an issue, i’m storing values from an xml file in a javascript variable. Like:


    currentResult.getElementsByTagName("town").item(0).firstChild.nodeValue

    I’m doing this using Ajax, my XML results are created on the fly from the database via a super class. Everything is working fine except where a field in my database contains a null value. FF error console says:


    currentResult.getElementsByTagName("town").item(0).firstChild is null

    I’ve only just started getting into this Ajax thing, and use Javascript very rarely. I’ve tried to handle the null value like so:


    if(currentResult.getElementsByTagName("town").item(0).firstChild.nodeValue == null)
    {

    var town = " ";

    }

    But I still get the javascript error presumably on the conditional statement. It’s hard to track the location as I have several PHP, and Javascript files included.

    Any ideas on handling the Null value?

    Cheers

    Craig

  11. Arh, got it,

    Silly mistake, checking the nodeValue for null, obviously can’t happen because it doesn’t exist:

    if(currentResult.getElementsByTagName(“town”).item(0).firstChild == null)

    Works, Rather than

    if(currentResult.getElementsByTagName(“town”).item(0).firstChild.nodeValue == null)

    Thanks anyway, lol

  12. Craig, you just saved my facebook connect site!

    In most browsers the fb:profile-pic tag is replaced in parseDom by an img tag with the class of fb_profile_pic_rendered. In Safari on Mac I’m getting the image but the class=””. That makes it impossible to reference the image using getElementsByClassName and determine the src of the user thumbnail.

    I switched the code to
    statusImageSrc=document.getElementById("statusDiv").getElementsByTagName("img")[0].src;
    and it works every time.

  13. how to use getElementsByTagName() for remote html. I want to use it in jsp and want to parse the html which is on the same server but different directory

  14. Hi panag,

    You could potentially use an Ajax XMLHTTPRequest to get the other document, then use getElementsByTagName on the node that’s returned.

  15. I was asked to avoid ajax/jquery for this one ( I was planning to use jQuery’s load function) … I have to use plain file IO operation…any suggestion ? … to be specific I have index.html in tomcat WEB-INF/view/jsp/ui forlder and jsp in WEB-INF/view/jsp/include folder. I want to read this index.html and read is and want to embedd this html in jsp and add title under and css where I find “INSER CSS” text

  16. but then how can I seperate part of html ? I want to insert some text in text here and some css where I find in html

  17. Hi, you have script access to the iframe.

    var iframeH1s = document.getElementById(“yourIframeName”).contentDocument.getElementsByTagName(“h1”);

  18. Thank you Rob…this will solve the tag problem but what if I want to parse non tags element like .. I was hoping to use strcmp for this…can we use similar like strcmp in iframes ?

  19. Perhaps it’s worth noting that the Prototype framework has a utility ($A) which accepts an array-like collection like documentGetElementsByTagName() and returns an actual array. If a document is using Prototype, one would want to first convert documentGetElementsByTagName() to an array. To quote from the Prototype doc on $A (a convenience alias of Array.from), “The reason you would want an actual Array is simple: Prototype extends Array to equip it with numerous extra methods, and also mixes in the Enumerable module, which brings in another boatload of nifty methods. Therefore, in Prototype, actual Arrays trump any other collection type you might otherwise get.”

  20. I am 68 y/o and javascript is hard for me to learn but I’m trying. I can tell you KNOW but I can’t always follow what you mean.
    I need to change a page dynamically according to (1 in 13 options) selected. I have 13 arrays of 12 elements (musical semitones) which must repopulate the tag according to that selection. (the 13th option is numerical and I thought by referring to it from original selected key it could serve as a pivot for the transposition, but you could probably obviate this step). I know it would take 2 switches (unless you know of a single procedure that would do it) but I can’t loop through the document and effect the changes. Perhaps having a pivot array to repopulate the innerHTML and changing the contents of that array to clone whichever key array is selected. I have the idea but my skills and practical experience handicap me greatly. I’d appreciate your guidance. This is for a program that would be implemented in singalongs for institutions for the elderly and is a not-for-profit project.

  21. I’m sorry i neglected to mention that the first thing I need to do is loop thhrough all the tagged elements (which contain the name of the note -A, C, Db, whatever-) and converting them to the index of the selected array. That’s where the numeral array came to mind. The second step is swapping the new selected array into the looped data. Thanks again!

  22. I have a small working example that only reefers to 1 array (alternate musical key), but I haven’t found a way to construct a loop for the tag list that will convert the text to index of the original selected key and the back to the same index of the new key. I have gone through books and spent weeks tryings things out but my knowledge is limited so i’m frustrated.
    I’m sorry if I can’t explain it any better and am very thankful for your interest!

    Select a key and click the button:

    C
    Db
    D
    Eb
    E
    F</option
    Gb
    G
    Ab
    A
    Bb
    B

    Display index

    var Dsteps = new Array(“D”, “D#”, “E”, “F”, “F#”, “G”, “G#”, “A”, “Bb”, “B”, “C”, “C#”);

    function keySelect()
    {
    var x = document.getElementById(“keySelect”).selectedIndex;
    var y = document.getElementById(“keySelect”).options;
    //alert(“Index: ” + y[x].index + ” is ” + y[x].text);
    var selKey=(y[x].text);
    alert(selKey);
    }

    function myFunction()
    {
    var list=document.getElementsByTagName(“p”)[0]
    list.getElementsByTagName(“step”)[0].innerHTML=Dsteps[9];
    list.getElementsByTagName(“step”)[1].innerHTML=Dsteps[11];
    }

    G///CDEF

    Click the button to change the text of a list item.

    Try it

  23. Hi Rob, I’ve put together a few things on this page that hopefully you’ll find the patience to wade through the confusion and throw some light into.

    Your interest and rare solidarity with plodders like me is immensely appreciated!

    Ed

Leave a Reply

Your email address will not be published. Required fields are marked *