4

My code is...

How do I get the text in each list item into an array using native javascript?

<ul id="list">
    <li>List Item 1</li>
    <li>List Item 2</li>
    <li>List Item 3</li>
    <li>List Item 4</li>
</ul>

<script type="text/javascript">
var list = document.getElementById('list').childNodes.TextNode;
for(var i=0;i < list.length; i++) {
    var arrValue = list[i];
    alert(arrValue);
}
</script>

Many thanks.

Gumbo
  • 643,351
  • 109
  • 780
  • 844

5 Answers5

4

Unless you want the text-nodes between each <li> it's not a good idea to use childNodes. What's wrong with getElementsByTagName('li')?

var listItems = document.getElementById('list').getElementsByTagName('li'),

    myArray = map(listItems, getText);

function map(arrayLike, fn) {
    var ret = [], i = -1, len = arrayLike.length;
    while (++i < len) ret[i] = fn(arrayLike[i]);
    return ret;
}

function getText(node) {
    if (node.nodeType === 3) return node.data;
    var txt = '';
    if (node = node.firstChild) do {
        txt += getText(node);
    } while (node = node.nextSibling);
    return txt;
}
James
  • 109,676
  • 31
  • 162
  • 175
  • best so far, though nested lists would be a problem if any existed, as `getElementsByTagName` is of course hierarchical. Why not just `map(listItems, getText)`, though? – bobince May 08 '10 at 11:11
  • @bibince, changed to `map(listItems, getText)`. Thanks! – James May 08 '10 at 11:16
1

Try this:

var list = document.getElementById('list').childNodes;
var theArray = [];
for(var i=0;i < list.length; i++) {
    var arrValue = list[i].innerHTML;
    alert(arrValue);
    theArray.push(arrValue);
}
nickf
  • 537,072
  • 198
  • 649
  • 721
  • `childNodes` contains whitespace Text nodes, for which `innerHTML` is not defined. `innerHTML` will return escaped characters for some text. – bobince May 08 '10 at 11:07
1
var LIs = document.getElementById('list').childNodes;
var list = [];
for( var i = 0; i < LIs.length; ++i )
{
    var LI = LIs[i];
    list.push(LI.innerText || LI.textContent);
}

And as always, the simpler way using jQuery:

var list = $('#list li').map(function(){ return $(this).text(); });
Vincent Robert
  • 35,564
  • 14
  • 82
  • 119
  • `childNodes` contains whitespace Text nodes that are unwanted in the list (and for which `innerText` is not defined). `||` test fails for empty-string `innerText`, leaving IE to put `undefined` in array. – bobince May 08 '10 at 11:14
  • 1
    With jQuery it's *even* simpler: `var list = $('#list li').map(function(){return $.text([this])});` – James May 08 '10 at 16:41
1

Just about any Javascript library (Prototype, jQuery, Closure, ...) will make this easier, but if you want to do it yourself:

You're close, your Javascript should look something like this:

window.onload = onPageLoad; // Or any of several other similar mechanisms
                            // (you could just run it at the bottom of the page)
function onPageLoad() {
    var node, list, arrValue;

    list = [];
    for (node = document.getElementById('list').firstChild;
        node;
        node = node.nextSibling) {
        if (node.nodeType == 1 && node.tagName == 'LI') {
            list.push(node.innerHTML);
        }
    }

    // `list` now contains the HTML of each LI element under the `ul#list` element
}

Explanation:

  • Before using document.getElementById, you need to be sure that the DOM is ready for you to do that. It's definitely ready at onload time, and there are various mechanisms for triggering your code a bit earlier than that if you like (including putting the script right at the end).
  • The loop starts by getting the ul#list element's first child, then continues as long as there are further siblings.
  • In the loop, we check that each node is an Element (nodeType == 1) and that its tag name is "LI".
  • If it is, we retrieve its HTML and push it on the array.

I've used innerHTML to retrieve the content of the LIs because it's widely supported. Alternately, you could use innerText on IE (and some others) and textContent on Firefox, but beware that they don't do quite the same thing (textContent on Firefox will include the contents of script tags, for instance, which probably isn't what you want).

James
  • 109,676
  • 31
  • 162
  • 175
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • @J-P: That's certainly an option; it's a loop either way, using `getElementsByTagName` requires a second function call and creation of a NodeList, which seems unnecesary if you're going to loop anyway. (Is that your downvote? If so, seems a bit harsh just for going a different way...) – T.J. Crowder May 08 '10 at 10:43
0

var list = document.getElementsByTagName('ul')[0].getElementsByTagName('li');

var theArray = [];

for (var i = 0; i < list.length; i++) {
    var arrValue = list[i].innerHTML;
    console.log(arrValue);
    theArray.push(arrValue);
}
pixel 67
  • 1,530
  • 18
  • 22