Armadilha a tecla enter, mas não ao escolher sugestão autocomplete do navegador
-
22-07-2019 - |
Pergunta
Eu tenho algumas caixas de texto em uma página e eu quero clicar em um link quando o usuário pressiona entrar em nenhum deles.
Eu posso facilmente prender o botão entrar usando javascript (por olhar para 13 em event.keyCode
e event.which
), mas eu bati um problema quando do navegador recurso de preenchimento automático entra em ação e sugere o que o usuário pode querer digitar. Estamos descobrindo os usuários muitas vezes Pressione Enter para aceitar a sugestão do navegador, em vez de guia. Isso confunde os usuários como o link é clicado imediatamente, enquanto eles ainda pretende inserir texto em alguns dos outros campos.
Eu sei que seria melhor usar um formulário e um botão de envio aqui, mas por várias razões que não é prático.
Eu estou usando jQuery, tão à vontade para oferecer soluções jQuery.
Solução
usuário sempre tem que pressionar a tecla para baixo, se optar por seleccionar um dos o direito automático de texto completo, por que não criar uma variável para algo quando pressione a tecla para baixo, e, em seguida, se eles fazem a introduzir imprensa depois você verificar o variável. Você não deve fazer a função de ligação clique se a variável é definida, caso contrário, fazê-lo como normal.
Outras dicas
Usando a ideia de tuanvt na resposta aceita, eu escrevi um plugin jQuery que faz o trabalho.
posso controlar quando o usuário pressiona para cima, para baixo, page-up e page-down chaves para dizer quando eles estão na caixa de preenchimento automático. Todas as outras chaves implica que eles deixaram-lo.
I garantir que apenas aplicar essas regras para caixas de texto:. Todos os outros elementos de entrada comportar normalmente
Opera já faz um trabalho muito bom do que eu estava tentando alcançar, então eu não cumprir minhas regras nesse navegador -. Caso contrário, o usuário teria que pressione Enter duas vezes
Testado no IE6, IE7, IE8, Firefox 3.5.5, o Google Chrome 3.0, Safari 4.0.4, Opera 10.00.
Está disponível em jquery.com como a SafeEnter plug-in . Para sua conveniência, o código para versão 1.0 é a seguinte:
// jQuery plugin: SafeEnter 1.0
// http://plugins.jquery.com/project/SafeEnter
// by teedyay
//
// Fires an event when the user presses Enter, but not whilst they're in the browser's autocomplete suggestions
//codesnippet:2e23681e-c3a9-46ce-be93-48cc3aba2c73
(function($)
{
$.fn.listenForEnter = function()
{
return this.each(function()
{
$(this).focus(function()
{
$(this).data('safeEnter_InAutocomplete', false);
});
$(this).keypress(function(e)
{
var key = (e.keyCode ? e.keyCode : e.which);
switch (key)
{
case 13:
// Fire the event if:
// - we're not currently in the browser's Autocomplete, or
// - this isn't a textbox, or
// - this is Opera (which provides its own protection)
if (!$(this).data('safeEnter_InAutocomplete') || !$(this).is('input[type=text]') || $.browser.opera)
{
$(this).trigger('pressedEnter', e);
}
$(this).data('safeEnter_InAutocomplete', false);
break;
case 40:
case 38:
case 34:
case 33:
// down=40,up=38,pgdn=34,pgup=33
$(this).data('safeEnter_InAutocomplete', true);
break;
default:
$(this).data('safeEnter_InAutocomplete', false);
break;
}
});
});
};
$.fn.clickOnEnter = function(target)
{
return this.each(function()
{
$(this)
.listenForEnter()
.bind('pressedEnter', function()
{
$(target).click();
});
});
};
})(jQuery);
Tente configurar o autocomplete fora em sua caixa de seleção, embora este não é padrão para todos os navegador, mas ele funciona em navegadores comuns.
<input type="text" autocomplete="off" />
JQuery é bom e tudo, mas por que não usar JavaScript simples?
function submit_on_enter(e) {
var keycode;
if (window.event) keycode = window.event.keyCode;
else if (e) keycode = (e.keyCode ? e.keyCode : e.which);
else return true;
if (keycode == 13) {
if (window.previousKeyCode) {
// down=40,up=38,pgdn=34,pgup=33
if (window.previousKeyCode == 33 || window.previousKeyCode == 34 ||
window.previousKeyCode == 39 || window.previousKeyCode == 40) {
window.previousKeyCode = keycode;
return true;
}
}
submit_form();
return false;
} else {
window.previousKeyCode = keycode;
return true;
}
}
rastrear tecla enter no evento keyup, a seleção é completada pelo tempo que você detectar tecla enter no evento keyup.
detectar tecla enter em keydown e fazer operação de interferir com a funcionalidade de preenchimento automático.
Isso funciona para mim:
$('input').keypress(function(e) {
if(e.which == 13) {
if(this.value)
{
$("#submitbutton").click();
}
}
});
Se você estiver usando os novos tipos de campo de formulário html5, você pode querer código alter de teedyay da seguinte forma:
case 13:
// Fire the event if:
// - we're not currently in the browser's Autocomplete, or
// - this isn't a textbox, or
// - this is Opera (which provides its own protection)
if (!$(this).data('safeEnter_InAutocomplete') || !$(this).is('input([type=text],[type=email],[type=number],[type=search],[type=tel],[type=url])') || $.browser.opera)
{
...
Observe os novos tipos de entrada.
Eu não tenho certeza se você está prendendo teclas pressionadas na janela, ou em elementos DOM específicos. Você deve fazer o último (por exemplo, sobre o elemento form
), então em seu manipulador de eventos, olhar para o objeto de evento para determinar qual elemento DOM foi a origem do evento. Se este era um campo de texto com autocomplete, então return false;
.
Dê uma olhada .keypress()
manipulador de eventos do jQuery, e event.target
propriedade do objeto de evento.
Eu enfrentei o mesmo problema e embora não seja perfeito eu usei uma outra abordagem que eu considero mais simples. Ao criar o autocomplete I definir a hora para o evento select e depois compará-lo antes de tomar quaisquer ações:
$('#completer').autocomplete({
source: ['First', 'Last'], delay: 0, minLength: 0,
select: function(ev, ui) {
$(ev.target).data('lastAutocompleteSelectTimestamp', new Date().getTime())
}
})
$(document).on('keydown', '#completer', function(ev){
if (ev.which != 13) return
var lastAutocompletionTime = $(ev.currentTarget).data('lastAutocompleteSelectTimestamp')
if (!lastAutocompletionTime || (new Date().getTime() - lastAutocompletionTime) > 100)
alert('Enter pressed outside autocomplete context')
})
<html>
<head>
<link href="https://code.jquery.com/ui/1.11.0/themes/smoothness/jquery-ui.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.11.0/jquery-ui.min.js"></script>
</head>
<body>
<input id=completer type=text />
</body>
</html>
Outra abordagem (mais seguro) é usar os eventos keyup
e keydown
para detectar alterações de valor.
Autocomplete define o valor depois caso keyDown
. Quando são observados ambos os eventos, o seguinte é muito mais confiável do que as outras soluções:
var tempValue;
// fire when enter is 1. pressed and 2. released
function handlerEnter(type){
// save the value for comparison
if(type == 'keyDown'){
tempValue = document.activeElement.value;
return null; // quit
}
// quit when the value changed in between keyDown & keyUp
if(type == 'keyUp' && tempValue != document.activeElement.value){
return null;
}
// autocomplete wasn't used
doStuff();
}
Você pode querer verificar se document.activeElement é uma entrada. Sinta-se livre para usar meu mal extensão protótipo .