Estou tentando fazer o seguinte, algo aparentemente simples.
Se for pressionada uma tecla que teria digitado um caractere em um campo de entrada de texto, e esse pressionamento de tecla ainda não for feito em outro lugar (por exemplo, nenhum campo de entrada teve o foco), então focalize um campo de entrada específico e digite o caractere lá.
Isso evita que os usuários cliquem com o mouse em um navegadorjogo que requer respostas rápidas, mas também pode ser usado em, digamos, um aplicativo de bate-papo. Se o usuário acidentalmente esqueceu de focar neste campo de entrada (grande e óbvio), quero lidar com isso com elegância e não puni-lo.
Ressalvas:
- Se algum campo de entrada estiver em foco, o evento deve ir para lá e em nenhum outro lugar.
- As teclas que não digitam caracteres (Enter, teclas de seta, PgUp, PgDn, ...) devem ser deixadas com seu comportamento padrão.
Usando jQuery, eu vim com algo assim:
$(document).keypress(function(e) {
var input = $("#my-input-field");
if (e.which >= " " && !input.is(":focus")) {
input.focus();
input.trigger(e);
e.preventDefault();
}
});
No entanto, isso não funciona, por dois motivos:
- Os eventos ainda borbulham até
document
mesmo se um determinado campo de entrada os tratar. Soluções possíveis:- Ligar
keypress
manipuladores de eventos para todos os campos de entrada e chamadasstopPropagation
em cada um, mas isso soa como um hack horrível esperando para dar errado. - Verifique no manipulador acima se um campo de entrada está atualmente em foco e ignore-o em caso afirmativo, mas parece que estarei perdendo alguns casos em que algo mais está usando os pressionamentos de tecla.
- Ligar
- Chamando
.trigger(e)
não funciona. Ele chama meus manipuladores de eventos personalizados, mas não aciona o padrãokeypress
comportamento de realmente inserir o personagem.
Qual é a saída mais limpa?
Respostas:
5 para resposta № 1Pensando bem, os eventos disparam nesta ordem: keydown
, keyup
, keypress
.
Você pode usar algo como:
$(document.body).on("keydown", function(e) {
if(document.activeElement.tagName.toLowerCase() != "input") {
$("#my-default-input").focus();
}
});
Então, o evento keydown vai terminar, vai mais tardedisparar o evento keyup (no campo agora focado) e deve gravar o caractere no campo e, em seguida, disparar o evento keypress que outros eventos (se houver) vinculados ao campo podem usar.
O conteúdo da instrução if pode ser alterado para filtrar certos pressionamentos de tecla ou para adicionar outras marcas, como <canvas>
para a lista "não toque".
Observe também que não testei isso, mas teoricamente deve funcionar. :)
1 para resposta № 2
Você não pode acionar manualmente um pressionamento de tecla para um usuário (potencial violação de segurança), todos trigger()
neste caso, é disparar quaisquer ouvintes de evento atribuídos ao evento de pressionamento de tecla. Você pode modificar o valor da caixa de texto usando .val (). Basta adicionar o personagem a ele.
Você pode testar para ver se o pressionamento de tecla foi feito em uma caixa de texto com if($(e.target).is("input"))
no ouvinte de pressionamento de tecla do documento. Você também pode adicionar um cheque "textarea"
se você desejar.