0

Possible Duplicate:
Event handlers inside a Javascript loop - need a closure?

I want to simply assign onclick events to a series of li elements within an unordered list. Instead of doing it the messy way by either defining lots of unique IDs and manually adding the events to each li element I'd like to do it programatically with a for loop.

html:

<ul id="homeNav">
    <li><a title="Back to home page" href="">home</a></li>
    <li><a title="Play" href="">play</a></li>
    <li><a title="About the site?" href="">about</a></li>
    <li><a title="Latest development news and info." href="">dev blog</a></li>
    <div class="clear"></div>
</ul>

Javascript:

window.onload = function()
{
    var parentList = document.getElementById('homeNav');
    var listItems = parentList.getElementsByTagName('li');
    var numItems = listItems.length;
    for(var i = 0; i < numItems; i++)
    {
        listItems[i].onmouseover = function()
        {
            listItems[i].getElementsByTagName('a')[0].style.color = 'blue';
        }
        listItems[i].onmouseout = function()
        {
            listItems[i].getElementsByTagName('a')[0].style.color = '#cccccc';
        }
    }
}

I get the error listItems[i] is undefined

To me it looks like the event is literally looking for the i index variable instead of using the number assigned to it at the time of the event being added to the trigger, or maybe the i variable isn't within the closures' scope?

Community
  • 1
  • 1
Lee
  • 3,869
  • 12
  • 45
  • 65

3 Answers3

4

The variable is not avilable in the event, you can use this..

for(var i = 0; i < numItems; i++)
{
    listItems[i].onmouseover = function()
    {
        this.getElementsByTagName('a')[0].style.color = 'blue';
    }
    listItems[i].onmouseout = function()
    {
        this.getElementsByTagName('a')[0].style.color = '#cccccc';
    }
}
Rajat Singhal
  • 11,234
  • 5
  • 38
  • 56
  • Excellent. Thank you. Works perfectly. I would have expected the JS interpreter to associate it with the `this` equivalent. – Lee Sep 25 '12 at 19:08
0

I'm not sure, but i would think & check

var listItems = parentList.getElementsByTagName('li');
listItems[i]

... I'm not sure that you're doing it 2) do a console.log (listItems) to see what's it, and remember about array - object difference. that's all for now, have to go... sorry for the brief answer, hope it helps.

Elmor
  • 4,775
  • 6
  • 38
  • 70
0

there is problem in your code. on mouseover or mouseout value of i would be equal to numItems; as these events will get called after finish of for loop. so you should save context.

function bindEvent(elem){

            elem.onmouseover = function()
            {
               elem.getElementsByTagName('a')[0].style.color = 'blue';
            }
            elem.onmouseout = function()
            {
               elem.getElementsByTagName('a')[0].style.color = '#cccccc';
            }
}

    window.onload = function()
    {
        var parentList = document.getElementById('homeNav');
        var listItems = parentList.getElementsByTagName('li');
        var numItems = listItems.length;
        for(var i = 0; i < numItems; i++)
        {
          bindEvent(listItems[i]);

        }
    }
Anoop
  • 23,044
  • 10
  • 62
  • 76
  • Are you sure? It works exactly as intended with a simple change from `listItems[i]` to `this` – Lee Sep 25 '12 at 19:12
  • using this is better. but if you want to save index of item then above will help you. both answers are correct. – Anoop Sep 25 '12 at 19:14