8
votes

SettimeOUT et propagation d'événement

Je veux créer un événement ponctuel déclenché en cliquant n'importe où. Cet événement est créé en cliquant sur un bouton. Je ne veux pas que l'événement déclenche sur le bouton en cliquant sur le bouton, seuls les clics suivants n'importe où (y compris le bouton).

Ainsi, dites-le que je reçois des HTML comme ce qui suit: P>

$('#btn').click( function() {
  setTimeout(function() {
    $(document).one('click', function() {
      console.log('triggered');
    });
  }, 1);
});

$('#someparent').click(function() {
  // this must always be triggered
});


12 commentaires

Vous ne pouvez pas filer l'événement de clic et simplement retirer la poignée une fois que l'événement a été déclenché (sauf si la source est le bouton)?


Je ne suis pas sûr de comprendre ce que tu veux dire?


il suffit de retourner false pour empêcher Boubling


Je souhaite spécifiquement éviter l'annulation de la propagation des événements. Le bouton pourrait potentiellement avoir des parents qui souhaitent écouter dans l'événement de clic. C'est un exemple de réveillé dans ma question.


Wow, puis peut-être que le problème ici est la façon dont vous voulez la mettre en œuvre ... Pourquoi vous voulez lier un événement sans gérer la bulle?


Plus je lisais cela, plus je suis confus sur ce que vous voulez réaliser. Donc, vous cliquez sur 'x' et ensuite cela enregistre un événement sur le document. Pourquoi? Et pourquoi ne voulez-vous pas empêcher la propagation?


Si vous voulez tout bulter, restez simplement avec $ (document) .on ("Cliquez sur") Bien que je ne le recommande pas


Techunter: J'ai ajouté un violon. Mais il semble qu'Andrea Casaccia a déjà fourni une réponse.


ok je comprends mieux la question maintenant lol. Travailler avec Settimeout ne garantit jamais la commande et ne devrait jamais être utilisé pour résoudre le problème comme celui-ci. Casaccia a la bonne réponse


La réponse de Andrea Casaccia dit que la commande est garantie.


BTW Votre code dit .One ("Cliquez sur") au lieu de .on ("Cliquez sur") dans plusieurs taches.


Voir API.JQUERY.com/one


3 Réponses :


8
votes

Boubelle d'événement signifie que, après que un événement déclenche sur l'élément le plus profond possible, il déclenche ensuite les parents dans l'ordre de nidification.

de: https://developer.mozilla.org/ EN-US / DOCS / Web / JavaScript / EventLoop # Ajouter_messages

Ajout de messages

dans les navigateurs Web, des messages sont ajoutés à tout moment un événement survient et là-bas est un auditeur d'événements qui y est attaché. S'il n'y a pas d'auditeur, le L'événement est perdu. Donc un clic sur un élément avec un gestionnaire d'événements de clic ajoutera un message - de même avec n'importe quel autre événement.

appeler Settimeout ajoutera un message à la file d'attente après l'heure passé comme deuxième argument. S'il n'y a pas d'autre message dans la file d'attente, Le message est traité immédiatement; Cependant, s'il y a des messages, Le message Settimeout devra attendre que d'autres messages soient traité. Pour cette raison, le deuxième argument indique un minimum temps et pas un temps garanti.

Donc, le comportement que vous avez, n'est pas par hasard, vous êtes assuré que les messages de la file d'attente seront traités avant le traitement du message que vous ajoutez après un délai d'attente.


1 commentaires

Exactement ce que je cherchais. Cela garantit le comportement attendu. Merci.



2
votes

Ma compréhension de ce que vous voulez: après avoir cliqué sur un bouton "Activation", le clic suivant sur la page (y compris sur le bouton "Activation") devrait déclencher un événement spécial. Ceci est facilement géré avec un drapeau:

var activationFlag = false;

$('#btn').click(function(event){
  event.preventDefault();

  if(!activationFlag) {
    event.stopPropagation();
    console.log('Global event activated');
  }

  activationFlag = true;
});

$('#someparent').click(function(event){
  if(activationFlag) {
    console.log('Time for a special event');
  } else {
    event.preventDefault();
    event.stopPropagation();
  }
});


1 commentaires

Merci. C'est un exemple artificiel construit d'un problème mondial réel, il semble donc un peu bizarre. Il existe de nombreuses meilleures solutions que l'approche Settimeout que j'ai utilisé, mais je cherchais spécifiquement une réponse à si le comportement attendu était garanti. Je conviens toutefois qu'un drapeau est la solution appropriée dans ce cas, même si je n'éviterais pas l'arrêt de la propagation des événements comme vous le faites dans votre exemple.



2
votes

Voici une solution de contournement en utilisant un drapeau au lieu d'un deuxième événement:

var documentWaitingClick = false;
$(function() {
  $(document).on('click', function(e) {
    if (documentWaitingClick) {
      //simulate the "one"
      documentWaitingClick = false;
      console.log('document click');
    } else if (e.target.tagName === 'BUTTON') {
      documentWaitingClick = true;
      console.log('button click')
    }
  });
});


0 commentaires