-2

Following my code:

for(var i =0; i < document.getElementById('test').getElementsByTagName("li").length; i++){                                  
    document.getElementById('test').getElementsByTagName("li")[i].onmouseover= function(){
    alert(document.getElementById('test').getElementsByTagName("li")[i].innerHTML);
    }
}

HTML:

<div id="test">
    <ul><li>test</li><li>test2</li><li>test3</li><li>test4</li></ul>
</div>

JSfiddle: http://jsfiddle.net/Pwddf/1/

"i" is always assigned the last value and then does not work. How to solve?

user2992868
  • 157
  • 1
  • 1
  • 5

5 Answers5

3

The problem is scoping. If you create a function inside of a loop, the loop variables will always have their last loop values. Basically, the loop executes, but the variables inside the function declaration are not evaluated until the function is called, at which point "i" is equal to the last value. You can use a closure to make the vars resolve immediately.

for(var i =0; i < document.getElementById('test').getElementsByTagName("li").length; i++){
    (function(i) {                                  
        document.getElementById('test').getElementsByTagName("li")[i].onmouseover= function(){
            alert(document.getElementById('test').getElementsByTagName("li")[i].innerHTML);
        };
    })(i);
}

I also agree with tymeJV that you should store your elements first, rather than reselecting them.

tandrewnichols
  • 3,456
  • 1
  • 28
  • 33
  • Sorry, I was in a hurry. A closure causes the function to execute immeidately, so it needs to be OUTSIDE the assignment, otherwise, the alert fires immediately. – tandrewnichols Nov 21 '13 at 18:29
2

Looks like you want querySelectorAll instead:

var elems = document.querySelectorAll("#test ul li");
for (var i = 0; i < elems.length; i++) {
    elems[i].onmouseover = function() {
        console.log("See?");
    }
}

If you actually need that i value, use a closure inside the for:

(function(i) {
    elems[i].onmouseover = function() {
        console.log("See?" + i);
    }
})(i)

Demo: http://jsfiddle.net/Pwddf/2/

tymeJV
  • 103,943
  • 14
  • 161
  • 157
1

Here is a very concise solution that works in jsfiddle inside Firefox and IE9:

var elems = document.getElementById("test").getElementsByTagName("li");
for(var i =0; i < elems.length; i++){
    elems[i].onmouseover= function(e){
       console.log(this.innerHTML);
       console.log(e);
    }
}

http://jsfiddle.net/8LyhN/1/

Not knowing what all you are planning to do inside your mouseover event, I recommend passing in the event so you can reference it as 'e'.

David Fleeman
  • 2,588
  • 14
  • 17
0

You need to cache i;

    for(var i =0; i < document.getElementById('test').getElementsByTagName("li").length; i++)
    {   
       var _i = i;                            
        document.getElementById('test').getElementsByTagName("li")[i].onmouseover= function()
        {

        alert(document.getElementById('test').getElementsByTagName("li")[_i].innerHTML);
        }
    }

// Even better;

var elements = document.getElementById('test').getElementsByTagName("li");
for(var i =0; i < elements.length; i++)
{                                  
    elements[i].addEventListener('mouseover', function()
    {
    alert(this.innerHTML);
    });
}
Erik Simonic
  • 457
  • 3
  • 13
  • The first trick won't work; the local variable in the function is still accessing the shared "i" from the enclosing scope. – Pointy Nov 21 '13 at 18:23
  • You are right.. I should put the var _i = i; outside the event listener. – Erik Simonic Nov 21 '13 at 18:28
  • Well check the closure code in the other answers - JavaScript scope doesn't work like scope in other languages. – Pointy Nov 21 '13 at 18:30
0

You should do like this if you really want to use javascript than JQuery.

var ul = document.getElementById("test");
var li = ul.getElementsByTagName("li");

for(var i =0; i <li.length; i++){                                   
    li[i].onmouseover= function(){
        alert(this.innerHTML);
    }
}

check here : http://jsfiddle.net/alaminopu/Pwddf/5/

Md. Al-Amin
  • 1,423
  • 1
  • 13
  • 26