如何在使用event. preventdefault()之后触发事件

时间:2023-01-10 00:03:38

I want to hold an event until I am ready to fire it e.g

我想办一件事,直到我准备就绪为止

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

   e.preventDefault(); 

   // do lots of stuff

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

}

Is there an equivalent to the run() function described above?

是否存在与上面描述的run()函数等价的函数?

12 个解决方案

#1


113  

Nope. Once the event has been canceled, it is canceled.

不。一旦事件被取消,它就被取消。

You can re-fire the event later on though, using a flag to determine whether your custom code has already run or not - such as this (please ignore the blatant namespace pollution):

稍后您可以重新启动事件,使用一个标志来确定您的自定义代码是否已经运行——例如这样(请忽略明显的名称空间污染):

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

A more generalized variant (with the added benefit of avoiding the global namespace pollution) could be:

更广义的变体(避免全局命名空间污染的附加好处)可能是:

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

Usage:

用法:

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

Bonus super-minimalistic jQuery plugin with Promise support:

极简的jQuery插件,承诺支持:

(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));

Usage:

用法:

$('.button').onButFirst('click',
    function(){
        console.log('doing lots of work!');
    },
    function(){
        console.log('done lots of work!');
    });

#2


56  

A more recent version of the accepted answer.

一个更近期的答案。

Brief version:

简短的版本:

$('#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 */
    }

});



A good use case for something like this is where you may have some legacy form code that works, but you've been asked to enhance the form by adding something like email address validation before submitting the form. Instead of digging through the back-end form post code, you could write an API and then update your front-end code to hit that API first before allowing the form to do it's traditional POST.

对于类似这样的东西,一个很好的用例是您可能有一些可以工作的遗留表单代码,但是您被要求在提交表单之前添加电子邮件地址验证之类的东西来增强表单。您可以编写一个API,然后更新前端代码,在允许表单执行传统的post操作之前,首先访问该API。

To do that, you can implement code similar to what I've written here:

为此,您可以实现类似于我在这里所写的代码:

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


16  

You can do something like

你可以做一些类似的事情

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

#4


8  

Override the property isDefaultPrevented like this:

重写财产被像这样阻止:

$('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, this is most complete way of retriggering the event with the exactly same data.

IMHO,这是用完全相同的数据重新触发事件的最完整的方法。

#5


6  

It is possible to use currentTarget of the event. Example shows how to proceed with form submit. Likewise you could get function from onclick attribute etc.

可以使用事件的currentTarget。示例显示如何继续提交表单。同样,你也可以从onclick属性中获得函数等等。

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

  // code

  event.currentTarget.submit();
});

#6


5  

Just don't perform e.preventDefault();, or perform it conditionally.

只是不要执行e.preventDefault();或有条件地执行它。

You certainly can't alter when the original event action occurs.

当原始事件发生时,您当然不能更改。

If you want to "recreate" the original UI event some time later (say, in the callback for an AJAX request) then you'll just have to fake it some other way (like in vzwick's answer)... though I'd question the usability of such an approach.

如果您想要“重新创建”最初的UI事件(例如,在AJAX请求的回调中),那么您只需以其他方式伪造它(如vzwick的答案)……尽管我怀疑这种方法的可用性。

#7


4  

The approach I use is this:

我使用的方法是:

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

#8


3  

as long as "lots of stuff" isn't doing something asynchronous this is absolutely unneccessary - the event will call every handler on his way in sequence, so if theres a onklick-event on a parent-element this will fire after the onclik-event of the child has processed completely. javascript doesn't do some kind of "multithreading" here that makes "stopping" the event processing neccessary. conclusion: "pausing" an event just to resume it in the same handler doesn't make any sense.

只要“很多东西”没有异步执行,这绝对是不必要的——事件将按顺序调用每个处理程序,因此,如果在父元素上有一个onklick事件,该事件将在子元素的onclik-event被完全处理后触发。javascript在这里不做某种“多线程”,这使得“停止”事件处理变得必要。结论:“暂停”事件只是在同一个处理程序中恢复它没有任何意义。

if "lots of stuff" is something asynchronous this also doesn't make sense as it prevents the asynchonous things to do what they should do (asynchonous stuff) and make them bahave like everything is in sequence (where we come back to my first paragraph)

