1

I have a table where one of the td cells has a input type=text field. Each row in the table has something like this:

<td class="expected_minutes">
   <input id="minutes-980" class="minutes" type="text" value="39" name="minutes-980">
</td>

Now what I'm trying to do is change the value in another cell if the user changes the value in this particular one. It doesn't necessarily have to be done when the user is done changing text. It can be whenever the value in the text box changes at all -- whatever works best. Here's some code I found on SO to get me started:

//setup before functions
    var typingTimer;                //timer identifier
    var doneTypingInterval = 2000;  //time in ms

    //on keyup, start the countdown
    $('.minutes').keyup(function(){
        clearTimeout(typingTimer);
        typingTimer = setTimeout(doneTyping, doneTypingInterval);
    });

    //on keydown, clear the countdown 
    $('.minutes').keydown(function(){
        clearTimeout(typingTimer);
    });

    //user is "finished typing," do something
    function doneTyping () {
        console.log("DONE TYPING");
    }

The problem I've found here is this code was most likely targeting an application with a single input text box. I have several rows where each row has one and I need to run some code when the minutes value in that particular row has been modified.

Is there anyway I can make this work for all of the text boxes in my table?

randombits
  • 47,058
  • 76
  • 251
  • 433

2 Answers2

2

You need some way to associate a timeout with a specific input. One convenient way of doing this would be using jQuery's .data function:

var doneTypingInterval = 2000;  //time in ms

//on keyup, start the countdown
$('.minutes').keyup(function(){
    var typingTimer = $(this).data('timer');
    clearTimeout(typingTimer);

    typingTimer = setTimeout(doneTyping, doneTypingInterval);

    $(this).data('timer', typingTimer);
});

//on keydown, clear the countdown 
$('.minutes').keydown(function(){
    clearTimeout($(this).data('timer'));
});

//user is "finished typing," do something
function doneTyping () {
    console.log("DONE TYPING");
}

Also, as a sidenote, I don't really see the need for the keydown handler at all. You could do all of this with one handler (on keyup or keydown).

Example: http://jsfiddle.net/RkWH5/


Update from comment: If you need to know which input is "done", you could use $.proxy to create a function whose this value is the value of the input:

var doneTypingInterval = 2000; //time in ms

$('.minutes').keydown(function () {
    var typingTimer = $(this).data('timer');

    clearTimeout(typingTimer);

    typingTimer = setTimeout($.proxy(doneTyping, this), doneTypingInterval);

    $(this).data('timer', typingTimer);
});

function doneTyping() {
    /* `this` is the element that the user is done typing in. */
    $(this).css('color', 'red');
}

If you don't want to use this, you could pass a parameter to doneTyping this way:

var doneTypingInterval = 2000; //time in ms

//on keyup, start the countdown
$('.minutes').keydown(function () {
    var typingTimer = $(this).data('timer')
        , el = this;

    clearTimeout(typingTimer);

    typingTimer = setTimeout(function () {
        doneTyping(el);
    }, doneTypingInterval);

    $(this).data('timer', typingTimer);
});

//user is "finished typing," do something
function doneTyping(el) {
    /* do something with "el" */
}
Andrew Whitaker
  • 124,656
  • 32
  • 289
  • 307
  • Is it also possible to pass a parameter to doneTyping so I know which text box was affected? I didn't ask that in the original question and this is the right answer regardless. – randombits Feb 27 '14 at 21:17
  • @randombits: Yep, in fact that's what's happening in the Jsfiddle :). I updated the answer as well. – Andrew Whitaker Feb 27 '14 at 21:18
0

Need to loop and set the timers as internal to the closure so they're independent on each one: (trying to keep it close to your code, all I did was function wrap and loop)

var typeTimingSingle = function(elem){
//setup before functions
var typingTimer;                //timer identifier
var doneTypingInterval = 2000;  //time in ms

//on keyup, start the countdown
$(elem).keyup(function(){
    clearTimeout(typingTimer);
    typingTimer = setTimeout(doneTyping, doneTypingInterval);
});

//on keydown, clear the countdown 
$(elem).keydown(function(){
    clearTimeout(typingTimer);
});

//user is "finished typing," do something
function doneTyping () {
    console.log("DONE TYPING");
}
};

$('.minutes').forEach(typeTimingSingle); // Use any loop needed
Andrew Templeton
  • 1,656
  • 10
  • 13