Is there a [universal] way to invoke a default action after calling event.preventDefault()?

JavascriptJquery

Javascript Problem Overview


This question is for the purposes of developing jQuery plugins and other self-contained JavaScript snippets that don't require modifying other script files for compatibility.

We all know that event.preventDefault() will prevent the default event so we can run a custom function. But what if we want to simply delay the default event before invoking it? I've seen various, case-specific ninja tricks and workarounds to re-invoke the default action, but like I said, my interest is in a universal way to re-trigger the default, and not deal with default triggers on a case-by-case basis.

$(submitButton).click(function (e) {

    e.preventDefault();

    // Do custom code here.

    e.invokeDefault(); // Imaginary... :(
});

Even for something as simple as form submission, there seems to be no universal answer. The $(selector).closest("form").submit() workaround assumes that the default action is a standard form submission, and not something wacky like a __doPostBack() function in ASP.NET. To the end of invoking ASP.NET callbacks, this is the closest I've come to a universal, set-it-and-forget-it solution:

$(submitButton).click(function (e) {

    e.preventDefault();

    // Do custom code here.

    var javascriptCommand = e.currentTarget.attributes.href.nodeValue;
    evalLinkJs(javascriptCommand);
});


function evalLinkJs(link) {
    // Eat it, Crockford. :)
    eval(link.replace(/^javascript:/g, ""));
}

I suppose I could start writing special cases to handle normal links with a window.location redirect, but then we're opening a whole new can of worms--piling on more and more cases for default event invocation creates more problems than solutions.

So how about it? Who has the magic bullet that I've been searching for?

Javascript Solutions


Solution 1 - Javascript

Take a look at this one:

You could try

if(!event.mySecretVariableName) {
   event.preventDefault();
} else {
   return; // do nothing, let the event go
}

// your handling code goes here
event.originalEvent.mySecretVariableName = "i handled it";

if (document.createEvent) {
   this.dispatchEvent(event.originalEvent);
} else {
    this.fireEvent(event.originalEvent.eventType, event.originalEvent);
}

Using this answer: https://stackoverflow.com/questions/2490825/how-to-trigger-event-in-javascript and the jQuery event reference: http://api.jquery.com/category/events/event-object/

Tag the event object you receive so if you receive it again you don't loop.

Solution 2 - Javascript

Don't call preventDefault() in the first place. Then the default action will happen after your event handler.

Solution 3 - Javascript

This should work. I've only tested in firefox though.

<html>
<head>
<script>
    window.addEventListener("click",handleClick,false);
    function handleClick(e){
        if (e.useDefault != true){
            alert("we're preventing");
            e.preventDefault();
            alert(e.screenX);
            //Firing the regular action
            var evt = document.createEvent("HTMLEvents");
            evt.initEvent(e.type,e.bubbles,e.cancelable);
            evt["useDefault"] = true;
            //Add other "e" attributes like screenX, pageX, etc...
            this.dispatchEvent(evt);
        }
        else{
            alert("we're not preventing");
        }
    }
</script>
</head>
<body>

</body>
</html>

Of course, you'd have to copy over all the old event variables attributes too. I just didn't code that part, but it should be easy enough.

Solution 4 - Javascript

It's not possible like JamWaffles has already proven. Simple explanation why it's impossible: if you re-trigger the default action your event listener intercept again and you have an infinite loop.

And this

click(function (e) {
    e.preventDefault();
    // Do custom code here.
    e.invokeDefault(); // Imaginary... :(
});

is the same like this (with your imaginary function).

click(function (e) {
    // Do custom code here.
});

It seems that you want to manipulate the url of your clicked element. If you do it like this it just works fine. Example.

Solution 5 - Javascript

I needed to disable a button after click and then fire the default event, this is my solution

$(document).on('click', '.disabled-after-submit', function(event) {
    event.preventDefault();
    $(event.currentTarget).addClass('disabled');
    $(event.currentTarget).removeClass('disabled-after-submit');
    $(event.currentTarget).click();
    $(event.currentTarget).prop('disabled', true);
});

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJakeView Question on Stackoverflow
Solution 1 - JavascriptMike EdwardsView Answer on Stackoverflow
Solution 2 - JavascriptBenView Answer on Stackoverflow
Solution 3 - JavascriptAzmisovView Answer on Stackoverflow
Solution 4 - JavascriptstyrrView Answer on Stackoverflow
Solution 5 - JavascriptTomáš TibenskýView Answer on Stackoverflow