Can I delay the keyup event for jquery?
Asked Answered
D

5

11

I'm using the rottentomatoes movie API in conjunction with twitter's typeahead plugin using bootstrap 2.0. I've been able to integerate the API but the issue I'm having is that after every keyup event the API gets called. This is all fine and dandy but I would rather make the call after a small pause allowing the user to type in several characters first.

Here is my current code that calls the API after a keyup event:

    var autocomplete = $('#searchinput').typeahead()
    .on('keyup', function(ev){

        ev.stopPropagation();
        ev.preventDefault();

        //filter out up/down, tab, enter, and escape keys
        if( $.inArray(ev.keyCode,[40,38,9,13,27]) === -1 ){

            var self = $(this);

            //set typeahead source to empty
            self.data('typeahead').source = [];

            //active used so we aren't triggering duplicate keyup events
            if( !self.data('active') && self.val().length > 0){

                self.data('active', true);

                //Do data request. Insert your own API logic here.
                $.getJSON("http://api.rottentomatoes.com/api/public/v1.0/movies.json?callback=?&apikey=MY_API_KEY&page_limit=5",{
                    q: encodeURI($(this).val())
                }, function(data) {

                    //set this to true when your callback executes
                    self.data('active',true);

                    //Filter out your own parameters. Populate them into an array, since this is what typeahead's source requires
                    var arr = [],
                        i=0;

                    var movies = data.movies;

                     $.each(movies, function(index, movie) {
                        arr[i] = movie.title
                        i++;
                     });

                    //set your results into the typehead's source 
                    self.data('typeahead').source = arr;

                    //trigger keyup on the typeahead to make it search
                    self.trigger('keyup');

                    //All done, set to false to prepare for the next remote query.
                    self.data('active', false);

                });

            }
        }
    });

Is it possible to set a small delay and avoid calling the API after every keyup?

Doubleripper answered 1/4, 2012 at 17:11 Comment(0)
E
10

it can be easily done like this:

var autocomplete = $('#searchinput').typeahead().on('keyup', delayRequest);

function dataRequest() {
    // api request here
}

function delayRequest(ev) {
    if(delayRequest.timeout) {
        clearTimeout(delayRequest.timeout);
    }

    var target = this;

    delayRequest.timeout = setTimeout(function() {
        dataRequest.call(target, ev);
    }, 200); // 200ms delay
}
Embed answered 1/4, 2012 at 17:29 Comment(2)
This works well but it seems to get stuck in a loop, making a call to datarequest every 200 ms?Doubleripper
In your code, you are triggering keyup after keyup: self.trigger('keyup'). For the proper keyup event handling you should remove ev.stopPropagation(); and self.trigger('keyup')Embed
C
4

In general, this can be achieved with setTimeout and clearTimeout methods:

var timer;

$('#textbox').keyup(function() {
    if (timer) {
        clearTimeout(timer);
    }
    timer = setTimeout('alert("Something cool happens here....");', 500);
});

setTimeout will execute the provided javascript after the specified interval in milliseconds passes. clearTimeout will cancel this execution.

I've also prepared jsFiddle demo showing the code snippet in action.

References:

Cammack answered 1/4, 2012 at 17:26 Comment(0)
P
2

For people working with v0.11 of typeahead.js and using Bloodhound to fetch remote suggestions, you can use the rateLimitWait option to throttle requests:

var search = new Bloodhound({
  datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),
  queryTokenizer: Bloodhound.tokenizers.whitespace,
  remote: {
    url: '/search?q=%QUERY',
    rateLimitWait: 500
  }
});
Penstemon answered 30/4, 2015 at 20:58 Comment(0)
F
1

Not sure what version Bootstrap 2.0 uses for typeahead, but v0.9.3 has a minLength option that's hidden under the hood, but not documented.

$('#people').typeahead({
  name: 'people',
  prefetch: './names.json',
  minLength: 3
});

As found from this blog post: http://tosbourn.com/2013/08/javascript/setting-a-minimum-length-for-your-search-in-typeahead-js/

Federalism answered 11/12, 2013 at 20:34 Comment(0)
N
-1

Rather than a delay, if you just want to allow the user to enter a few characters before the ajax $.getJSON request, you could amend the if statement so that the user has to enter a minimum number of characters, for example 3, before you request the data:

if( !self.data('active') && self.val().length >=3){
Northey answered 1/4, 2012 at 17:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.