0

i hve been trying to add the click event to the particular div created . which was successful ,my problem is when clicked it shows me undefined.

here is the code

resulta is a global variable (array with objects)

for(s = 0;s<resulta.length;s++)
    {
        y = document.createElement('div')
        y.setAttribute('class', 'eachssd');
        var x = document.createTextNode(resulta[s].name)
        y.appendChild(x);
        o.appendChild(y)
        y.addEventListener('click',function bnmhv(){location.href=resulta[s].datasrc},false)
    }

thanks in advance

  • What if you changed `y.addEventListener('click',function bnmhv(){location.href=resulta[s].datasrc},false)` to `y.addEventListener('click',function(){location.href=resulta[s].datasrc},false)` leaving the `bnmhv` out. – dbf May 16 '15 at 23:21
  • possible duplicate of [Event handlers inside a Javascript loop - need a closure?](http://stackoverflow.com/questions/341723/event-handlers-inside-a-javascript-loop-need-a-closure) – Patrick Evans May 16 '15 at 23:26

1 Answers1

0

When the for loop executes all created event listeners referrence the same s variable which, after every iteration, have value equal to resulta.length, so resulta[s] is indeed undefined and every event handler will refer to this value. What you have to do is create new scope for every of your handlers via enclosing it in closure. This scope can "hold" resulta[<current iteration's s value>] so that handlers can refer to it.

For example:

for(var s = 0; s < resulta.length; s++)
{
    (function (data) {
        var y = document.createElement('div')
        y.setAttribute('class', 'eachssd');
        var x = document.createTextNode(resulta[s].name)
        y.appendChild(x);
        o.appendChild(y)

        y.addEventListener('click', function () { location.href = data.datasrc }, false);
    }(resulta[s]));
}

In every iteration an anonymous function is created and immediately invoked with one argument beeing resulta[<current iteration's s value>] which is stored in data argument. Some time later, when user clicks on one of created divs it click handler will refer to data from it's lexical scope.


Further reading

Community
  • 1
  • 1
Bartosz Gościński
  • 1,468
  • 1
  • 16
  • 28
  • 1
    Using `let` inside of the for loop is another option, since `let` is block-scoped. So you could just do `let datasrc = resulta[s].datasrc` before attaching the listener, and use `datasrc` inside of the anonymous function. `let` is not very well supported right now, however; and in Chrome, only supported in strict mode. –  May 16 '15 at 23:41
  • 1
    Aaah, also, the `y.addEventListener` line throws a SyntaxError. Should be `y.addEventListener('click', function () { location.href = data.datasrc }, false);` –  May 16 '15 at 23:47
  • Didn't see this. Good catch :) Edited. – Bartosz Gościński May 16 '15 at 23:52
  • @ gbonscinski ,can u pls explain the why data is used as an arguement and why it is inside brackets after the closure – Chuks Udoka Jun 11 '15 at 21:46
  • @ChuksUdoka Here we're creating an [IIFE](http://stackoverflow.com/questions/8228281/what-is-the-function-construct-in-javascript) to 'store' current `resulta[s]` value in `data` because we'll need it on `click` handler execution – Bartosz Gościński Jun 11 '15 at 22:12
  • @ChuksUdoka I edited my answer a bit so hopefully it's more clear now – Bartosz Gościński Jun 11 '15 at 22:29