8
votes

Empêcher la fonction de tirer deux fois sur la mise en place de la mise au point et de cliquer sur

Je tente d'obtenir un événement pour tirer sur les deux Cliquez sur CODE> et FOCUS CODE>, mais je veux seulement que cela soit enfumel une fois. Lorsque je clique à l'intérieur d'une entrée, il tire deux fois (en cliquant sur et concentrer). Comment puis-je empêcher cela?

$('input').on('focus click', function(){
    console.log('fired');
});


1 commentaires

FWIW, j'ai mis à jour ma réponse originale avec un déboqueur à usage général.


3 Réponses :


10
votes

Vous pouvez utiliser .one code> à la place. Qui permettra uniquement à l'événement de tirer une fois, mais supprimera également la liaison une fois qu'il a été tiré:

var mouseDown, currentTarget;
$('input').on({
    "mousedown mouseup": function (e) {
        mouseDown = e.type === "mousedown";
        currentTarget = e.target;
    },
    "focus click": function (e) {
        if (mouseDown && currentTarget === e.target) return;
        console.log('fired');
    }
});


6 commentaires

Mais alors cela supprime la reliure ... qui n'est pas ce que je veux.


@kylex ajouté stopimmediatepropagation ainsi, ce qui devrait fonctionner ... Je dirais que c'est un bug que ce n'est pas le cas. Va chercher un peu plus parce que je n'aime pas la solution de T.j, même si cela fonctionne.


@Marcusekwall: StopimmediatePropagation arrête la propagation de Cet événement (par exemple, Cliquez sur ) à d'autres gestionnaires. Cela ne fait rien pour arrêter d'autres événements que le navigateur allume également comme un sous-produit de l'événement en cours (par exemple, Focus ).


Vient de réaliser un autre problème avec la dernière méthode. Cela ne fonctionne pas correctement si les événements FOCUS sont tirés des autres, car ils n'enregistrent pas le second Focus . @kylex puis-je demander pourquoi vous devez vous attaquer à cliquer sur tout, car un clic déclenchera la mise au point, il ne devrait pas être nécessaire?


@Marcusekwall, je lie les deux parce que ce n'est pas seulement une entrée qui l'active. Cela pourrait être un div ou une plage. Je n'ai montré qu'une entrée car c'est la balise qui provoque des problèmes.


@kklex Okey! Révisé ma réponse. Il comprend désormais une solution entièrement de travail.



8
votes

Un peu d'hystérésis peut être une option. Entrez fondamentalement la dernière fois que vous avez répondu à l'événement et ignorez les événements suivants dans un délai de garde.

vous pourrait em> utiliser code> code> pour cela (exemple à la fin de la réponse) , mais je préfère ceci: un déboqueur général: p>

Exemple en direct à l'aide de Cliquez sur et focus code> | Source en direct P>

$('input').on('focus click', function(){
    var $this = $(this);
    var now = +new Date();
    var lastClicked = $this.data("lastClicked");
    if (lastClicked && (now - lastClicked) < 100) {
        // Don't do anything
        return;
    }
    $this.data("lastClicked", now);

    // Do the work
});


3 commentaires

+1 Un peu hacky, mais un travail solide autour. (Je serais toujours au courant des cas de bord)


Le problème avec l'utilisation d'une hystérésis ou d'un déboqueur est que si vous cliquez sur l'entrée et maintenez le bouton pour plus de 100 ms, il déclenchera pour les deux Cliquez sur et FOCUS < / code>.


Underscore JS a une implémentation de DEBONCE Voir ici



1
votes

C'est une ancienne question, mais je n'ai pas pu trouver d'autres réponses comme ce qui résolu mon problème. Donc, je le pose ici pour que quiconque arrive à courir dans ce problème en 2015.

$('#menu-button').on('click focus', function(event) {
  if(event.type === 'focus') { // 1
    // Do stuff once
  }
});


1 commentaires

+1 Merci pour votre message. J'aime ton "meilleur moyen". Mais j'utilise la version 1.7.2 de JQuery qui me donne «focus» au lieu de «se concentrer». Merci pour une solution ligne.