Is identifying the index of a list item the best approach?

I need to select list items from a list and then perform operations such as adding event handlers to them. I can think of two ways to do this.

HTML:

    <ul id="list">
       <li id="listItem-0"> first item </li>
       <li id="listItem-1"> second item </li> 
       <li id="listItem-2"> third item </li> 
    </ul>

      

  • Using identifiers -

    for(i=0;i<3;i++)
    {
       document.getElementById("listItem-"+i).addEventListener("click",foo,false);
    }
    
          

  • Using the childNodes property -

    for(i=0;i<3;i++)
    {
      document.getElementById("list").childNodes[i]
         .addEventListener("click",foo,false);
    }
    
          

The reason I use the first approach is because in the foo function, if I want the index at which the item is in the list, I can do so by splitting the id -

    function foo()
    {
      tempArr = this.id.split('-');      
      index = tempArr[tempArr.length-1]; // the last element in the array
    }

      

I cannot think of a way to do this using the second method, i.e. without using an ID naming scheme.

Questions:

  • How do I get the index using the second method or any better method.
  • Are there any very bad consequences after the first method?
0


source to share


4 answers


You can avoid adding event handlers to each list item by adding one event handler to the containing item (unordered list) and using the concept of an event bubble. In this single event handler, you can use the properties of the event object to determine what was clicked.

It seems like you want to display data in an array to display items. If parsing the array index from the list item id would work, another approach would be to store the "key" value in the list item as an extension and use the properties of the javascript object to find your data.

Partial example:



<li key="myKey">

//oData is a object (eg. var oData = {};) that has been populated with properties
//whose value is the desired data (eg. oData["myKey"] = 123;)

alert(oData[event.srcElement.key]); // alerts 123

      

Regarding the bad effects of the first method you showed, one bad effect is that with many list items, you end up with many event handlers that will affect performance at some point.

Also note that you can inadvertently create a global var in your loops by omitting the var keyword for "i".

+3


source


If you choose to use jQuery it will be as simple as:



$('ul#list li').click(function () {
    var i = this.id.split('-').pop();
    alert( i );
});

      

+1


source


Perhaps something similar to:

var lis = document.getElementById("list").getElementsByTagName("li");

for (var i = 0, li; li = lis[i]; ++i) {
  li.addEventListener("click", (function(pos) {
    return function() {
      alert(pos);
    };
  })(i), false);
}

      

Or, with some inspiration from J cs's answer and custom data attributes :

var lis = document.getElementById("list").getElementsByTagName("li");

for (var i = 0, li; li = lis[i]; ++i) {
  li.setAttribute("data-index", i); // Or whatever value you want...
  li.addEventListener("click", function() {
    alert(this.getAttribute("data-index"));
 }, false);
}

      

+1


source


As stated above, if you want to get a list of li you have to use getElementsByTagName for your ul because childNodes can fetch some text nodes as well as li nodes.

Now, if you need to use the index in an event handler, you might be better off using the closure directly to reuse the loop variable inside the event handler.

var lis = document.getElementById("list").getElementsByTagName("li");

for( var i = 0, l = lis.length; i < l; ++i )
{
    (function(){

        // As a new variable will be created for each loop, 
        // you can use it in your event handler  
        var li = lis[i]; 

        li.addEventListener("click", function() 
        {
            li.className = "clicked";

        }, false);

    })();
}

      

But you might consider event delegation for this purpose. You only need to bind an event handler to the parent element and find the clicked element using the target attribute.

document.getElementById("list").addEventListener("click", function(event)
{
    var li = event.target;
    if( li.nodeName.toLowerCase() == "li" )
    {
        ...
    }
}, false);

      

0


source







All Articles