.keyCode vs. .which

228

Eu pensei que isso seria respondido em algum lugar no Stack Overflow, mas não consigo encontrá-lo.

Se estou ouvindo um evento de pressionamento de tecla, devo usar .keyCodeou .whichpara determinar se a tecla Enter foi pressionada?

Eu sempre fiz algo como o seguinte:

$("#someid").keypress(function(e) {
  if (e.keyCode === 13) {
    e.preventDefault();
    // do something
  }
});

Mas estou vendo exemplos que usam em .whichvez de .keyCode. Qual é a diferença? Um é mais compatível com vários navegadores que o outro?

ScottE
fonte

Respostas:

209

Nota: A resposta abaixo foi escrito em 2010. Aqui, muitos anos depois, ambos keyCodee whichsão preteridos em favor de key(para a chave lógico) e code(para a colocação física da chave). Mas observe que o IE não suporta code, e seu suporte keyé baseado em uma versão mais antiga da especificação, portanto, não é bem correto. Enquanto escrevo isso, o Edge atual baseado no EdgeHTML e no Chakra também não é compatível code, mas a Microsoft está lançando seu substituto para o Edge, baseado em Blink e V8 , que provavelmente é necessário.


Alguns navegadores usam keyCode, outros usam which.

Se você estiver usando jQuery, poderá usá-lo com segurança, whichpois o jQuery padroniza as coisas ; Mais aqui.

Se você não estiver usando jQuery, poderá fazer o seguinte:

var key = 'which' in e ? e.which : e.keyCode;

Ou alternativamente:

var key = e.which || e.keyCode || 0;

... que lida com a possibilidade que e.whichpossa existir 0(restaurando isso 0no final, usando o ||operador curiosamente poderoso do JavaScript ).

TJ Crowder
fonte
2
Thanks TJ Onde eu encontraria uma referência para isso? Não que eu não acredite em você, estou apenas curioso! ... Vejo que você acabou de adicionar isso, obrigado. Portanto, mesmo para quem não usa jquery, qual é a melhor opção?
precisa
7
@ ScottE: Se não estiver usando o jQuery, você deverá lidar com isso explicitamente. Eu costumo fazer assim: var key = event.which || event.keyCode;Isso será usado event.whichse for definido e não como falsey, ou event.keyCodese whichfor indefinido ou falsey. Tecnicamente eu provavelmente deveria fazer, var key = typeof event.which === "undefined" ? event.keyCode : event.which;mas se event.whichfor 0(pode ser 0?), É improvável que eu me importe com o tipo de coisa que faço.
TJ Crowder
2
@ Scott, aqui está uma referência básica: quirksmode.org/js/keys.html (não inclui which, o que eu acho que é fornecido apenas pelo jQuery, mas não tenho 100% de certeza, mas você deve começar a ver diferenças nos navegadores)
Mottie
1
@ fudgey: whiché fornecido keypresspor todos os navegadores, exceto o IE. E o modo quirks não é autorizado aqui. Como referência, o link que a @TJ Crowder postou é muito melhor: unixpapa.com/js/key.html .
Tim Down
5
@TJ Crowder: Sim, a whichpropriedade do evento pode ser zero, e isso pode fazer uma grande diferença para a maioria dos aplicativos. Por exemplo, chaves não imprimíveis no Firefox têm uma whichpropriedade zero e a mesma keyCodepropriedade que keydown. A tecla Home possui um keyCodede 36 no meu PC no Firefox, que é o código de caractere para "$", o que tornaria impossível distinguir entre o usuário pressionando a tecla Home e o usuário digitando um caractere $ usando event.which || event.keyCode.
Tim Down
32

jQuery normaliza event.whichdependendo se event.which, event.keyCodeou event.charCodeé suportado pelo navegador:

// Add which for key events
if ( event.which == null && (event.charCode != null || event.keyCode != null) ) {
   event.which = event.charCode != null ? event.charCode : event.keyCode;
}

Um benefício adicional .whiché que o jQuery também faz isso por cliques do mouse:

// Add which for click: 1 === left; 2 === middle; 3 === right
// Note: button is not normalized, so don't use it
if ( !event.which && event.button !== undefined ) {
    event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
}
David Tang
fonte
2
var key = event.which || event.charCode || event.keyCode
Anne van Rossum
@ anne-van-rossum, event.wich == null && ...teste apenas para nulo ou indefinido. seu event.wich || ...teste de falsidade (indefinido, nulo, falso, 0, '' etc.)
aMarCruz 22/15/15
@aMarCruz Falsy de propósito. Por exemplo, bugs.webkit.org/show_bug.cgi?id=16735 com os relatórios do Webkit 0. E eu não acho que procurar ""ou []machucar.
Anne van Rossum
20

Se você estiver em Javascript baunilha, observe que o keyCode agora está obsoleto e será descartado:

Esse recurso foi removido dos padrões da Web. Embora alguns navegadores ainda possam suportá-lo, ele está sendo eliminado. Evite usá-lo e atualize o código existente, se possível; consulte a tabela de compatibilidade na parte inferior desta página para orientar sua decisão. Esteja ciente de que esse recurso pode deixar de funcionar a qualquer momento

https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode

