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?

4
  • I'd rather not use jQuery. I'd like to be comfortably proficient with Javascript before I dabble in JS libraries and frameworks. Commented Sep 25, 2012 at 19:05
  • I just created this JSFiddle and it seems to work fine. Commented Sep 25, 2012 at 19:06
  • @Pheonixblade9 because this function will never be called. Commented Sep 25, 2012 at 19:09
  • @IgorShastin gotcha, I just never experienced the error Commented Sep 25, 2012 at 19:17

3 Answers 3

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';
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Excellent. Thank you. Works perfectly. I would have expected the JS interpreter to associate it with the this equivalent.
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.

Comments

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]);

        }
    }

2 Comments

Are you sure? It works exactly as intended with a simple change from listItems[i] to this
using this is better. but if you want to save index of item then above will help you. both answers are correct.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.