No jQuery, como posso saber entre um clique programático e um clique do usuário?

91

Digamos que eu tenha um gerenciador de cliques definido:

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

});

Como posso, no manipulador de função, saber se o evento foi disparado programaticamente ou pelo usuário?

Kevin Owocki
fonte
Como o programa dispara um evento programaticamente?
Clayton
5
Por que você precisa distinguir os casos?
Damien_The_Unbeliever
@Clayton: $x.click()ou $x.trigger('click').
mu é muito curto
Tive uma situação com um controle deslizante de imagem que rolava automaticamente pelas imagens e fazia isso disparando cliques no item de navegação correto associado à imagem. O problema é que, quando o usuário clica no navegador, a rotação automática deve parar.
Kasapo
2
Isso funciona no último Firefox, Chrome e IE9. Por que não aceitar a resposta abaixo com o maior número de votos ?? @kevino
OZZIE

Respostas:

119

Você pode dar uma olhada no objeto de evento e. Se o evento foi disparado por um clique real, você vai ter coisas como clientX, clientY, pageX, pageY, etc. dentro ee eles vão ser números; esses números estão relacionados à posição do mouse quando o clique é acionado, mas provavelmente estarão presentes mesmo que o clique tenha sido iniciado pelo teclado. Se o evento foi disparado por $x.click(), você não terá os valores de posição usuais em e. Você também pode olhar para a originalEventpropriedade , que não deveria estar lá se o evento viesse $x.click().

Talvez algo assim:

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

E aqui está um pequeno sandbox para brincar: http://jsfiddle.net/UtzND/

mu é muito curto
fonte
4
Isso é incrível ... Eu só pensei "talvez os eventos disparados pelo jQuery não tenham informações de posição do mouse"! w00t!
Kasapo
2
Isso pode ser derrotado em navegadores que suportam createEvent. jsfiddle.net/UtzND/26
Joe Enzminger
2
@JoeEnzminger sim, mas por que você derrotaria seu próprio script, por assim dizer ...?
OZZIE
3
Estou preocupado com o fato de um script de terceiros gerar um evento de clique e meu script tratá-lo presumindo que foi gerado pelo usuário (um clique real).
Joe Enzminger,
2
@JoeEnzminger: Todas as apostas estão canceladas quando seu código está no navegador, não há nada que você possa fazer que não possa ser derrotado por uma pessoa suficientemente inteligente. Acho que o melhor que você pode fazer é verificar um monte de coisas: Existe um originalEvent? É o tipo de coisa certo? Existem coordenadas em algum lugar? As coordenadas são consistentes? As coordenadas estão dentro #foo? ...
mu é muito curto
44

Você pode usar um parâmetro extra conforme declarado no manual do gatilho jQuery :

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

$('#foo').trigger('click', ['Trigger']);
Shikiryu
fonte
3
O único problema que vejo com isso é que você não consegue distinguir entre um clique normal e $x.click(), o .click()chamador tem que dizer explicitamente que ele está fingindo. Isso pode ou não ser um problema, dependendo do que Kevin Owocki está fazendo.
mu é muito curto
1
@mu: Não entendo muito bem sua diferença entre um clique "normal" (usuário?) e o $x.click()que é o eventHandler (para clique do usuário, que pode ser "normal")
Shikiryu
1
A diferença é que um vem do usuário e o outro do software. O clique falso pode vir de um plugin ou algum outro código que não pode ser modificado para adicionar os argumentos extras. Não estou criticando sua solução, apenas observando alguns possíveis furos.
mu é muito curto
Embora mu esteja correto e isso não funcione em todas as situações, era exatamente o que eu estava procurando, obrigado! Não sabia que poderia passar o parâmetro extra como um var, mas isso é exatamente o que eu precisava para testar os cliques "reais" em uma interface do usuário complicada que trata alguns cliques "reais" como programáticos. Obrigado por ambas as soluções incrivelmente úteis!
Phil
9

Já há outra pergunta respondida.

Como detectar se um click () é um clique do mouse ou disparado por algum código?

Use a whichpropriedade do objeto de evento. Deve ser undefinedpara eventos acionados por código

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

Exemplo de JsFiddle - http://jsfiddle.net/interdream/frw8j/

Espero que ajude!

Swanidhi
fonte
2
Nem sempre funciona. Por exemplo select, daria um e.which==undefinedpar para um evento genuíno.
JNF
5

Tentei todas as soluções acima. Nada funcionou no meu caso. A solução abaixo funcionou para mim. Espero que ajude você também.

$(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
fonte
4

DOM Nível 3 especifica event.isTrusted. No momento, isso só é compatível com o IE9 + e o Firefox (com base em meus testes. Também li (embora não tenha pesquisado exaustivamente) que pode ser substituído em alguns navegadores e provavelmente ainda não está 100% pronto para ser realmente confiável (infelizmente).

Esta é uma versão modificada do violino de @ mu que funciona no IE e no Firefox.

Joe Enzminger
fonte
Bom ponto. Eu não acho que nada será 100% sólido. Você teria que misturar alguns testes para ver se isTrustedé compatível e não gravável. Acho que a verdadeira resposta depende do porquê dessa pergunta e nunca descobrimos o porquê.
mu é muito curto
@mu, cheguei a esta questão depois de fazer uma semelhante, mas mais geral. Meu caso "por que" é que quero ter certeza de que estou apenas executando uma ação (uma transação financeira, embora pequena) se o usuário tiver realizado uma ação afirmativa direta na página.
Joe Enzminger
1

Solução Vanila js:

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

Não vai participar na discussão intelectual, o código que funcionou para mim para filtrar .click()e .trigger('click')é-

$(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
fonte