childNodeByID function for Web Extensibility

During the Web Extensibility talk at HP Software Universe, somebody asked me to post the code for childNodeByID. This is a javascript function that is useful in Web Extensibility projects. It lets you find the child of a DOM object that has a specific id attribute.

At the time, I said this function was only a few lines long. I was wrong. Somebody with more javascript experience could probably golf this down to a few lines, but my version is pretty long.

JavaScript:
  1. /// <summary>
  2. /// Find a DOM element's child node that matches a given string.
  3. /// </summary>
  4. /// <param name="currentElement" type="HTMLHtmlElement">DOM Element to traverse</param>
  5. /// <param name="sID" type="String">html id we're looking for</param>
  6. /// <returns type="HTMLHtmlElement">The matching html element</returns>
  7. function childNodeByID(currentElement, sID)
  8. {
  9.   if (currentElement)
  10.   {
  11.     var result = null;
  12.     if (currentElement.id == sID)
  13.     {
  14.       result = currentElement;
  15.     }
  16.     else
  17.     {
  18.         // Traverse the tree
  19.         var i=0;
  20.         var currentElementChild=currentElement.childNodes[i];
  21.         while (currentElementChild)
  22.         {
  23.           // Recursively traverse the tree structure of the child node
  24.           result = childNodeByID(currentElementChild, sID);
  25.           if (result) break;
  26.           i++;
  27.           currentElementChild=currentElement.childNodes[i];
  28.         }
  29.     }
  30.     return result;
  31.   }
  32. }

I found the meat of this function at permadi.com and modified it for my own use.

Tags: , , , , , ,

2 Comments for “childNodeByID function for Web Extensibility”

  1. johan Says:

    How about..

    function childNodeByID(currentElement, sID)
    {
    if (!currentElement) return null;
    if (currentElement.id == sID) return currentElement;
    for(var i=0; i<currentElement.childNodes.lenght; i++) {
    var node = childNodeByID(currentElement.childNodes[i], sID);
    if (node) return node;
    }
    return null;
    }

    Reply to johan

  2. Motti Says:

    First off all you should use “all” instead of “children” this simplifies matters since there’s no recursion (recursion is cool but it does have some overhead).

    You can also pass a parameter to the “all” function, the problem is that this searches both the “id” and “name” property, if you know that there will be no clash you can simplify things to ‘elem.all(”id”)’.

    I have approximately zero experience with JavaScript so I don’t know if the way I distinguish between elements and collections is the idiomatic way (but it works).

    function elemById(root, id)
    {
    var found = root.all(id);
    if (found.tagName) // found is an element
    return found;
    // More than one match, found is a collection
    for (var i = 0; i < found.length; ++i)
    if (found[i].id == id)
    return found[i];
    }

    You may want to add this at the beginning of the function if you want the semantics of the original post.
    if (root.id == id)
    return root;

    Reply to Motti

Leave a Reply