views:

959

answers:

3

I would like to know how I can refer to a list item object if I had for example the following html list

<div id="subdiv_2">  
 <div id="subdiv_3">  
  <ul>  
   <li><a href="">Item1</a></li>  
   <li><a href="">Item2</a></li>  
   <li><a href="">Item3</a></li>    
  </ul>  
 </div>  
</div>

How is it possible to register an onclick to the Item2 li without it having to have a unique elementId eg I can do so for subdiv_3 because it has a unique ID and isn't in the list by

document.getElementById('subdiv_3').addEventListener('click', function();, false);

My goal is ultimately to assign a function to each list object, for the number of list objects with unique parameters based upon the list object number eg:

for(i=0;i<list.length;i++){  
 "document.getElementById(list.item"+i+").addEventListener(\'click\',function("+i+");,false);";  
}

This question has been Answered! Thank you

+2  A: 

You could get all the children elements of subdiv_3 that are <li>. Then iterate through that loop adding the functions as you go.

div = document.getElementById('subdiv_3');
els = div.getElementsByTagName('li');

for (var i=0, len=els.length; i<len; i++) {
    alert(i);  // add your functions here   
}

Looking at your code sample, when you're in the loop creating your functions you may run into closure scoping problems. (All the functions will appear to use the same value of i.) Check out my answer to this question to deal with that problem: http://stackoverflow.com/questions/315712/how-to-add-event-handler-with-arguments-to-an-array-of-elements-in-javascript

Benry
Perfect! Thank you :) If Stackoverflow let me upvote I would :)
Supernovah
A: 

In reponse to the comment on Benry's Answer By Benry, After using his code, the following proves that each elementLi can be referred to with els[i]

function attachToList(){
div = document.getElementById('menu2');
els = div.getElementsByTagName('li');
for (var i=0, len=els.length; i<len; i++) {
setTimeout('els['+i+'].style.backgroundColor=\"#FFFFCC\";',(250*i));
}
}
Supernovah
+1  A: 

@Supernovah: You can actually assign a real function to setTimeot(). That rids you of the string formatting, which will stand in your way when you want to do more complex things than just setting one property.

This is the code:

function attachToList() {
  var div = document.getElementById('menu2');
  var els = div.getElementsByTagName('li');
  // create a closure returning an anonymous inner function
  var fn  = function(li) {
    return function() {
      li.style.backgroundColor = "#FFFFCC";
    };
  };
  for (var i=0, len=els.length; i<len; i++) {
    // create function instance suitable for current iteration
    var changeLi = fn(els[i]);
    // pass function reference to setTimeout()
    setTimeout(changeLi, 250*i);
  }
}

And a short explanation:

Using a closure is the trick that makes sure when setTimeout() triggers, all variables still have the expected values.

You do this by writing a function that returns a function. The outer function takes parameters, the inner function does not. But it refers to the parameters of the outer function. In the loop, you call the outer function (with correct parameters) and get a whole new inner function every time, each which has it's own version of the parameter values. This is the one you assign to setTimeout().

Tomalak
Thanks for this, I also understood this from Benry's other post.
Supernovah
Also I think the use of return function()... is causing an closure problem with passing the variable down the chain. Without nesting that function, instead just in it's parent, your idea works fine.
Supernovah