0

I'm trying to initialize a bunch of jquery functions using a foor loop. I use the for loop's counter in each iteration to call the function on a row in a table.

But it doesn't works. I think it's because the counter doesn't exists within the function. This is because I have already tried to run my function hard-coding the places where the counter should be, with, say, 0, and my function works as intended on row 0 of my table. When I leave the counter in place it throws me an error, says that the html elements I get by Id are null.

Is there something I'm missing? How do I pass the counter into a function in javascript?

Here's my code:


  var typingTimer;                //timer identifier
  var doneTypingInterval = 400;  //time in ms (5 seconds)

var i

for (i = 0; i < 10; i++) {
  //on keyup, start the countdown
  $('#precios-'.concat(i,'-precio')).keyup(function(i){
      clearTimeout(typingTimer);
      if (document.getElementById('precios-'.concat(i,'-precio')).value) {
          typingTimer = setTimeout(doneTyping, doneTypingInterval);
      }
  });

  //user is "finished typing," do something
  function doneTyping(i) {
          var it = i
          $.getJSON('./_revisarCaptura', {
            unidades: $($($('#precios-'.concat(it,'-precio')).parents()[1]).siblings()[6]).html(),
            ultimoPrecio: $($($('#precios-'.concat(it,'-precio')).parents()[1]).siblings()[7]).html().substring(1),
            nuevoPrecio: document.getElementById('precios-'.concat(it,'-precio')).value,
            nuevasUnidades: document.getElementById('precios-'.concat(it,'-precio')).value,
          }, function(data) {

            $('#precios-'.concat(it,'-precio')).css('backgroundColor', data.result)
  })
  return false
}

i++

}


1 Answers1

0

Your code has two problems:

  1. keyup and doneTyping() functions declare i as a parameter. They shadow the i variable outside the loop. The keyup funciton receives the keyup event as i instead.
  2. i is not captured for each iteration of the loop. By the time the callbacks are called, i will be set to 10 instead of the loop counter.

The following code fixes the problem.

var typingTimer;                //timer identifier
var doneTypingInterval = 400;   //time in ms (5 seconds)
// This i is changed by the loop.
// By the time doneTyping() is called, i will be 10.
var i;
for (i = 0; i < 10; i++) {
    // let/const keeps the variable scoped within the loop
    const id = `precios-${i}-precio`;
    const selector = `#${id}`;

    // This is also known as debounce
    $(selector).keyup(function(/* remove i */){
        clearTimeout(typingTimer);
        if (document.getElementById(id).value) {
            typingTimer = setTimeout(doneTyping, doneTypingInterval);
        }
    });

    function doneTyping(/* remove i */) {
        $.getJSON('./_revisarCaptura', {
            unidades: $($($(selector).parents()[1]).siblings()[6]).html(),
            ultimoPrecio: $($($(selector).parents()[1]).siblings()[7]).html().substring(1),
            nuevoPrecio: document.getElementById(id).value,
            nuevasUnidades: document.getElementById(id).value,
        }, function(data) {
            $(selector).css('backgroundColor', data.result)
        });
        return false; // Do you need this?
    }
}

See also let vs. var.

Dafang Cao
  • 897
  • 5
  • 15