views:

1333

answers:

7

How can I refer to a nested div by id when it has the same id as a div nested in a similarly named div

eg

<div id="obj1">
    <div id="Meta">
        <meta></meta>
    </div>
</div>

<div id="obj2">
    <div id="Meta">
        <meta></meta>
    </div>
</div>

I want to get the innerHTML of meta

document.getElementById('obj1').getElementById('Meta').getElementsByTagName('meta')

doesn't work

+9  A: 

Id is supposed to be unique.

John Ellinwood
interesting point /= I guess seeing as it's already been programmed with the named Id's I'm kind of stuck to go and change them
Supernovah
yeah, you're kind of screwed unless you can change that.
bigmattyh
+14  A: 

IDs should only be used when there is one of that item on the page, be it a SPAN, DIV or whatever. CLASS is what you should use for when you may have a repeating element.

Code there doesn't work because you're referring to an element by unique ID, but have more than one on the page.

random
+4  A: 

You may also run into problems with this markup because the "meta" tag is only legal inside the head tag, not the body tag. As far as I can tell from looking at Firebug, Firefox will even go so far as to pull those meta tags out of the body and toss them into the head (and, in this case, put any text content inside the parent div), so you won't see them in the DOM at all.

Greg Campbell
+2  A: 

As the id attribute is a unique document-wide identifier, you should probably namespace your ids.

<div id="obj1">
    <div id="obj1_Meta">
        <meta></meta>
    </div>
</div>

<div id="obj2">
    <div id="obj2_Meta">
        <meta></meta>
    </div>
</div>

document.getElementById('obj1_Meta').getElementsByTagName('meta')
rjh
+3  A: 

For the HTML you've given, this should work:

document.getElementById('obj1').getElementsByTagName('div')[0].getElementsByTagName('meta');

Just ignore the bogus id on the inner div and get it by tag name. You should also be able to ignore the inner div completely, since getElementsByTagName searches the entire subtree:

document.getElementById('obj1').getElementsByTagName('meta');
Jason DeFontes
this will not work due to there being an unknown number of div's in the obj1 as well as the given Meta one
Supernovah
in that case you could still search through all the divs (recursively, even) until you find the <meta> tag you want. Since you can't change the HTML, you have to get creative with the DOM :)
rjh
You should still be able to look for the id "Meta" by looping through the child divs. You can't use getElementById because your html is invalid, but I'm guessing the div elements will still have their id values set.
Jason DeFontes
+2  A: 

Hate to point out the obvious, but in your example, obj1_Meta and obj2_Meta are unique id's, so if it's the case in your working code:

document.getElementById('obj1_Meta').getElementsByTagName('meta')[0].innerHTML;

would work as described. As a double check, did you over think this?

If not, bummer...

As "bad" or "wrong" as your code is, an option that will work is to use a JavaScript framework like jQuery. Once you've included it, you can get elements by passing it a CSS selector (even a semantically incorrect one) like so:

$('#obj1 #obj1_Meta meta').html()

$() is jQuery's way of saying document.getElementById() ...on steroids. .html() is its equivalent of .innerHTML

Other frameworks, like PrototypeJS and MooTools also provide similar functionality.

Prototype for example:

$$('#obj1 #obj1_Meta meta').innerHTML;//note the double $'s

Frameworks save lots of time and trouble with regard to browser compatibility, "missing" JavaScript methods (like getElementsByClassName) and coding AJAX quickly. These things make them a good idea to use to anyway.

sudopeople
+2  A: 

IDs are meant to be unique, use classes intelligently.

<div id="obj1" class="obj">
    <div id="obj1_Meta" class="obj_Meta">
        <meta></meta>
    </div>
</div>

<div id="obj2" class="obj">
    <div id="obj2_Meta" class="obj_Meta">
        <meta></meta>
    </div>
</div>
  • .obj = targets both elements
  • #obj1.obj = targets only the first
  • #obj1.obj_Meta = targets obj1 inner DIV
  • #obj2.obj = targets only the second
  • #obj2.obj_Meta = targets obj2 inner DIV
Nimbuz