Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to ignore all except the last one of a series of quick Javascript events?

One of my script calls a function at some point, due to a 'changeCursor' event (I am using ACE editor). This slows down the movement of the cursor when I press it many times.

I really want this function to be called, but it's fine if it is only called once my cursor stopped moving (i.e. I do not need to see intermediary states).

Is there a standard way to have all but the last event ignored?

like image 939
joelhoro Avatar asked Mar 17 '13 20:03

joelhoro


2 Answers

The classic way is to use a short timeout:

var cursorTimer;
function changeCursor() {
    clearTimeout(cursorTimer);
    cursorTimer = setTimeout(function() {
        // process the actual cursor change here
    }, 500);

}

Your regular code can continue calling changeCursor() every time it changes (just like it does now), but the actual code inside the setTimeout() will only execute when no cursor change events have occurred in the last 500ms. You can adjust that time value as desired.

The only way to know that events have stopped is to wait some short period of time and detect no further movement (which is what this does). It is common to use similar logic with scroll events.

like image 104
jfriend00 Avatar answered Sep 28 '22 04:09

jfriend00


It maybe overkill for this one issue, but check out RxJS: http://reactive-extensions.github.com/RxJS/#What is RxJS?

It adds some pretty powerful methods to "query/manipulate" event streams in JavaScript. https://github.com/Reactive-Extensions/RxJS/wiki/Observable

In this case the "throttle" method is what your after. Here is an example that uses Throttle with the keyup event to create auto-complete of wikipedia matches. https://github.com/Reactive-Extensions/RxJS-Examples/blob/master/autocomplete/autocomplete.js

// Get all distinct key up events from the input and only fire if long enough and distinct
var keyup = Rx.Observable.fromEvent(input, 'keyup').select(function (e) {
    return e.target.value; // Project the text from the input
})
.where(function (text) {
    return text.length > 2; // Only if the text is longer than 2 characters
})
.throttle(
    750 // Pause for 750ms
)
.distinctUntilChanged(); // Only if the value has changed
like image 29
eSniff Avatar answered Sep 28 '22 06:09

eSniff