views:

48

answers:

2

Hi all

I have a bunch of HTML list items and what i want is to be able to read the text of a list item and then be able to give the user the ability to modify it. the structure of each list item is the same:

<li id='1' class='attachment'>
    <a href='link.html'>TEXT VALUE I WANT TO READ AND MODIFY</a>
    <a href='link2.html'><img src'img1.jpg'></a>
    <a href='link3.html'><img src'img2.jpg'></a>
</li>

at the moment i am able to get the list item using

li = document.getElementById(id);

but if i get it to print out something like

li.childNodes[?] 
li.childNodes[?].data
li.childNodes[?].nodeValue etc...

i am never able to get it to print "TEXT VALUE I WANT TO READ AND MODIFY", it always gives null, undefined or [object Text] or something similar. any help would be greatly appreciated.

+2  A: 

What about this:

var li = document.getElementById(1);
var a = li.getElementsByTagName('a');

alert(a[0].innerHTML);

And before anyone can suggest to just use jQuery, here's the equivalent:

$('li#someid a').html();

In my opinion, if you're doing fine without jQuery, don't use it.

Tatu Ulmanen
You shouldn't use *innerHTML* or *html()* to get the text value of an element. Both will return html encoded characters such as ` `, `>`, `<`, etc.
Andy E
@Andy E, that is true, it's just a bad habit I have as I have never run into any problems when using innerHTML/html().
Tatu Ulmanen
+1  A: 

You need to get the textContent or innerText properties:

var li = document.getElementById(id);
var t = "textContent" in li.childNodes[0] ? "textContent" : "innerText";
alert(li.childNodes[0][t]);

innerText is implemented by IE and textContent is implemented by standards compliant browsers.

Alternatively, if you're certain that the element's first child will be a text node, you can use

alert(li.childNodes[0].childNodes[0].nodeValue);


Based on your comment below, we can make a safe assumption that white-space is interfering with the childNodes property in your example. This is normal - childNodes returns both elements and text nodes that are direct descendants of the given element. The alternative is to use children in newer browsers:

// 1st example using `children` instead
var li = document.getElementById(id);
var t = "textContent" in li ? "textContent" : "innerText";
alert(li.children[0][t]);

// 2nd example using `children` instead
alert(li.children[0].childNodes[0].nodeValue);

children isn't supported pre Firefox 3.5 and in other older browsers. You could use li.getElementsByTagName("a") for the example that you've posted - but bear in mind that it will return all <a> element descendants, not just immediate children.

Andy E
i like either of your suggestions but for some reason it still does not work. if i create a loop and print out all childnodes i get 0=>[object Text] 1=>link.html 2=>[object Text] 3=>link2.html 4=>[object Text] 5=>link3.html 6=>[object Text]. i think the text i am looking for is in 2, however if i then print out everything in 2 i get 20 elements each being undefined. any ideas?
Mitch
@Mitch: ah, you've run into the famous "white-space = TextNode" issue with *childNodes*. I've updated my answer with a solution.
Andy E
awesome! it works! thx very much, this was driving me nuts!
Mitch