问题
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?
回答1:
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
}
回答2:
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:
- Javascript timing methods
回答3:
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
}
});
回答4:
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/
回答5:
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){
来源:https://stackoverflow.com/questions/9966394/can-i-delay-the-keyup-event-for-jquery