I have a search box on my web page that has check boxes in order for the user to filter their results. Only one check box can be checked at once.
When a check box is clicked my code runs off and applies the filter to the list and returns the correct results.
The problem I have is that when a check box is clicked multiple times in quick succession, it queues the requests and pulls them back one by one. This can take a while if a check box is checked and then un-checked multiple times.
Is there any way in Javascript to inform the function that it has been called again and it should stop everything other than this last request?
When you click Call the function button, it will execute the function. To stop the function, click Stop the function execution button.
The return statement stops the execution of a function and returns a value.
The destroy() function performs any processing necessary before the database server removes a row that contains opaque data. The database server calls the destroy() function just before it removes the internal representation of an opaque type from disk.
You want to wrap your onclick
callback in a debouncing function like
http://underscorejs.org/#debounce
Say you have this
function search() {
// ...
}
$jquery(".myFilterCheckboxes").click(search);
You should be able to just change the above to:
// Only allow one click event / search every 500ms:
$jquery(".myFilterCheckboxes").click(_.debounce(search, 500));
There are tons of debouncing functions out there, and writing your own isn't a big deal really if you can't or don't want to include underscore.js.
My first thought was towards debouncing because you mentioned multiple clicks creating multiple events in a short period. Debouncing is used really often for things like type-ahead search or autocomplete to provide a little space between key presses for thinking time.
As others have mentioned it may make more sense to simply disable the checkboxes / click event while your search is running. In that case, try something like this:
function disableClick(elem) {
elem.unbind("click");
elem.attr("disabled", true);
}
function enableClick(elem, onclick) {
// Enable click events again
elem.live("click", search);
// Enable the checkboxes
elem.removeAttr("disabled");
}
function search() {
var boxes = $jquery(".myFilterCheckboxes");
disableClick(boxes);
$.get(...).always(function() {
enableClick(boxes, search);
});
}
$jquery(".myFilterCheckboxes").live("click", search);
Why disable the click event, add the disabled attribute to the checkboxes instead of just a global lock variable? Well, global locks can be somewhat error prone, but more than that, we already have a global object that matters in the DOM. If we just modify the DOM state we get the right behavior and signal to our users that they should chill out on the checkboxes until the search completes.
That said, it probably makes sense with any kind of locking / unbinding scenario to indicate to the user with a loading spinner or something that you're doing work.
You can use a lock pattern:
http://jsfiddle.net/RU6gL/
HTML
<input type="checkbox" onclick="fire()" >CB1
<br />
<input type="checkbox" onclick="fire()" >CB2
JS
function_lock = false
fire = function() {
// First, check the lock isn't already reserved. If it is, leave immediately.
if (function_lock) return;
// We got past the lock check, so immediately lock the function to
// stop others entering
function_lock = true;
console.log("This message will appear once, until the lock is released")
// Do your work. I use a simple Timeout. It could be an Ajax call.
window.setTimeout(function() {
// When the work finishes (eg Ajax onSuccess), release the lock.
function_lock = false;
}, 2000);
}
In this example, the function will only run once, no matter how many times the checkboxes are clicked, until the lock is released after 2 seconds by the timeout.
This pattern is quite nice, because it gives you control opver when you release the lock, rather than relying on a timed interval like 'debounce'. For example, it will work with Ajax. If your checkbox is triggering an Ajax call to do the filtering, you can:
HTML
<input type="checkbox" onclick="doAjax()" >CB2
JS
ajax_lock = false
doAjax: function() {
// Check the lock.
if (ajax_lock) return;
// Acquire the lock.
ajax_lock = true;
// Do the work.
$.get("url to ajax endpoint", function() {
// This is the success function: release the lock
ajax_lock = false;
});
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With