ObiHill
ObiHill

Reputation: 11886

Retrieving an element nested within another element using id

I have the following code which simply parses HTML markup to a DOM object.

var html_str = '<div id="body-wrapper">\
        <div id="container-1">\
            <p>This is the first container - Line 1</p>\
            <p>This is the first container - Line 2</p>\
            <p><img src="assets/img/pull_1.jpg"></p>\
        </div>\
        <div id="container-2">\
            <p>This is the second container - Line 1</p>\
            <p>This is the second container - Line 2</p>\
            <p>This is the second container - Line 3</p>\
            <p><img src="assets/img/pull_2.jpg"></p>\
        </div>\
        <div id="container-3">\
            <p>Test</p>\
            <p><img src="assets/img/pull_3.jpg"></p>\
        </div>\
    </div>';

var elem_obj = document.createElement("div");
elem_obj.innerHTML = html_str;

How do I get the element with id == container-1 from within elem_obj? Vanilla JavaScript only and something other than elem_obj.querySelector('#container-1') because I need to support IE below version 8.

Thanks.

Upvotes: 2

Views: 1422

Answers (2)

Amadan
Amadan

Reputation: 198438

As I said in comments, apologies for arguing vehemently on incomplete data. While it is true old IE could use getElementById in DocumentFragment, it is not generally true for newer browsers, so a hybrid strategy is needed for best compatibility.

var html = '<div id="body-wrapper">\
  <div id="container-1">\
    <p>This is the first container - Line 1</p>\
    <p>This is the first container - Line 2</p>\
    <p><img src="#"></p>\
  </div>\
  <div id="container-2">\
    <p>This is the second container - Line 1</p>\
    <p>This is the second container - Line 2</p>\
    <p>This is the second container - Line 3</p>\
    <p><img src="#"></p>\
  </div>\
    <div id="container-3">\
    <p>Test</p>\
    <p><img src="#"></p>\
  </div>\
</div>';


// from http://stackoverflow.com/a/1643512/240443
function getElementByIdFromNode(node, id) {
  for (var i = 0; i < node.childNodes.length; i++) {
    var child = node.childNodes[i];
    if (child.nodeType !== 1) // ELEMENT_NODE
      continue;
    if (child.id === id)
      return child;
    child = getElementByIdFromNode(child, id);
    if (child !== null)
      return child;
  }
  return null;
}
// based on http://stackoverflow.com/a/1643383/240443
function getElementByIdFromString(html, id) {
  var div = document.createElement("div");
  div.innerHTML = html;
  // New browsers
  if (div.querySelector) {
    return div.querySelector("#" + id);
  }
  // Old IE
  var frag = document.createDocumentFragment();
  if (frag.getElementById) {
    frag.appendChild(div);
    return frag.getElementById(id);
  }
  // Anything else just in case
  return getElementByIdFromNode(div, id);
}
var container3 = getElementByIdFromString(html, "container-3");
console.log(container3);

Upvotes: 2

Sebastian Simon
Sebastian Simon

Reputation: 19505

Proposed solution (alternative to DocumentFragment): you could search for the desired element with a loop.

JSFiddle (look at Console output).

The loop looks like this:

var elem_obj_containers = elem_obj.children[0].children;
  // All <div>s with those “container-” IDs

var container1_element=null; // The result or null

for(var i=0;i<=elem_obj_containers.length;i++){
    if(elem_obj_containers[i].id=='container-1'){ // Checking for ID
        container1_element=elem_obj_containers[i]; // Assigning result
        console.log(elem_obj_containers[i]); // Verify result
        break; // Show’s over!
    }
}

So if the ID is found, the element is assigned to container1_element, otherwise the variable remains null (like the real document.getElementById).

It should work all the way back to IE6 as of MDN’s page for children. IE 6, 7 and 8 just include HTML comment nodes in children as well. This shouldn’t be a big deal.

Upvotes: 1

Related Questions