Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jQuery's One - Fire once with multiple event types

Is there a way to fire a single function once when any event is raised?

For example, if I have the following function: (demo in jsfiddle)

$('input').one('mouseup keyup', function(e){ 
    console.log(e.type);
});

I'd like to only call the function once, regardless of which event fired it.

But according to the docs for .one():

If the first argument contains more than one space-separated event types, the event handler is called once for each event type.

So, currently the function will fire once for each event type.

like image 303
KyleMit Avatar asked Jul 05 '14 17:07

KyleMit


People also ask

How to trigger the same function with multiple events using jQuery?

Triggering the same function with multiple events is often required. Well, this task is very easy using jQuery. Using jQuery on () method this task can be done. We can easily pass multiple events with jQuery on () method. The jQuery on multiple events is an easy task.

How to use multiple event names inside on () method in JavaScript?

Inside the on () method, in the first parameter, we put multiple event names separated by space. The same function will be called every time one of these three events will occur. Now we are going to give an example. In this example, we have a text type input field.

What is the use of jQuery event method?

Commonly Used jQuery Event Methods $(document).ready() The $(document).ready() method allows us to execute a function when the document is fully loaded. This event is already explained in the jQuery Syntax chapter. click() The click() method attaches an event handler function to an HTML element.

What is an event in JavaScript?

An event represents the precise moment when something happens. The term "fires/fired" is often used with events. Example: "The keypress event is fired, the moment you press a key". In jQuery, most DOM events have an equivalent jQuery method.


2 Answers

Instead of using .one, use .on and remove the binding manually with .off.

$('input').on('mouseup keyup', function(e){
    console.log(e.type);
    $(this).off('mouseup keyup');
});

Fiddle: http://jsfiddle.net/23H7J/3/


This can be done a little more elegantly with namespaces:

$('input').on('mouseup.foo keyup.foo', function(e){
    console.log(e.type);
    $(this).off('.foo');
});

This allows us to use a single identifier (foo) to remove any number of bindings, and we won't affect any other mouseup or keyup bindings the element may have.

Fiddle: http://jsfiddle.net/23H7J/41/

like image 102
Mooseman Avatar answered Nov 11 '22 00:11

Mooseman


Great answers! To wrap them into a function, here's a jQuery extension based off the current answers:

//The handler is executed at most once per element for all event types.
$.fn.once = function (events, callback) {
    return this.each(function () {
        $(this).on(events, myCallback);
        function myCallback(e) {
            $(this).off(events, myCallback);
            callback.call(this, e);
        }
    });
};

Then call like this:

$('input').once('mouseup keyup', function(e){ 
    console.log(e.type);
});

Demo in fiddle

Bonus: This has the added benefit of only detaching the handlers for this specific function by passing in the original handler to the off function. Otherwise, you'll need custom namespaces.

Additionally, if you want a handler to fire only once as soon as any of the elements fire any of the events and then immediately detach itself, then just remove the each from the extension like this:

//The handler is executed at most once for all elements for all event types.
$.fn.only = function (events, callback) {
    var $this = $(this).on(events, myCallback);
    function myCallback(e) {
        $this.off(events, myCallback);
        callback.call(this, e);
    }
    return this
};
like image 27
KyleMit Avatar answered Nov 11 '22 00:11

KyleMit