0

I have an event handler wired to a variety of events to ensure that it gets fired under a variety of circumstances.

var allChangeEvents = "focus blur select change click dblclick mousedown mouseup keypress keydown keyup";
$("#myTextbox").on(allChangeEvents, function() {
    console.log("Event fired.");
});

You'll notice that interacting regularly with <input type="text" id="myTextbox" /> (clicking, tapping, focusing, etc.) will actually cause the event to be fired multiple times. If the code being run becomes very large, then this could hurt performance. Is there any way for me to prevent the event from being fired so many times without having to remove a ton of my event types?

Jacob Stamm
  • 1,660
  • 1
  • 29
  • 53

2 Answers2

4

One option is to throttle (or debounce) the calls, so that you only get one call occurring per time period. A simple implementation would be as below (however, a better implementation can be found here)

function debounce(fn,time){
    var timerId = null;
    return function(e){
        if(timerId)
            return;

        timerId = setTimeout(function(){
            fn(e);
            timerId = null;
        },time);
    }
}

And usage would be

var allChangeEvents = "focus blur select change click dblclick mousedown mouseup keypress keydown keyup";
$("#myTextbox").on(allChangeEvents, debounce(function(e) {
    console.log("Event fired.");
},300)); 

As you can see, this example would cause your event handling function to occur no more often than every 300ms. This is a good way to limit how often intensive functions are executed.

Below is a live example of this in action

var allChangeEvents = "focus blur select change click dblclick mousedown mouseup keypress keydown keyup";
$("#myTextbox").on(allChangeEvents, debounce(function(e) {
    console.log("Event fired.");
},300));


function debounce(fn,time){
    var timerId = null;
    return function(e){
        if(timerId)
            return;
        
        timerId = setTimeout(function(){
            fn(e);
            timerId = null;
        },time);
    }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="myTextbox" />
Jamiec
  • 133,658
  • 13
  • 134
  • 193
  • Thanks. I've gotta say, I personally think your implementation is easier to understand than the one in the link you provided. You'd have to be a JavaScript pro to understand that stuff, whereas your example is clear and concise. – Jacob Stamm Nov 03 '15 at 16:28
  • Mine is naive though - it changes the call site of the function, and can lead to weird behaviour. – Jamiec Nov 03 '15 at 16:29
  • does that mean that it brings the function out of its previous context? – Jacob Stamm Nov 03 '15 at 17:58
  • Sort of, for event handlers it will work fine - it passes through the event (`e`) which is all you'll need. It wont work so well in a more generic sense - which the linked version would. – Jamiec Nov 04 '15 at 08:34
3

According to the documentation: http://api.jquery.com/event.stopimmediatepropagation/

if your functions ends with a call to event.stopImmediatePropagation(); as soon as one is executed the others wont fire.

pedromss
  • 2,443
  • 18
  • 24
  • 4
    This only applies for events bubbling up the "DOM tree", not for multiple separate events on the same element. `stopImmediatePropagation()` would work if, for instance, you had a ` – Jacob Stamm Sep 28 '17 at 20:33