Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to trigger an event after using event.preventDefault()

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?

like image 682
Mazatec Avatar asked Sep 30 '11 13:09

Mazatec


People also ask

How do I override event preventDefault?

The easiest way to do this is to do $("#new_form")[0]. submit() , it will bypass any jQuery bound handlers and submit the form.

What does event preventDefault () do?

preventDefault() The preventDefault() method of the Event interface tells the user agent that if the event does not get explicitly handled, its default action should not be taken as it normally would be.

What's the difference between event preventDefault () and event stopPropagation () methods?

preventDefault() prevents the default browser behavior for a given element. stopPropagation() stops an event from bubbling or propagating up the DOM tree. Whereas, return false is a combination of both preventDefault() and stopPropagation() .


2 Answers

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:

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

Usage:

$('.button').onButFirst('click',     function(){         console.log('doing lots of work!');     },     function(){         console.log('done lots of work!');     }); 
like image 136
vzwick Avatar answered Sep 20 '22 11:09

vzwick


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.

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();      }  }); 
like image 30
Cory Danielson Avatar answered Sep 22 '22 11:09

Cory Danielson