How to respond to a Javascript event only if it is fired once and then not fired again during some time period?
Add a timeout, that runs your code 500ms after the event fires, each time the event fires clear the timeout and create a new one.
eg.
google.maps.event.addListener(map, 'bounds_changed', (function () {
var timer;
return function() {
clearTimeout(timer);
timer = setTimeout(function() {
// here goes an ajax call
}, 500);
}
}()));
There is a really good approach available on unscriptable.com:
Function.prototype.debounce = function (threshold, execAsap) {
var func = this, // reference to original function
timeout; // handle to setTimeout async task (detection period)
// return the new debounced function which executes the original function
// only once until the detection period expires
return function debounced () {
var obj = this, // reference to original context object
args = arguments; // arguments at execution time
// this is the detection function. it will be executed if/when the
// threshold expires
function delayed () {
// if we're executing at the end of the detection period
if (!execAsap)
func.apply(obj, args); // execute now
// clear timeout handle
timeout = null;
};
// stop any current detection period
if (timeout)
clearTimeout(timeout);
// otherwise, if we're not already waiting and we're executing at the
// beginning of the waiting period
else if (execAsap)
func.apply(obj, args); // execute now
// reset the waiting period
timeout = setTimeout(delayed, threshold || 100);
};
}
This would let you do:
// call the function 200ms after the bounds_changed event last fired:
google.maps.event.addListener(map, 'bounds_changed', (function() {
// here goes an ajax call
}).debounce(200));
// call the function only once per 200ms:
google.maps.event.addListener(map, 'bounds_changed', (function() {
// here goes an ajax call
}).debounce(200,true));
If you prefer to not augment the Function.prototype
there is a standalone function debounce(func, threshold, execAsap)
available on the blog post.
google suggests using another listener ...
google.maps.event.addListener(map, 'idle', showMarkers);
quote "Note that you could listen to the bounds_changed event but it fires continuously as the user pans; instead, the idle will fire once the user has stopped panning/zooming." /quote
see
http://code.google.com/apis/maps/articles/toomanymarkers.html#gridbasedclustering