56 votes

Existe-t-il un moyen [universel] d'invoquer une action par défaut après avoir appelé event.preventDefault() ?

Cette question a pour but de développer des plugins jQuery et d'autres extraits JavaScript autonomes qui ne nécessitent pas de modifier d'autres fichiers script pour des raisons de compatibilité.

Nous savons tous que event.preventDefault() empêchera l'événement par défaut afin que nous puissions exécuter une fonction personnalisée. Mais que se passe-t-il si nous voulons simplement retarder l'événement par défaut avant de l'invoquer ? J'ai vu plusieurs astuces de ninja et de contournement pour ré-invoquer l'action par défaut, mais comme je l'ai dit, je suis intéressé par un moyen universel de redéclencher l'événement par défaut, et non pas de traiter les déclencheurs par défaut au cas par cas.

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

    e.preventDefault();

    // Do custom code here.

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

Même pour quelque chose d'aussi simple que la soumission d'un formulaire, il ne semble pas y avoir de réponse universelle. Le site $(selector).closest("form").submit() suppose que l'action par défaut est une soumission de formulaire standard, et non pas quelque chose de farfelu comme une __doPostBack() dans ASP.NET. Jusqu'à la fin de l'invocation des callbacks ASP.NET, c'est ce qui se rapproche le plus d'une solution universelle, du genre "on met tout en place et on oublie tout" :

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

Je suppose que je pourrais commencer à écrire des cas spéciaux pour gérer des liens normaux avec un window.location rediriger, mais alors nous ouvrons une toute nouvelle boîte de Pandore - empiler de plus en plus de cas pour l'invocation d'événements par défaut crée plus de problèmes que de solutions.

Alors, qu'en pensez-vous ? Qui a la solution magique que je cherche ?

2 votes

Je ne comprends pas vraiment ce que tu essaies de faire... le code du gestionnaire d'événement n'exécute-t-il pas avant l'action par défaut se produit (par exemple, un submit le code du gestionnaire d'événement s'exécutera avant que le formulaire ne soit réellement soumis... n'est-ce pas ce que vous essayez d'obtenir ?)

2 votes

Votre code personnalisé est-il asynchrone ? Cela pourrait expliquer pourquoi vous pensez avoir besoin d'une telle méthode, mais même si vous disposez de cette méthode imaginaire, cela ne résoudra pas votre problème.

1 votes

Tu as vraiment besoin d'être plus clair sur ce que tu veux. Si vous voulez exécuter du code dans le gestionnaire, ce code s'exécute de toute façon avant le comportement "par défaut".

13voto

Mike Edwards Points 2609

Jetez un coup d'oeil à celui-ci :

Vous pouvez essayer

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

En utilisant cette réponse : Comment déclencher un événement en JavaScript ? et la référence de l'événement jQuery : http://api.jquery.com/category/events/event-object/

Marquez l'objet de l'événement que vous recevez de sorte que si vous le recevez à nouveau, vous ne ferez pas de boucle.

13voto

Ben Points 2009

N'appelez pas preventDefault() en premier lieu. L'action par défaut se produira alors après votre gestionnaire d'événement.

15 votes

C'est la bonne réponse tant que vous n'avez pas besoin d'effectuer le traitement par défaut de manière asynchrone après votre traitement personnalisé.

0 votes

Pas de vrai dans mon copy j'ai besoin de retourner true pour le texte à copier. Ne rien faire ou renvoyer des valeurs erronées ne fonctionne pas non plus. Mais ce n'est pas la question de l'OP.

4voto

Azmisov Points 1229

Cela devrait fonctionner. Je n'ai testé qu'avec Firefox.

<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>

Bien sûr, il faudrait aussi copier tous les anciens attributs des variables d'événements. Je n'ai pas codé cette partie, mais cela devrait être assez facile.

2 votes

+1 C'est la bonne approche. Vous devriez essayer de créer le bon type d'événement - voir developer.mozilla.org/fr/US/docs/DOM/document.createEvent

3voto

styrr Points 717

Ce n'est pas possible comme JamWaffles l'a déjà prouvé. L'explication simple de cette impossibilité est la suivante : si vous redéclenchez l'action par défaut, votre écouteur d'événements intercepte à nouveau et vous obtenez une boucle infinie.

Et ceci

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

est le même comme ceci (avec votre fonction imaginaire).

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

Il semble que vous vouliez manipuler l'url de l'élément cliqué. Si vous le faites de cette façon, cela fonctionne bien. Ejemplo .

0voto

Tomáš Tibenský Points 321

J'avais besoin de désactiver un bouton après le clic et de déclencher l'événement par défaut, voici ma 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);
});

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X