Подтвердить что ты не робот

Как инициировать событие после использования event.preventDefault()

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

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

   e.preventDefault(); 

   // do lots of stuff

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

}

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

4b9b3361

Ответ 1

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

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

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 (workResult && $.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!');
    });

Ответ 2

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

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

$('#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();

    }

});

Ответ 3

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

$(this).unbind('click').click();

Ответ 4

Отмените свойство 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);
}

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

Ответ 5

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

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

  // code

  event.currentTarget.submit();
});

Ответ 6

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

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

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

Ответ 7

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

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

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

fooobar.com/questions/110356/...

Ответ 8

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

если "много вещей" является чем-то асинхронным, это также не имеет смысла, поскольку это мешает асинхронным вещам делать то, что они должны делать (асинхронный материал), и сделать их bahave, как будто все происходит последовательно (где мы возвращаемся к мой первый абзац)

Ответ 9

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

$('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
});

Ответ 10

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

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

Ответ 11

Другим решением является использование window.setTimeout в прослушивателе событий и выполнение кода после завершения процесса события. Что-то вроде...

window.setTimeout(function() {
  // do your thing
}, 0);

Я использую 0 за период, так как меня не волнует ожидание.

Ответ 12

Я знаю, что эта тема устарела, но я думаю, что могу внести свой вклад. Вы можете инициировать поведение события по умолчанию для определенного элемента в любое время в вашей функции обработчика, если вы уже знаете это поведение. Например, когда вы вызываете событие click на кнопке reset, вы фактически вызываете функцию reset в ближайшей форме как поведение по умолчанию. В функции обработчика после использования функции preventDefault вы можете вызвать поведение по умолчанию, вызвав функцию reset в ближайшей форме в любом месте вашего кода обработчика.

Ответ 13

Если этот пример может помочь, добавьте "пользовательское подтверждение popin" на некоторые ссылки (я сохраняю код "$.ui.Modal.confirm", это просто пример для обратного вызова, который выполняет исходное действие):

//Register "custom confirm popin" on click on specific links
$(document).on(
    "click", 
    "A.confirm", 
    function(event){
        //prevent default click action
        event.preventDefault();
        //show "custom confirm popin"
        $.ui.Modal.confirm(
            //popin text
            "Do you confirm ?", 
            //action on click 'ok'
            function() {
                //Unregister handler (prevent loop)
                $(document).off("click", "A.confirm");
                //Do default click action
                $(event.target)[0].click();
            }
        );
    }
);