Javascript: setTimeout() - help needed
I'm currently doing a highlighting function on a webpage and im using the jquery plugin for that. My code looks like this:
var input = function() {
var matchword = $('#searchbox').val();
if(matchword != "") {
$('body').remove开发者_StackOverflowHighlight();
$('body').highlight($('#searchbox').val());
}
}
$(document).ready(function() {
$('#searchbox').keyup(function() {
setTimeout("input()", 2000);
});
});
It works fine if there is not so large amount of data on the page. But in case of large amount of data on the page the whole process is slowing down which causes that inputbox is freezing untill the letter is hightlighted. So the typing is not smooth. I tryed to use a setTimeout but it seems doesnt help. Any ideas?
Please don't pass setTimeout
a string, there's no need in this case, you can call the function directly like this:
$(function() {
$('#searchbox').keyup(function() {
if($(this).data("timeout")) clearTimeout($(this).data("timeout"));
$(this).data("timeout", setTimeout(input, 2000));
});
});
As for the other problem of queueing up highlights, you just need to clear the previous timeout (from up to 2 seconds ago) first like above. Also, you can store this timeout locally on the element using .data()
like I have above, fewer global variables and you could use this across many elements instead of a timeout variable for each.
In the sample that you have provided, the setTimeout is only delaying the execution of the function, but the number of executions is still the same. What you need to do is, refresh the timeout each time the user types a character, so the input() function does not fire each time:
var timer;
$('#searchbox').keyup(function() {
clearTimeout(timer);
timer = setTimeout(input, 2000);
});
You could use the JQuery throttle plugin - it's a rate limiter.
jQuery isn’t actually required for this plugin, because nothing internal uses any jQuery methods or properties. jQuery is just used as a namespace under which these methods can exist.
From here
jQuery throttle / debounce allows you to rate-limit your functions in multiple useful ways. Passing a delay and callback to $.throttle returns a new function that will execute no more than once every delay milliseconds. Passing a delay and callback to $.debounce returns a new function that will execute only once, coalescing multiple sequential calls into a single execution at either the very beginning or end.
The timeout isn't helping now as you're just delaying the execution of all keyup events by 2000 milliseconds – it will just freeze the browser 2 seconds later. I assume what you want is that when there has been 2000 milliseconds from the last keyup event, then fire the input
function. That can be accomplished like this:
$(document).ready(function() {
var keyUpTimeout;
$('#searchbox').keyup(function() {
clearTimeout(keyUpTimeout);
keyUpTimeout = setTimeout("input()", 2000);
});
});
As you clear the previous timeout using clearTimeout
, the input
function is called only once when writing stops. Ergo, text is highlighted when the user has paused writing for 2 seconds.
Consider using focus and blur listeners with setInterval function, rather than the keyup listener. In the following example I'm calling the input method only when there is a change in the "searchbox" value. This will allow me to avoid unnecessary invocations to the input method [like user pressing shift key].
$(document).ready(function() {
var highlightInterval;
var previousValue = $('#searchbox').val();
$('#searchbox').focus(function() {
if(highlightInterval) {
window.clearInterval(highlightInterval);
}
highlightInterval = window.setInterval(function(){
if(previousValue != $('#searchbox').val()){
previousValue = $('#searchbox').val();
input();
}
}, 2000);
});
$('#searchbox').blur(function(){
window.clearInterval(highlightInterval);
});
});
I understand that the highlight method is looking for all the appareances of $('#searchbox').val()
and then it's sorrounding it with some kind of highlighting style. Please, correct me if I'm wrong!
I think you may make it a bith more smooth by wrapping each highlighting inside a setTimeout, like this
function wrapIntoHighligh(something){
...
}
for(var i = 0; i < occurrences.length; i++){
setTimeout("wrapIntoHighligh(something)", 1);
}
It may not be the cleaner solution... but it will make that each highlighting goes out of the loop, it will enqeue again in the JS stack and hopefully it will not block everything.
精彩评论