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?
The easiest way to do this is to do $("#new_form")[0]. submit() , it will bypass any jQuery bound handlers and submit the form.
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.
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() .
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!'); });
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(); } });
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With