Как вызвать событие после использования event.preventDefault () - PullRequest
131 голосов
/ 30 сентября 2011

Я хочу удерживать событие до тех пор, пока не буду готов его запустить, например:

$('.button').live('click', function(e){

   e.preventDefault(); 

   // do lots of stuff

   e.run() //this proceeds with the normal event    

}

Существует ли эквивалент функции run(), описанной выше?

Ответы [ 13 ]

138 голосов
/ 30 сентября 2011

Неа. После отмены события оно отменяется.

Вы можете повторно запустить событие позже, используя флаг, чтобы определить, уже запущен ваш пользовательский код или нет - например, так (пожалуйста, игнорируйте явное загрязнение пространства имен):

var lots_of_stuff_already_done = false;

$('.button').on('click', function(e) {
    if (lots_of_stuff_already_done) {
        lots_of_stuff_already_done = false; // reset flag
        return; // let the event bubble away
    }

    e.preventDefault();

    // do lots of stuff

    lots_of_stuff_already_done = true; // set flag
    $(this).trigger('click');
});

Более обобщенный вариант (с дополнительным преимуществом предотвращения загрязнения глобального пространства имен) может быть:

function onWithPrecondition(callback) {
    var isDone = false;

    return function(e) {
        if (isDone === true)
        {
            isDone = false;
            return;
        }

        e.preventDefault();

        callback.apply(this, arguments);

        isDone = true;
        $(this).trigger(e.type);
    }
}

Использование:

var someThingsThatNeedToBeDoneFirst = function() { /* ... */ } // do whatever you need
$('.button').on('click', onWithPrecondition(someThingsThatNeedToBeDoneFirst));

Бонусный супер-минималистичный плагин jQuery с поддержкой Promise:

(function( $ ) {
    $.fn.onButFirst = function(eventName,         /* the name of the event to bind to, e.g. 'click' */
                               workToBeDoneFirst, /* callback that must complete before the event is re-fired */
                               workDoneCallback   /* optional callback to execute before the event is left to bubble away */) {
        var isDone = false;

        this.on(eventName, function(e) {
            if (isDone === true) {
                isDone = false;
                workDoneCallback && workDoneCallback.apply(this, arguments);
                return;
            }

            e.preventDefault();

            // capture target to re-fire event at
            var $target = $(this);

            // set up callback for when workToBeDoneFirst has completed
            var successfullyCompleted = function() {
                isDone = true;
                $target.trigger(e.type);
            };

            // execute workToBeDoneFirst callback
            var workResult = workToBeDoneFirst.apply(this, arguments);

            // check if workToBeDoneFirst returned a promise
            if ($.isFunction(workResult.then))
            {
                workResult.then(successfullyCompleted);
            }
            else
            {
                successfullyCompleted();
            }
        });

        return this;
    };
}(jQuery));

Использование:

$('.button').onButFirst('click',
    function(){
        console.log('doing lots of work!');
    },
    function(){
        console.log('done lots of work!');
    });
68 голосов
/ 26 августа 2014

Более поздняя версия принятого ответа.

Краткая версия:

$('#form').on('submit', function(e, options) {
    options = options || {};

    if ( !options.lots_of_stuff_done ) {
        e.preventDefault();
        $.ajax({
            /* do lots of stuff */
        }).then(function() {
            // retrigger the submit event with lots_of_stuff_done set to true
            $(e.currentTarget).trigger('submit', { 'lots_of_stuff_done': true });
        });
    } else {
        /* allow default behavior to happen */
    }

});


Хороший вариант использования для чего-то подобного - это когда у вас может быть какой-то унаследованный код формы, который работает, но вас попросили улучшить форму, добавив что-то вроде проверки адреса электронной почты перед отправкой формы,Вместо того, чтобы копаться в почтовом коде серверной формы, вы можете написать API, а затем обновить свой код переднего плана, чтобы сначала использовать этот API, прежде чем позволить форме выполнять традиционный POST.

Для этого вы можете реализовать код, подобный тому, что я написал здесь:

$('#signup_form').on('submit', function(e, options) {
    options = options || {};

    if ( !options.email_check_complete ) {

        e.preventDefault(); // Prevent form from submitting.
        $.ajax({
            url: '/api/check_email'
            type: 'get',
            contentType: 'application/json',
            data: { 
                'email_address': $('email').val() 
            }
        })
        .then(function() {
            // e.type === 'submit', if you want this to be more dynamic
            $(e.currentTarget).trigger(e.type, { 'email_check_complete': true });
        })
        .fail(function() {
            alert('Email address is not valid. Please fix and try again.');
        })

    } else {

        /**
             Do traditional <form> post.
             This code will be hit on the second pass through this handler because
             the 'email_check_complete' option was passed in with the event.
         */

        $('#notifications').html('Saving your personal settings...').fadeIn();

    }

});
18 голосов
/ 25 сентября 2012

Вы можете сделать что-то вроде

$(this).unbind('click').click();
11 голосов
/ 14 октября 2015

Переопределить свойство isDefaultPrevented следующим образом:

$('a').click(function(evt){
  evt.preventDefault();

  // in async handler (ajax/timer) do these actions:
  setTimeout(function(){
    // override prevented flag to prevent jquery from discarding event
    evt.isDefaultPrevented = function(){ return false; }
    // retrigger with the exactly same event data
    $(this).trigger(evt);
  }, 1000);
}

ИМХО, это наиболее полный способ перезапуска события с точно такими же данными.

8 голосов
/ 26 февраля 2016

Можно использовать currentTarget из event.Пример показывает, как приступить к отправке формы.Аналогично, вы можете получить функцию из атрибута onclick и т. Д.

$('form').on('submit', function(event) {
  event.preventDefault();

  // code

  event.currentTarget.submit();
});
6 голосов
/ 30 сентября 2011

Только не выполняйте e.preventDefault(); и не выполняйте его условно.

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

Если вы хотите «воссоздать» исходное событие пользовательского интерфейса через некоторое время (скажем, в обратном вызове для запроса AJAX), вам просто нужно будет подделать его другим способом (как в ответе vzwick) ... хотя Я бы поставил под сомнение практичность такого подхода.

3 голосов
/ 12 июня 2018

Более поздний ответ умело использует jQuery.one()

$('form').one('submit', function(e) {
    e.preventDefault();
    // do your things ...

    // and when you done:
    $(this).submit();
});

https://stackoverflow.com/a/41440902/510905

3 голосов
/ 07 марта 2017

Подход, который я использую, таков:

$('a').on('click', function(event){
    if (yourCondition === true) { //Put here the condition you want
        event.preventDefault(); // Here triggering stops
        // Here you can put code relevant when event stops;
        return;
    }
    // Here your event works as expected and continue triggering
    // Here you can put code you want before triggering
});
3 голосов
/ 30 сентября 2011

, пока "много вещей" не делает что-то асинхронное, это абсолютно ненужно - событие будет последовательно вызывать каждый обработчик на своем пути, поэтому, если на родительском элементе происходит событие onklick, оно срабатывает послеonclik-событие ребенка обработано полностью.javascript здесь не выполняет какую-то «многопоточность», что делает необходимым «остановку» обработки событий.вывод: «приостанавливать» событие, просто чтобы возобновить его в том же обработчике, бессмысленнопоскольку это мешает асинхронным вещам делать то, что они должны делать (асинхронные вещи), и заставлять их вести себя так, как будто все в порядке (где мы возвращаемся к моему первому абзацу)

2 голосов
/ 25 декабря 2016

Принятое решение не будет работать, если вы работаете с тегом привязки.В этом случае вы не сможете снова щелкнуть ссылку после вызова e.preventDefault().Это потому, что событие click, сгенерированное jQuery, это просто слой поверх событий собственного браузера.Таким образом, запуск события click для тега привязки не будет переходить по ссылке.Вместо этого вы можете использовать библиотеку типа jquery-simulate , которая позволит вам запускать собственные события браузера.

Подробнее об этом можно узнать по этой ссылке

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...