Verifique se o evento é acionado por um ser humano

140

Eu tenho um manipulador anexado a um evento e gostaria que ele fosse executado apenas se for acionado por um humano, e não por um método trigger (). Como eu digo a diferença?

Por exemplo,

$('.checkbox').change(function(e){
  if (e.isHuman())
  {
    alert ('human');
  }
});

$('.checkbox').trigger('change'); //doesn't alert
Dziamid
fonte

Respostas:

212

Você pode verificar e.originalEvent: se estiver definido, o clique é humano:

Veja o violino http://jsfiddle.net/Uf8Wv/

$('.checkbox').change(function(e){
  if (e.originalEvent !== undefined)
  {
    alert ('human');
  }
});

meu exemplo no violino:

<input type='checkbox' id='try' >try
<button id='click'>Click</button>

$("#try").click(function(event) {
    if (event.originalEvent === undefined) {
        alert('not human')
    } else {
        alert(' human');
    }


});

$('#click').click(function(event) {
    $("#try").click();
});
Nicola Peluchetti
fonte
1
@ Nicola Isso está documentado em algum lugar?
Šime Vidas
@ Time eu não sei, mas acho que é padrão. veja aqui: api.jquery.com/category/events/event-object
Nicola Peluchetti
@ Nicola vejo, é uma coisa jQuery. O jQuery armazena o objeto de evento original dentro dessa propriedade. Btw, o que você quer dizer com não sabe? Você acabou de fornecer o link para a documentação:)
Šime Vidas
1
Parece que você também pode usarevent.isTrigger
avoliva 28/05
1
@ Anurag, eu estava correndo para o mesmo problema agora. Parece que o jQuery é preenchido originalEventquando o evento é acionado DOM.click(), mas você pode usar $($("#try")[0]).click();, o que é desajeitado, mas funciona.
113016 Daniel Garrett
19

Mais direto do que acima seria:

$('.checkbox').change(function(e){
  if (e.isTrigger)
  {
    alert ('not a human');
  }
});

$('.checkbox').trigger('change'); //doesn't alert
Kenneth Spencer
fonte
Esta é a melhor resposta. Para obter uma explicação, consulte: stackoverflow.com/questions/10704168/...
jaredjacobs
3
Embora isso seja tentador e provavelmente confortável na prática, observe que os desenvolvedores do jQuery não desejam passar isTriggerpara a API pública a partir desse momento .
23413 Jon
7

Eu acho que a única maneira de fazer isso seria passar um parâmetro adicional na triggerchamada conforme a documentação .

$('.checkbox').change(function(e, isTriggered){
  if (!isTriggered)
  {
    alert ('human');
  }
});

$('.checkbox').trigger('change', [true]); //doesn't alert

Exemplo: http://jsfiddle.net/wG2KY/

detaylor
fonte
1
você pode conferir o originalEvent propriedade do objeto de evento: se o evento não vem de um clique, é indefinido
Nicola Peluchetti
1
Por alguma razão, o event.originalEvent não estava funcionando para mim (apenas continuei pressionando 1) ao usar o manipulador 'click' do Zepto. Então, eu tentei a solução acima. Funcionou como um encanto.
Larrydx
7

A resposta aceita não funcionou para mim. Faz 6 anos e o jQuery mudou muito desde então.

Por exemplo, event.originalEventretorna sempre truecom o jQuery 1.9.x. Quero dizer, o objeto sempre existe, mas o conteúdo é diferente.

Quem usa versões mais recentes do jQuery pode tentar este. Funciona no Chrome, Edge, IE, Opera, FF

if ((event.originalEvent.isTrusted === true && event.originalEvent.isPrimary === undefined) || event.originalEvent.isPrimary === true) {
    //Hey hooman it is you
}
Ergec
fonte
3

Atualmente, a maioria dos navegadores oferece suporte a event.isTrusted :

if (e.isTrusted) {
  /* The event is trusted: event was generated by a user action */
} else {
  /* The event is not trusted */
}

Dos documentos :

O IsTrusted propriedade somente leitura da Eventinterface é uma Boolean que é verdade quando o evento foi gerado por uma ação do usuário, e falsa quando o evento foi criado ou modificado por um script ou expedidos via EventTarget.dispatchEvent () .

felipsmartins
fonte
0

Você pode usar onmousedown para detectar o clique do mouse vs a chamada trigger ().

boateng
fonte
Talvez eu não trabalhe no seguinte cenário: Às vezes é possível selecionar os elementos da página usando a tecla Tab. Por exemplo, se eu tiver selecionado dessa maneira uma caixa de seleção, posso marcar / desmarcar usando a tecla de espaço. Ou abra um drodpdown usando a tecla de seta para baixo.
Diego Favero
0

Eu pensaria em uma possibilidade em que você verifica a posição do mouse, como:

  • Clique
  • Obter posição do mouse
  • Sobrepõe as cordas do botão
  • ...
Lucas
fonte
Talvez eu não trabalhe no seguinte cenário: Às vezes é possível selecionar os elementos da página usando a tecla Tab. Por exemplo, se eu tiver selecionado dessa maneira uma caixa de seleção, posso marcar / desmarcar usando a tecla de espaço. Ou abra um drodpdown usando a tecla de seta para baixo.
Diego Favero
0

Incase você tem o controle de todo o seu código, não chamadas de alienígenas $(input).focus()do que setFocus().

Usar uma variável global é uma maneira correta para mim.

var globalIsHuman = true;

$('input').on('focus', function (){
    if(globalIsHuman){
        console.log('hello human, come and give me a hug');
    }else{
        console.log('alien, get away, i hate you..');
    }
    globalIsHuman = true;
});

// alien set focus
function setFocus(){
    globalIsHuman = false;
    $('input').focus();
}
// human use mouse, finger, foot... whatever to touch the input

Se algum alienígena ainda quiser ligar $(input).focus()de outro planeta. Boa sorte ou verifique outras respostas

vanduc1102
fonte
Isso apenas impede que as pessoas liguem setFocus()- não impede que as pessoas acionem o evento de foco. Não escrever setFocus()também impediria as pessoas de chamá-lo, então não vejo o benefício. De fato, as pessoas ainda podem ligar $('input').focus()e passar.
Rob
uau, primeira vez que alguém comenta logo após responder à pergunta, atualizo a resposta
vanduc1102
Se você estiver trabalhando em um ambiente fechado sem outro script de terceiros, isso funcionaria em um mundo perfeito. No entanto, as aplicações mais práticas são para sites clientes com todos os tipos de plugins e scripts adicionados a eles que muito bem podem chamar esse foco. Uma coisa que pode ajudar nisso é agrupar seu código (e qualquer código que precise chamar essa função) em uma função de escopo como esta: (function(){/*your code here*/})();Isso impediria a função setFocus de ser chamada e o booleano de ser alterado por scripts externos.
Xandor 13/11/19