Reputation: 1362
I have a search button the user can click.
This search button calls a function. I want to avoid that the function is executed multiple times when the user clicks the search button twice or more (because he thinks that nothing has happened).
I am thinking of using setTimeout(function(){})
somehow and in the end only call the search function again if the click on the button is at least 3 seconds away from the last click.
Example: https://jsfiddle.net/n1rcre75/ - I want to be able to click the button twice in a row (after 1 second) but have the execute function only run once
Any ideas?
Upvotes: 1
Views: 3600
Reputation: 13767
I created a constructor to handle this in a reusable way. You can provide a delay when you create the object or when you invoke it. It has a default of 300ms.
function FunctionInvoker(waitTime) {
this.timerIdentifier = null;
this.waitTime = waitTime || 300;
var self = this;
this.invoke = function (callback, waitTime) {
self.cancel();
self.timerIdentifier = setTimeout(function () {
self.cancel();
callback();
}, waitTime || self.waitTime);
};
this.cancel = function () {
if (self.timerIdentifier != null) {
clearTimeout(self.timerIdentifier);
self.timerIdentifier = null;
}
}
}
To use it:
var functionInvoker = new FunctionInvoker();
functionInvoker.invoke(function () {
// whatever you want to do (callback function)
saveMyData(); // for ex: save data
});
I used this code when dealing with a slider. The slider was making an AJAX call too many times. By using the functionInvoker I was able to only make the AJAX call when slider keeps the same value for Xms.
Upvotes: 1
Reputation: 1362
This function can be used to make it work without any additional states or parameters that have to be cared for
function debounce(func, wait, immediate) {
var timeout;
return function() {
var context = this, args = arguments;
var later = function() {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
};
https://jsfiddle.net/cpg584pp/
Upvotes: 0
Reputation: 80
took your fiddle and made a few changes, the
setTimeout(function(){
//stuff
},3000);
is only to simulate the actual searching
https://jsfiddle.net/n4fhaqad/
Upvotes: 1
Reputation: 5527
Just guard the search:
var button = document.getElementById('search');
var runSearch = true;
button.addEventListener('click', function(evt) {
evt.preventDefault();
if(!runSearch){
return;
}
console.log('do search');
runSearch = false;
setTimeout(function(){
runSearch = true;
}, 3000);
});
Or, if you don't want to introduce another variable to the scope:
document.getElementById('search').addEventListener('click', (function() {
var runSearch = true;
return function(evt) {
evt.preventDefault();
if(!runSearch){
return;
}
runSearch = false;
console.log('do search');
setTimeout(function(){
runSearch = true;
}, 3000);
}
})());
Upvotes: 3
Reputation: 4261
A generic code. You can add avoid_double_click class to that link/button on which you want to avoid multiple clicks
jQuery('.avoid_double_click').on('click', function(e) {
var onclick_event = jQuery(this).attr('onclick');
jQuery(this).removeAttr("onclick");
var that = this;
setTimeout(function(){
jQuery(that).attr('onclick', onclick_event);
},2000);
});
Upvotes: 0
Reputation: 2974
Try this code:
<html>
<head>
<script type="text/javascript" src="http://code.jquery.com/jquery-2.1.3.min.js"></script>
<script>
$(document).ready(function() {
$('button').click(function() {
$('button').prop('disabled', true);
setTimeout(function() {
$('button').prop('disabled', false);
}, 3000);
});
});
</script>
</head>
<body>
<button>Click me</button>
</body>
</html>
Upvotes: 0
Reputation: 8488
Just another solution:
<button onclick="buttonClick()">Click</button>
<script>
var running = false;
function buttonClick(){
if(running == false){
running = true;
//your code
setTimeout(function(){running = false}, 3000);
}
}
</script>
Upvotes: 0
Reputation: 435
When you call you our function from the press event, disable the original button for the time the function runs, for example using the get element by Id:
function(foo){
document.getElementById("yourButtonId").disabled = true;
//do your function
document.getElementById("btnPlaceOrder").disabled = false;
}
of course this use case is not perfect for all situations, where for example you want to do additional calls inside the function or even xhr. If you have callbacks you should re-enable the button in those.
Upvotes: 0
Reputation: 1310
Make the button inactive until your search function return success or error, or until the user change the search string.
Upvotes: 0