Dans jQuery, comment puis-je distinguer un clic programmatique et utilisateur?

91

Disons que j'ai un gestionnaire de clics défini:

$("#foo").click(function(e){

});

Comment puis-je, dans le gestionnaire de fonctions, savoir si l'événement a été déclenché par programme ou par l'utilisateur?

Kevin Owocki
la source
Comment le programme déclenche-t-il un événement par programmation?
Clayton
5
Pourquoi avez-vous besoin de distinguer les cas?
Damien_The_Unbeliever
@Clayton: $x.click()ou $x.trigger('click').
mu est trop court
J'ai eu une situation avec un curseur d'image qui faisait automatiquement défiler les images, et je l'ai fait en déclenchant des clics sur l'élément de navigation correct associé à l'image. Le problème est que lorsque l'utilisateur clique sur la navigation, la rotation automatique doit s'arrêter.
Kasapo
2
Cela fonctionne dans les derniers Firefox, Chrome et IE9. Pourquoi ne pas accepter la réponse ci-dessous avec les votes les plus élevés ?? @kevino
OZZIE

Réponses:

119

Vous pouvez jeter un œil à l'objet événement e. Si l'événement a été déclenché par un vrai clic, vous aurez des choses comme clientX, clientY, pageX, pageY, etc. à l' intérieur eet ils seront chiffres; ces chiffres sont liés à la position de la souris lorsque le clic est déclenché mais ils seront probablement présents même si le clic a été initié via le clavier. Si l'événement a été déclenché par, $x.click()vous n'aurez pas les valeurs de position habituelles dans e. Vous pouvez également regarder la originalEventpropriété , qui ne devrait pas être là si l'événement venait $x.click().

Peut-être quelque chose comme ça:

$("#foo").click(function(e){
    if(e.hasOwnProperty('originalEvent'))
        // Probably a real click.
    else
        // Probably a fake click.
});

Et voici un petit bac à sable avec lequel jouer: http://jsfiddle.net/UtzND/

mu est trop court
la source
4
C'est génial ... Je me suis juste dit "peut-être que les événements déclenchés par jQuery n'ont pas d'informations sur la position de la souris"! w00t!
Kasapo
2
Cela peut être résolu dans les navigateurs prenant en charge createEvent. jsfiddle.net/UtzND/26
Joe Enzminger
2
@JoeEnzminger oui mais pourquoi voudriez-vous vaincre votre propre script pour ainsi dire ...?
OZZIE
3
Je suis préoccupé par un script tiers générant un événement de clic et mon script le gérant en supposant qu'il a été généré par l'utilisateur (un clic réel).
Joe Enzminger
2
@JoeEnzminger: Tous les paris sont ouverts une fois que votre code est dans le navigateur, vous ne pouvez rien faire qui ne puisse être vaincu par une personne suffisamment intelligente. Je pense que le mieux que vous puissiez faire est de vérifier un tas de choses: y a-t-il un originalEvent? Est-ce la bonne sorte de chose? Y a-t-il des coordonnées quelque part? Les coordonnées sont-elles cohérentes? Les coordonnées sont-elles à l'intérieur #foo? ...
mu est trop court
44

Vous pouvez utiliser un paramètre supplémentaire comme indiqué dans le manuel du déclencheur jQuery :

$("#foo").click(function(e, from){
    if (from == null)
        from = 'User';
    // rest of your code
});

$('#foo').trigger('click', ['Trigger']);
Shikiryu
la source
3
Le seul problème que je vois avec cela est que vous ne pouvez pas faire la distinction entre un clic normal et $x.click(), l' .click()appelant doit vous dire explicitement qu'il le simule. Cela peut ou non être un problème en fonction de ce que Kevin Owocki fait.
mu est trop court
1
@mu: Je ne comprends pas très bien votre différence entre un clic "normal" (utilisateur?) et $x.click()quel est le gestionnaire d'événement (pour un clic utilisateur, qui peut être "normal")
Shikiryu
1
La différence est que l'un vient de l'utilisateur mais l'autre du logiciel. Le faux clic peut provenir d'un plugin ou d'un autre code qui ne peut pas être modifié pour ajouter les arguments supplémentaires. Je ne critique pas votre solution, je note simplement quelques trous possibles.
mu est trop court
Bien que mu soit correct et que cela ne fonctionnera pas dans toutes les situations, c'était exactement ce que je cherchais, merci! Je ne savais pas que je pouvais passer le paramètre supplémentaire comme un var, mais c'est exactement ce dont j'avais besoin pour tester les "vrais" clics dans une interface utilisateur compliquée qui traite certains "vrais" clics comme programmatiques. Merci pour les deux solutions incroyablement utiles!
Phil
9

Il y a déjà une autre question répondue.

Comment détecter si un clic () est un clic de souris ou déclenché par un code?

Utilisez la whichpropriété de l'objet événement. Cela devrait être undefinedpour les événements déclenchés par le code

$("#someElem").click(function(e) {
    if (e.which) {
        // Actually clicked
    } else {
        // Triggered by code
    }
});

Exemple JsFiddle - http://jsfiddle.net/interdream/frw8j/

J'espère que ça aide!

Swanidhi
la source
2
Ça ne marche pas toujours. Par exemple select, donnerait un e.which==undefinedmême pour un événement authentique.
JNF
5

J'ai essayé toutes les solutions ci-dessus, rien n'a été travaillé dans mon cas. La solution ci-dessous a fonctionné pour moi. J'espère que cela vous aidera également.

$(document).ready(function(){
  //calling click event programmatically
    $("#chk1").trigger("click");
});

$(document).on('click','input[type=checkbox]',function(e) {
		if(e.originalEvent.isTrusted==true){
			alert("human click");
		}
		else{
			alert("programmatically click");
		}
    
    });
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.3.1.min.js">
</script>

<input type="checkbox" id="chk1" name="chk1" >Chk1</input>
<input type="checkbox" id="chk2" name="chk2" >Chk2</input>
<input type="checkbox" id="chk3" name="chk3" >Chk3</input>

GSB
la source
4

DOM Niveau 3 spécifie event.isTrusted. Ceci n'est actuellement pris en charge que dans IE9 + et Firefox (sur la base de mes tests. J'ai également lu (bien que pas de recherches approfondies) qu'il peut être remplacé dans certains navigateurs et n'est probablement pas encore prêt à 100% à faire confiance (malheureusement).

Il s'agit d'une version modifiée du violon de @ mu qui fonctionne sur IE et Firefox.

Joe Enzminger
la source
Bon point. Je ne pense pas que quoi que ce soit sera solide à 100%. Vous devrez mélanger certains tests pour voir si isTrustedest pris en charge et non inscriptible. Je pense que la vraie réponse dépend du pourquoi de cette question et nous n'avons jamais su pourquoi.
mu est trop court
@mu, je suis venu à cette question après avoir posé une question similaire, mais plus générale. Mon cas «pourquoi» est que je veux m'assurer que je n'effectue qu'une action (une transaction financière, quoique minime) si l'utilisateur a pris une action positive directe sur la page.
Joe Enzminger
1

Solution Vanila js:

document.querySelector('button').addEventListener('click', function (e){
    if(e.isTrusted){
        // real click.
    }else{
        // programmatic click
    }
});
Abhishek
la source
-1

Je ne vais pas participer à la discussion intellectuelle, le code qui a fonctionné pour moi pour filtrer .click()et .trigger('click')est-

$(document).on('click touchstart', '#my_target', function(e) {
    if (e.pageX && e.pageY) { // To check if it is not triggered by .click() or .trigger('click')
        //Then code goes here
    }
});
Sahu V Kumar
la source