如果"很多东西"是异步的这也没有意义因为它阻止了异步的东西去做它们应该做的事情(异步的东西)并使它们像所有东西都是有序的一样(我们回到第一段)

#9


1  

Another solution is to use window.setTimeout in the event listener and execute the code after the event's process has finished. Something like...

另一个解决方案是使用窗口。当事件进程结束后,在事件监听器中设置setTimeout并执行代码。之类的……

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

I use 0 for the period since I do not care about waiting.

我用0表示周期,因为我不在乎等待。

#10


1  

The accepted solution wont work in case you are working with an anchor tag. In this case you wont be able to click the link again after calling e.preventDefault(). Thats because the click event generated by jQuery is just layer on top of native browser events. So triggering a 'click' event on an anchor tag wont follow the link. Instead you could use a library like jquery-simulate that will allow you to launch native browser events.

当您使用锚标记时,接受的解决方案不会起作用。在这种情况下,您不能在调用e.preventDefault()之后再次单击该链接。这是因为jQuery生成的单击事件只是在本机浏览器事件之上的一层。因此,在锚标记上触发“单击”事件不会跟随链接。您可以使用jquery- simulation这样的库来启动本地浏览器事件。

More details about this can be found in this link

更多的细节可以在这个链接中找到

#11


0  

I know this topic is old but I think I can contribute. You can trigger the default behavior of an event on a specific element any time in your handler function if you already know that behavior. For example, when you trigger the click event on the reset button, you actually call the reset function on the closest form as the default behavior. In your handler function, after using the preventDefault function, you can recall the default behavior by calling the reset function on the closest form anywhere in your handler code.

我知道这个话题已经过时了,但我认为我可以做点贡献。如果您已经知道该行为,则可以在处理程序函数的任何时候触发特定元素上的事件的默认行为。例如,当您触发reset按钮上的click事件时,您实际上将最近表单上的reset函数调用为默认行为。在处理程序函数中,在使用了preventDefault函数之后,您可以通过调用处理程序代码中最接近的窗体上的reset函数来回忆默认行为。

#12


0  

A more recent answer skillfully uses jQuery.one()

最近的答案巧妙地使用了jQuery.one()

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

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

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

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

#1


113  

Nope. Once the event has been canceled, it is canceled.

不。一旦事件被取消,它就被取消。

You can re-fire the event later on though, using a flag to determine whether your custom code has already run or not - such as this (please ignore the blatant namespace pollution):

稍后您可以重新启动事件,使用一个标志来确定您的自定义代码是否已经运行——例如这样(请忽略明显的名称空间污染):

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

A more generalized variant (with the added benefit of avoiding the global namespace pollution) could be:

更广义的变体(避免全局命名空间污染的附加好处)可能是:

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

Usage:

用法:

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

Bonus super-minimalistic jQuery plugin with Promise support:

极简的jQuery插件,承诺支持:

(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));

Usage:

用法:

$('.button').onButFirst('click',
    function(){
        console.log('doing lots of work!');
    },
    function(){
        console.log('done lots of work!');
    });

#2


56  

A more recent version of the accepted answer.

一个更近期的答案。

Brief version:

简短的版本:

$('#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 */
    }

});



A good use case for something like this is where you may have some legacy form code that works, but you've been asked to enhance the form by adding something like email address validation before submitting the form. Instead of digging through the back-end form post code, you could write an API and then update your front-end code to hit that API first before allowing the form to do it's traditional POST.

对于类似这样的东西,一个很好的用例是您可能有一些可以工作的遗留表单代码,但是您被要求在提交表单之前添加电子邮件地址验证之类的东西来增强表单。您可以编写一个API,然后更新前端代码,在允许表单执行传统的post操作之前,首先访问该API。

To do that, you can implement code similar to what I've written here:

为此,您可以实现类似于我在这里所写的代码:

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


16  

You can do something like

你可以做一些类似的事情

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

#4


8  

Override the property isDefaultPrevented like this:

重写财产被像这样阻止:

$('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, this is most complete way of retriggering the event with the exactly same data.

IMHO,这是用完全相同的数据重新触发事件的最完整的方法。

#5


6  

It is possible to use currentTarget of the event. Example shows how to proceed with form submit. Likewise you could get function from onclick attribute etc.

可以使用事件的currentTarget。示例显示如何继续提交表单。同样,你也可以从onclick属性中获得函数等等。

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

  // code

  event.currentTarget.submit();
});

#6


5  

Just don't perform e.preventDefault();, or perform it conditionally.

只是不要执行e.preventDefault();或有条件地执行它。

You certainly can't alter when the original event action occurs.

当原始事件发生时,您当然不能更改。

If you want to "recreate" the original UI event some time later (say, in the callback for an AJAX request) then you'll just have to fake it some other way (like in vzwick's answer)... though I'd question the usability of such an approach.

如果您想要“重新创建”最初的UI事件(例如,在AJAX请求的回调中),那么您只需以其他方式伪造它(如vzwick的答案)……尽管我怀疑这种方法的可用性。

#7


4  

The approach I use is this:

我使用的方法是:

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

#8


3  

as long as "lots of stuff" isn't doing something asynchronous this is absolutely unneccessary - the event will call every handler on his way in sequence, so if theres a onklick-event on a parent-element this will fire after the onclik-event of the child has processed completely. javascript doesn't do some kind of "multithreading" here that makes "stopping" the event processing neccessary. conclusion: "pausing" an event just to resume it in the same handler doesn't make any sense.

只要“很多东西”没有异步执行,这绝对是不必要的——事件将按顺序调用每个处理程序,因此,如果在父元素上有一个onklick事件,该事件将在子元素的onclik-event被完全处理后触发。javascript在这里不做某种“多线程”,这使得“停止”事件处理变得必要。结论:“暂停”事件只是在同一个处理程序中恢复它没有任何意义。

if "lots of stuff" is something asynchronous this also doesn't make sense as it prevents the asynchonous things to do what they should do (asynchonous stuff) and make them bahave like everything is in sequence (where we come back to my first paragraph)

如果"很多东西"是异步的这也没有意义因为它阻止了异步的东西去做它们应该做的事情(异步的东西)并使它们像所有东西都是有序的一样(我们回到第一段)

#9


1  

Another solution is to use window.setTimeout in the event listener and execute the code after the event's process has finished. Something like...

另一个解决方案是使用窗口。当事件进程结束后,在事件监听器中设置setTimeout并执行代码。之类的……

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

I use 0 for the period since I do not care about waiting.

我用0表示周期,因为我不在乎等待。

#10


1  

The accepted solution wont work in case you are working with an anchor tag. In this case you wont be able to click the link again after calling e.preventDefault(). Thats because the click event generated by jQuery is just layer on top of native browser events. So triggering a 'click' event on an anchor tag wont follow the link. Instead you could use a library like jquery-simulate that will allow you to launch native browser events.

当您使用锚标记时,接受的解决方案不会起作用。在这种情况下,您不能在调用e.preventDefault()之后再次单击该链接。这是因为jQuery生成的单击事件只是在本机浏览器事件之上的一层。因此,在锚标记上触发“单击”事件不会跟随链接。您可以使用jquery- simulation这样的库来启动本地浏览器事件。

More details about this can be found in this link

更多的细节可以在这个链接中找到

#11


0  

I know this topic is old but I think I can contribute. You can trigger the default behavior of an event on a specific element any time in your handler function if you already know that behavior. For example, when you trigger the click event on the reset button, you actually call the reset function on the closest form as the default behavior. In your handler function, after using the preventDefault function, you can recall the default behavior by calling the reset function on the closest form anywhere in your handler code.

我知道这个话题已经过时了,但我认为我可以做点贡献。如果您已经知道该行为,则可以在处理程序函数的任何时候触发特定元素上的事件的默认行为。例如,当您触发reset按钮上的click事件时,您实际上将最近表单上的reset函数调用为默认行为。在处理程序函数中,在使用了preventDefault函数之后,您可以通过调用处理程序代码中最接近的窗体上的reset函数来回忆默认行为。

#12


0  

A more recent answer skillfully uses jQuery.one()

最近的答案巧妙地使用了jQuery.one()

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

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

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

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