Em vez disso, use: .key ou .code, dependendo do comportamento desejado: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code https://developer.mozilla.org/en -US / docs / Web / API / KeyboardEvent / key

Ambos são implementados em navegadores modernos.

slykat
fonte
.code corresponde à localização física da tecla no teclado, enquanto .key corresponde ao caractere gerado pela tecla pressionada, independentemente da localização.
Christopher
1
Tanto o 'código' quanto a 'chave' têm peculiaridades nos navegadores modernos. O uso do exemplo "Experimente" no MDN developer.mozilla.org/pt-BR/docs/Web/API/KeyboardEvent/code em navegadores diferentes mostra que o IE11 / IE Edge não implementa 'código' e a 'chave' A implementação não corresponde à implementação no Chrome / FF / Safari (as diferenças parecem estar principalmente nos caracteres de controle como Escape e Enter). Eu acho que usar uma biblioteca pode ser mais fácil, a menos que você esteja disposto a explicar esses caprichos. Eu realmente quero que isso seja a resposta, mas parafusos IE até um presente :-(
Akrikos
Hmm ... na verdade, não parece tão ruim implementar a chave de uma maneira entre navegadores. As teclas alfanuméricas comuns retornam seu valor e as teclas de controle (escape, enter, tab, etc.) aparecem implementadas de forma idêntica na maioria dos navegadores, exceto o IE11 / Edge, que implementa uma versão mais antiga da especificação, portanto, pelo menos, existem apenas dois valores possíveis para cada chave.
Akrikos
Eu recomendaria usar em keyvez de code. Por exemplo, se você possui um teclado com teclas de controle de mídia, pressionar Reproduzir / Pausar gera "MediaPlayPause" para keye "" para code.
thdoan
6

veja isso: https://developer.mozilla.org/en-US/docs/Web/API/event.keyCode

Em um evento de pressionamento de tecla, o valor Unicode da tecla pressionada é armazenado na propriedade keyCode ou charCode, nunca em ambas. Se a tecla pressionada gerar um caractere (por exemplo, 'a'), charCode será definido como o código desse caractere, respeitando a letra maiúscula. (ou seja, charCode leva em consideração se a tecla Shift é pressionada). Caso contrário, o código da tecla pressionada é armazenado em keyCode. keyCode é sempre definido nos eventos keydown e keyup. Nesses casos, o charCode nunca é definido. Para obter o código da chave, independentemente de ela estar armazenada em keyCode ou charCode, consulte a propriedade. Os caracteres inseridos por meio de um IME não são registrados por keyCode ou charCode.

Leo
fonte
6

Eu recomendo event.keyatualmente. Documentos MDN: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key

event.KeyCodee event.whichambos têm avisos desaprovados desagradáveis ​​no topo de suas páginas MDN:
https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode https://developer.mozilla.org/en-US / docs / Web / API / KeyboardEvent / which

Para chaves alfanuméricas, event.keyparece ser implementado de forma idêntica em todos os navegadores. Para chaves de controle (tab, enter, escape, etc), event.keytem o mesmo valor no Chrome / FF / Safari / Opera, mas um valor diferente no IE10 / 11 / Edge (os IEs aparentemente usam uma versão mais antiga da especificação, mas se combinam como de 14 de janeiro de 2018).

Para chaves alfanuméricas, uma verificação seria algo como:

event.key === 'a'

Para caracteres de controle, você precisa fazer algo como:

event.key === 'Esc' || event.key === 'Escape'

Usei o exemplo aqui para testar em vários navegadores (tive que abrir no codepen e editar para que ele funcionasse com o IE10): https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/ código

event.code é mencionado em uma resposta diferente como uma possibilidade, mas o IE10 / 11 / Edge não a implementa; portanto, está fora se você deseja suporte ao IE.

Akrikos
fonte
2

Uma robusta biblioteca Javascript para capturar a entrada do teclado e as combinações de teclas inseridas. Não possui dependências.

http://jaywcjlove.github.io/hotkeys/

hotkeys('ctrl+a,ctrl+b,r,f', function(event,handler){
    switch(handler.key){
        case "ctrl+a":alert('you pressed ctrl+a!');break;
        case "ctrl+b":alert('you pressed ctrl+b!');break;
        case "r":alert('you pressed r!');break;
        case "f":alert('you pressed f!');break;
    }
});

teclas compreende os seguintes modificadores de: , shift, option, , alt, ctrl, control, command, e .

As seguintes teclas especiais podem ser usados para atalhos: backspace, tab, clear, enter, return, esc, escape, space, up, down, left, right, home, end, pageup, pagedown, del, deletee f1através f19.

小弟 调 调
fonte
Porém, ele arrisca Array.prototype.index; portanto, se você estiver usando isso em outra biblioteca, pode não ser adequado, pois modifica o escopo global. Também parece usar o obsoleto event.keyCode.
Akrikos
Esta biblioteca não detectou Fn no meu laptop Vaio.
thdoan
0

No Firefox, a propriedade keyCode não funciona no evento onkeypress (retornará apenas 0). Para uma solução entre navegadores, use a propriedade which juntamente com keyCode, por exemplo:

var x = event.which || event.keyCode;  // Use either which or keyCode, depending on browser support
Pankaj Chauhan
fonte