-1

Please help me fix this code

HTML

<p class="imgclass">Test1</p>
<p class="imgclass">Test2</p>
<p class="imgclass">Test3</p>

JavaScript

imgclassElements = document.getElementsByClassName('imgclass');
for (var i = 0; i < imgclassElements.length; i++){
    imgclassElements[i].onmouseover=function(){alert(i);};
}

In browser onmouseover elements with class .imgclass appear alertbox only with text "3". How fix this? I want to pop-up alert window with values appropriate .imgclass elements order.

Jonathan Drapeau
  • 2,610
  • 2
  • 26
  • 32
  • 2
    Hi Ivan. You've asked a very, very common JavaScript question, but unless you know the magic phrase 'Closure', it is very difficult to find the answer. – Jeremy J Starcher Aug 15 '14 at 12:11
  • @J.J.Starcher if he new what the word closure meant he would not be pitching his question: our job is to know he needs a closure, show him one and explain it, not slap him on the head. – MartinWebb Aug 15 '14 at 12:25
  • @MartinWebb I don't see any head-slapping here. I think Jeremy did a good job mentioning the word "closure" here and providing the answer by linking to the appropriate question. – dirkk Aug 15 '14 at 12:53
  • 1
    @dirkk: fair enough point made. I think we are all here to help. – MartinWebb Aug 15 '14 at 12:59

4 Answers4

1

This is the simplest way to do it, you can use a closure but I'll keep it simple. Also you can access the element and apply styles, or get info from it in the click handler

FIDDLE http://jsfiddle.net/bz7a2vf5/1/

HTML

<p id="item1" class="imgclass">Test1</p>
<p id="item2" class="imgclass">Test2</p>
<p id="item3" class="imgclass">Test3</p>

JS

imgclassElements = document.getElementsByClassName('imgclass');
for (var i = 0; i < imgclassElements.length; i++) {
    click(i);
}

function click(i){
       imgclassElements[i].onmouseover = function (e) {

       // you can also get the element from e.target
       alert(i);
       alert(e.target.id);
    };
}
MartinWebb
  • 1,998
  • 1
  • 13
  • 15
0

This may not be the most elegant way, but

imgclassElements[i].addEventListener('mouseover',function(j){return function(){alert(j);};}(i));

should do it.

That said, you should really read up on JS closures as suggested in the comments to your question.

icke
  • 1,568
  • 1
  • 19
  • 31
0

That problem is occurring because of the time alert is being called, value of i is incremented to 3 that's why it's giving 3 every time.

Try to bind a function with the current value of i like bellow

imgclassElements = document.getElementsByClassName('imgclass');
  var printVal = function(i){
    return function(){
        alert(i);
    };
  }
  for (var i = 0; i < imgclassElements.length; i++){
    imgclassElements[i].onmouseover = printVal(i)
  } 

There can be better solutions also.

Mritunjay
  • 25,338
  • 7
  • 55
  • 68
0

The easiest way is to extract the content of your loop in a function

function handleElement(element, i) {
    element.onmouseover=function(){alert(i);};
};
for (var i = 0; i < imgclassElements.length; i++){
    handleElement(imgclassElements[i], i);
}

Or you can use forEach (Sadly it's a HTMLCollection and not an Array, so it's a bit difficult)

Array.prototype.forEach.call(imgclassElements, function(element, i) {
    element.onmouseover=function(){alert(i);};
});

Or give the index as an argument

for (var i = 0; i < imgclassElements.length; i++){
    imgclassElements[i].onmouseover=(function(i){alert(i);}).bind(null, i);
}

And always a good thing to learn about closures

Volune
  • 4,324
  • 22
  • 23