JQuery One - один раз один раз с несколькими типами событий

В соответствии с docs для one:

Если первый аргумент содержит более одного типа событий, разделенных пробелами, обработчик события называется один раз для каждого типа события.

Есть ли способ запускать одну функцию один раз, когда возникает какое-либо событие?

Пример:

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

Я хотел бы только один раз вызвать функцию, независимо от того, какое событие запустило ее.

В настоящее время функция будет запускаться один раз для каждого типа события.

Демо в скрипте

Примечание. Я не ищу здесь событие focus. Это просто пример.

Ответ 1

Вместо .one используйте .on и удалите привязку вручную с помощью .off.

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

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


Это можно сделать немного более элегантно с пространствами имен:

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

Это позволяет нам использовать один идентификатор (foo) для удаления любого количества привязок, и мы не будем влиять на другие привязки клавиш или клавиш, которые может иметь элемент.

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

Ответ 2

Отличные ответы! Чтобы включить их в функцию, здесь расширение jQuery основывается на текущих ответах:

//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);
        }
    });
};

Затем назовите это:

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

Демо в скрипке

Бонус. Это имеет дополнительное преимущество только для отсоединения обработчиков для этой конкретной функции, передав исходный обработчик

Ответ 3

Вы можете просто добавить $('input').off(); в конец вашей функции.

Ответ 4

Чтобы выстрелить один раз и продолжить стрельбу, можно использовать следующий фрагмент:

https://jsfiddle.net/wo0r785t/1/

$.fn.onSingle = function(events, callback){
    if ("function" == typeof(callback)) {
        var t = this;
        var internalCallback = function(event){
            $(t).off(events, internalCallback);
            callback.apply(t, [event]);
            setTimeout(function(){
                $(t).on(events, internalCallback);
            }, 0);
        };
        $(t).on(events, internalCallback);
    }
    return $(this);
};

Он работает, временно отключив события, используя функцию internalCallback, и асинхронно (setTimeout) снова включив его.

Большинство других предложений в этом потоке отключить все будущие события на целевой. Однако, хотя OP, похоже, удовлетворен предыдущими ответами, в его вопросе не упоминается постоянное отключение событий.