86 votes

Comment poursuivre la propagation des événements après une annulation ?

Lorsqu'un utilisateur clique sur un certain lien, j'aimerais lui présenter une boîte de dialogue de confirmation. S'il clique sur "Oui", j'aimerais poursuivre la navigation initiale. Un hic : mon dialogue de confirmation est mis en œuvre en renvoyant un objet jQuery.Deferred qui n'est résolu que si l'utilisateur clique sur le bouton "Oui". Le dialogue de confirmation est donc asynchrone.

En gros, je veux quelque chose comme ça :

$('a.my-link').click(function(e) {
  e.preventDefault(); e.stopPropogation();
  MyApp.confirm("Are you sure you want to navigate away?")
    .done(function() {
      //continue propogation of e
    })
})

Bien sûr, je pourrais placer un drapeau et redéclencher le clic, mais c'est très compliqué. Y a-t-il un moyen naturel de faire cela ?

1 votes

Avez-vous essayé $this.trigger(e); ( éditer qui aurait besoin d'un drapeau s'il fonctionnait) ou $this.parent().trigger(e) (dans le callback), où $this se réfère aux éléments cliqués ?

0 votes

@FelixKling Cela ne fonctionnera pas car e.preventDefault(); e.stopPropogation(); a envoyé des drapeaux sur e. S'il existait un moyen d'envoyer une copie de e à e2, je pourrais appeler quelque chose du genre e.handler(e2) ce qui, à mon avis, devrait fonctionner.

0 votes

Je me suis dit que jQuery était peut-être assez intelligent pour réinitialiser les drapeaux lorsqu'ils sont transmis à trigger ...

0voto

Karuna Lakshman Points 26

Nous avons un besoin similaire dans notre projet et cela fonctionne pour moi. Testé dans chrome et IE11.

$('a.my-link').click(function(e) {
  e.preventDefault(); 
  if (do_something === true) {
    e.stopPropogation();
    MyApp.confirm("Are you sure you want to navigate away?")
    .done(function() {
      do_something = false;
      // this allows user to navigate 
      $(e.target).click();
    })
  }

})

0voto

Yura Kosyak Points 332

J'ai modifié votre code. Nouvelles fonctionnalités que j'ai ajoutées :

  1. Ajout d'un espace de noms à l'événement ;
  2. Après avoir cliqué sur un élément, l'événement sera supprimé par l'espace de noms ;
  3. Enfin, après avoir terminé les actions nécessaires dans la section "MyApp", la propagation se poursuit en déclenchant les événements de "clic" d'autres éléments.

Code :

$('a.my-link').on("click.myEvent", function(e) {
  var $that = $(this);
  $that.off("click.myEvent");
  e.preventDefault();
  e.stopImmediatePropagation();
  MyApp.confirm("Are you sure you want to navigate away?")
    .done(function() {
        //continue propogation of e
        $that.trigger("click");
    });
});

-2voto

irishbuzz Points 1692

Cette solution n'a pas été testée mais elle pourrait vous permettre de contourner le problème.

$('a.my-link').click(function(e) {
  e.preventDefault(); e.stopPropogation();
  MyApp.confirm("Are you sure you want to navigate away?")
    .done(function() {
      //continue propogation of e
      $(this).unbind('click').click()
  })
})

0 votes

Cela aurait pour effet de délier tous les gestionnaires d'événements de clics ! De plus, cette garde ne se produirait qu'une seule fois, de sorte que toute mise en cache de la page côté client serait annulée. J'ai des solutions de contournement, mais je me demande s'il n'y a pas quelque chose de plus idiomatique.

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