0

I'm trying to run one function to many elements, so I'm using a for loop. I dont understand why i'm not getting any values.

    var i;
var aFields = ["#business1A","#business1B","#business1C","#business1D","#business2A","#business2B","#business2C","#business2D",
                "#business3A","#business3B","#business3C","#business3D","#business4A","#business4B","#business4C","#business4D",
                "#business5A","#business5B","#business5C","#business5D","#business6A","#business6B","#business6C","#business6D"];
for (i = 0; i < aFields.length; i++) {
    $(aFields[i]).keyup(function(){
        alert($(aFields[i]+'Warning') + " - " +$(aFields[i]).val());
    });
}
Mike Spider
  • 217
  • 1
  • 3
  • 17
  • 2
    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures#Creating_closures_in_loops.3A_A_common_mistake – Arun P Johny Dec 31 '13 at 03:31
  • possible duplicate of [Javascript closure inside loops - simple practical example](http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example) – Barmar Dec 31 '13 at 03:36

4 Answers4

1

That's because you are using the variable i in the callback function for the event handler. The event happens when the loop has finished, so the variable contains an index that is beyond the last item in the array.

To use the value of the variable from the iteration where you bind the event, you can create a variable for each iteration by creating a scope, using an immediately executed function expression:

var i;
var aFields = ["#business1A","#business1B","#business1C","#business1D","#business2A","#business2B","#business2C","#business2D",
                "#business3A","#business3B","#business3C","#business3D","#business4A","#business4B","#business4C","#business4D",
                "#business5A","#business5B","#business5C","#business5D","#business6A","#business6B","#business6C","#business6D"];
for (i = 0; i < aFields.length; i++) {
  (function(j){
    $(aFields[j]).keyup(function(){
        alert($(aFields[j]+'Warning') + " - " +$(aFields[j]).val());
    });
  })(i);
}
Guffa
  • 687,336
  • 108
  • 737
  • 1,005
1

Try this:

var i;
var aFields = ["#business1A","#business1B","#business1C","#business1D","#business2A","#business2B","#business2C","#business2D",
                "#business3A","#business3B","#business3C","#business3D","#business4A","#business4B","#business4C","#business4D",
                "#business5A","#business5B","#business5C","#business5D","#business6A","#business6B","#business6C","#business6D"];
for (i = 0; i < aFields.length; i++) {
  (function(j){
    $(aFields[j]).keyup(function(){
        alert(($(this).attr('id')+'Warning') + " - " +$(this).val());
    });
  })(i);
}
Ringo
  • 3,795
  • 3
  • 22
  • 37
  • wrapping it in a function is unnecessary if you are just going to use `this`. I'd definitely prefer it over the closure method, since it is cleaner. – Dennis Dec 31 '13 at 03:42
  • It works! Thanks a lot for the light speed replies! Stackoverflow Rocks! :p – Mike Spider Dec 31 '13 at 03:44
0

The problem here is the wrong usage of the closure variable i, the variable is shared between all the keyup handlers so when the loop ends i will have the value aFields.length so aFields[i] will return undefined.

Try

var aFields = ["#business1A", "#business1B", "#business1C", "#business1D", "#business2A", "#business2B", "#business2C", "#business2D",
    "#business3A", "#business3B", "#business3C", "#business3D", "#business4A", "#business4B", "#business4C", "#business4D",
    "#business5A", "#business5B", "#business5C", "#business5D", "#business6A", "#business6B", "#business6C", "#business6D"];

$.each(aFields, function (i, val) {
    $(val).keyup(function () {
        alert($(val + 'Warning') + " - " + $(val).val());
    });
})
Arun P Johny
  • 384,651
  • 66
  • 527
  • 531
  • Thanks for your quick reply, However, I'm only getting the second value, the first still comes as "[object]". – Mike Spider Dec 31 '13 at 03:40
  • @MichelFigueiredo `$(val + 'Warning')` will evaluate to a jQuery object - what do you want there? – Dennis Dec 31 '13 at 03:43
  • i want to get hold of the actual id string so that I can pass into another function. that's working now. Cheers! – Mike Spider Dec 31 '13 at 03:54
0

The other answers are good explanations of how closures work, but the cleanest solution is to use this to refer to the selected object:

var i;
var aFields = ["#business1A","#business1B","#business1C","#business1D","#business2A","#business2B","#business2C","#business2D",
            "#business3A","#business3B","#business3C","#business3D","#business4A","#business4B","#business4C","#business4D",
            "#business5A","#business5B","#business5C","#business5D","#business6A","#business6B","#business6C","#business6D"];
for (i = 0; i < aFields.length; i++) {
    $(aFields[i]).keyup(function(){
        alert(this.id + ' Warning - ' + this.value);
    });
}
Dennis
  • 32,200
  • 11
  • 64
  • 79