Wie triggers man ein Ereignis nach der Verwendung von event.preventDefault () aus?

Ich möchte ein Ereignis halten, bis ich bereit bin es zu zünden

$('.button').live('click', function(e){ e.preventDefault(); // do lots of stuff e.run() //this proceeds with the normal event } 

Gibt es ein Äquivalent zur oben beschriebenen function run() ?

   

Nee. Sobald die Veranstaltung abgesagt wurde, wird sie abgesagt.

Sie können das Ereignis jedoch später erneut auslösen, indem Sie mithilfe eines Flags feststellen, ob Ihr benutzerdefinierter Code bereits ausgeführt wurde oder nicht (z. B. dies (ignorieren Sie bitte die eklatante Namensraumverschmutzung):

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

Eine generalisiertere Variante (mit dem zusätzlichen Vorteil, die globale Namensraumverschmutzung zu vermeiden) könnte sein:

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

Verwendung:

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

Bonus super-minimalistisches jQuery-Plugin mit Promise Unterstützung:

 (function( $ ) { $.fn.onButFirst = function(eventName, /* the name of the event to bind to, eg '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)); 

Verwendung:

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

Eine neuere Version der akzeptierten Antwort.

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


Ein guter Anwendungsfall für etwas Ähnliches ist, wo Sie möglicherweise einen Legacy-Formularcode haben, der funktioniert, aber Sie wurden gebeten, das Formular zu erweitern, indem Sie vor dem Senden des Formulars etwas wie die validation der E-Mail-Adresse hinzufügen. Anstatt den Back-End-Formularpostcode zu durchsuchen, könnten Sie eine API schreiben und dann Ihren Frontend-Code aktualisieren, um zuerst auf diese API zu treffen, bevor Sie dem Formular erlauben, seinen traditionellen POST auszuführen.

Um dies zu tun, können Sie Code ähnlich dem, was ich hier geschrieben habe, implementieren:

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

Sie können etwas wie tun

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

isDefaultPrevented die Eigenschaft isDefaultPrevented wie 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, dies ist die vollständigste Möglichkeit, das Ereignis mit den exakt gleichen Daten erneut zu triggern.

Es ist möglich currentTarget des event . Das Beispiel zeigt, wie mit dem Senden des Formulars verfahren wird. Genauso könnten Sie die function von onclick Attribut usw. bekommen.

 $('form').on('submit', function(event) { event.preventDefault(); // code event.currentTarget.submit(); }); 

e.preventDefault(); einfach nicht e.preventDefault(); oder führen Sie es bedingt aus.

Sie können sicherlich nicht ändern, wenn die ursprüngliche Ereignisaktion auftritt.

Wenn Sie das originale UI-Ereignis einige Zeit später “neu erstellen” wollen (zB im Callback für eine AJAX-Anfrage), dann müssen Sie es nur auf eine andere Art vortäuschen (wie in Vzwicks Antwort) … obwohl ich es tun würde Frage die Brauchbarkeit eines solchen Ansatzes.

Der Ansatz, den ich verwende, ist folgender:

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

Solange “viele Sachen” nicht etwas Asynchrones tun, ist dies absolut unnötig – das Event ruft nacheinander jeden Handler auf seinem Weg auf. Wenn es also ein onklick-Event auf einem Eltern-Element gibt, feuert dies nach dem Onclik- Ereignis des Kindes hat vollständig verarbeitet. Javascript macht hier keine Art von “Multithreading”, was das “Stoppen” der Ereignisverarbeitung notwendig macht. Fazit: “pausieren” eines Ereignisses, nur um es in der gleichen Handler wieder aufzunehmen, macht keinen Sinn.

Wenn “viel Zeug” etwas Asynchrones ist, macht das auch keinen Sinn, da es verhindert, dass die asketischen Dinge tun, was sie tun sollen (asynchrones Zeug) und sie dazu bringen, wie alles in einer Reihenfolge zu sein (wo wir zu meinem ersten Absatz zurückkehren) )

Die akzeptierte Lösung funktioniert nicht, wenn Sie mit einem Anker-Tag arbeiten. In diesem Fall können Sie nach dem Aufruf von e.preventDefault() nicht mehr auf den Link klicken. Das liegt daran, dass das von jQuery erzeugte click-Ereignis nur eine Ebene über nativen Browserereignissen ist. Das Auslösen eines “Klick” -Ereignisses auf einem Anker-Tag folgt also nicht dem Link. Stattdessen könnten Sie eine Bibliothek wie jquery-simulate verwenden , mit der Sie native Browser-Ereignisse starten können.

Weitere Details dazu finden Sie in diesem Link

Eine andere Lösung besteht darin, window.setTimeout im Ereignis-Listener zu verwenden und den Code auszuführen, nachdem der Ereignisprozess beendet wurde. Etwas wie…

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

Ich benutze 0 für den Zeitraum, da es mir egal ist, zu warten.

Ich weiß, dass dieses Thema alt ist, aber ich denke, ich kann dazu beitragen. Sie können das Standardverhalten eines Ereignisses für ein bestimmtes Element jederzeit in Ihrer Handler-function auslösen, wenn Sie dieses Verhalten bereits kennen. Wenn Sie beispielsweise das Click-Ereignis auf der Schaltfläche zum Zurücksetzen auslösen, rufen Sie die Reset-function in der nächsten Form als Standardverhalten auf. Nachdem Sie die preventDefault-function verwendet haben, können Sie in der Handler-function das Standardverhalten aufrufen, indem Sie die reset-function auf der nächstgelegenen Form irgendwo in Ihrem Handler-Code aufrufen.

Eine neuere Antwort verwendet gekonnt jQuery.one()

 $('form').one('submit', function(e) { e.preventDefault(); // do your things ... // and when you done: $(this).submit(); }); 

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