10

I have users making ajax call while typing. The problem is that it makes the call for every letter being typed, so I set timeout like this:

$(input).live('keyup', function(e){

setTimeout(function(){ 

var xx = $(input).val();
doSearch(xx); 

}, 400); 

}); 

It does wait for 400ms but then executes for every keyup. How can I change this to make the ajax call only 'once' about 400ms after the last typed letter?

(I used 'delay' in the past but that doesn't work at all with my script...)

Youss
  • 4,196
  • 12
  • 55
  • 109
  • There is already a solution provided in other question: https://stackoverflow.com/questions/4220126/run-javascript-function-when-user-finishes-typing-instead-of-on-key-up/16324620#16324620 – Lokendra Khandelwal Jun 21 '16 at 07:01
  • Does this answer your question? [Run javascript function when user finishes typing instead of on key up?](https://stackoverflow.com/questions/4220126/run-javascript-function-when-user-finishes-typing-instead-of-on-key-up) – Damjan Pavlica Apr 17 '20 at 17:39

4 Answers4

23
timer = 0;
function mySearch (){ 
    var xx = $(input).val();
    doSearch(xx); 
}
$(input).live('keyup', function(e){
    if (timer) {
        clearTimeout(timer);
    }
    timer = setTimeout(mySearch, 400); 
});

it's better to move your function to a named function and call it multiple times, 'cause otherwise you're creating another lambda function on each keyup which is unnecessary and relatively expensive

Gavriel
  • 18,880
  • 12
  • 68
  • 105
  • @Youss and what happens if you press and release one key, and then hold another key down? – Alnitak Apr 12 '12 at 13:19
  • @Alnitak, you're right, and there are other problems with this, for example when you type too slow (more than 400ms between 2 keys), but in normal case it makes things smoother – Gavriel Apr 12 '12 at 13:21
  • @Flöcsy the typing too slow problem is unavoidable. The key press one is, with my answer, since the timer clear is down on key down, not on each new key up. – Alnitak Apr 12 '12 at 13:22
  • @Alnitak My REAL problem was that typing was not smooth when fast typing (request was made, hence typing would stop and later cache up on itself). Slow typing is not a problem since I want the element of 'live search' – Youss Apr 12 '12 at 13:25
  • @Youss yup, I was just trying to make the point that IMHO clearing the timer is better done on key down than on key up. – Alnitak Apr 12 '12 at 13:26
4

You need to reset the timer each time a new key is pressed, e.g.

(function() {
    var timer = null;

    $(input).live('keyup', function(e) {
        timer = setTimeout(..., 400);
    });

    $(input).live('keydown', function(e) {
        clearTimeout(timer);
    });
)();

The function expression is used to ensure that the timer variable's scope is restricted to those two functions that need it.

Alnitak
  • 334,560
  • 70
  • 407
  • 495
0

I would think that you could use delay() again in this context as long as you're o.k. with adding a new temporary 'something' to the mix. Would this work for you?

$(input).live('keyup', function(e) {
    if (!$(input).hasClass("outRunningAJob")) {
        var xx = $(input).val();
        $(input).addClass("outRunningAJob");
        doSearch(xx);
        $(input).delay(400).queue(function() {
            $(this).removeClass("outRunningAJob");
            $(this).dequeue();
        });
    }
});
veeTrain
  • 2,915
  • 2
  • 26
  • 43
  • Seems like a workaround...The answer provided by @Flöcsy is more straight forward. ps what is outRunningAJob:) – Youss Apr 12 '12 at 13:17
  • I personally haven't yet become comfortable with the `timeout` functions and so I thought maybe you were in a similar place since you are asking about it. Is it a workaround? It is how I would currently approach the problem. If you are currently more familiar with using `delay` then this might be a better solution (in a maintainability respect). 'outRunningAJob' is just arbitrary but self-documenting. Glad you liked it :-) – veeTrain Apr 12 '12 at 13:36
0

I found the following easier to implement:

$(input).on('keyup', function () {
    delay(function () {
        if (input).val() !== '' && $(input).val() !== $(input).attr('searchString')) {
            // make the AJAX call at this time
            // Store the value sent so we can compare when JSON returns
            $(input).attr('searchString', $(input).val());

            namepicker2_Search_Prep(input);
        }
    }, 500);
});

By storing the current string you are able to see that the user has stopped typing. Then you can safely call your function to do what ever processing needs to happen.

Malcont3nt
  • 430
  • 1
  • 4
  • 11