Ловушка введите ключ, но не при выборе варианта автозаполнения браузера
У меня есть текстовые поля на странице, и я хочу щелкнуть ссылку, когда пользователь нажимает кнопку ввода в любом из них.
Я могу легко уловить кнопку ввода с помощью javascript (путем поиска 13 в event.keyCode
и event.which
), но я столкнулся с проблемой, когда функция автозаполнения браузера запускается и предлагает то, что пользователь может захотеть напечатать. Мы находим, что пользователи часто нажимают кнопку ввода, чтобы принять предложение браузера, а не вкладку. Это смущает пользователей при немедленном нажатии ссылки, тогда как они по-прежнему предназначены для ввода текста в некоторые другие поля.
Я знаю, что было бы лучше использовать форму и кнопку отправки здесь, но по разным причинам это не практично.
Я использую jQuery, поэтому не стесняйтесь предлагать решения jQuery.
Ответы
Ответ 1
Пользователь всегда должен нажимать клавишу "вниз", если они выбирают правильный текст с полным полным текстом, почему бы не установить переменную на что-то, когда они нажимают клавишу "вниз", а затем, если они нажимают клавишу "Enter", после этого вы проверяете переменная. Вы не должны использовать функцию щелчка ссылки, если переменная установлена, в противном случае это делается как обычно.
Ответ 2
Используя идею tuanvt в принятом ответе, я написал плагин jQuery, который выполняет задание.
Я отслеживаю, когда пользователь нажимает клавиши "вверх", "вниз", "вверх" и "вниз", чтобы указать, когда они находятся в поле автозаполнения. Все остальные клавиши подразумевают, что они оставили его.
Я гарантирую, что мы применяем эти правила только к текстовым полям: все остальные элементы ввода ведут себя нормально.
Opera уже делает довольно хорошую работу над тем, чего я пытаюсь достичь, поэтому я не применяю свои правила в этом браузере - иначе пользователь должен будет дважды нажать клавишу.
Протестировано в IE6, IE7, IE8, Firefox 3.5.5, Google Chrome 3.0, Safari 4.0.4, Opera 10.00.
Он доступен на jquery.com в качестве плагина SafeEnter. Для вашего удобства, код для версии 1.0 выглядит следующим образом:
// 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 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 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);
Ответ 3
Попробуйте установить автозаполнение в свой флажок, хотя это не является стандартным для всех браузеров, но оно работает с обычными браузерами.
<input type="text" autocomplete="off" />
Ответ 4
Отследить нажатие клавиши ввода в событии keyup, выбор завершается к моменту обнаружения клавиши ввода при событии keyup.
обнаружение клавиши ввода при нажатии клавиши и вмешательство в работу с функциями автозаполнения.
Ответ 5
JQuery хорош, и все, но почему бы не использовать простой JavaScript?
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;
}
}
Ответ 6
Это работает для меня:
$('input').keypress(function(e) {
if(e.which == 13) {
if(this.value)
{
$("#submitbutton").click();
}
}
});
Ответ 7
Если вы используете новые типы полей формы html5, вы можете изменить код teedyay следующим образом:
case 13:
// Fire the event if:
// - we're not currently in the browser 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)
{
...
Обратите внимание на новые типы ввода.
Ответ 8
Я не уверен, что вы нажали нажатия клавиш в окне или на определенных элементах DOM. Вы должны сделать последнее (например, в элементе form
), а затем в обработчике событий заглянуть в объект события, чтобы определить, какой элемент DOM был источником события. Если это текстовое поле с автозаполнением, то return false;
.
Посмотрите на jQuery .keypress()
обработчик событий, а event.target
объекта события.
Ответ 9
Я столкнулся с той же проблемой, и хотя я не был совершенным, я использовал другой подход, который я считаю более простым. При создании автозаполнения я устанавливаю текущее время для события select, а затем сравниваю его перед выполнением любых действий:
$('#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>
Ответ 10
Другой (безопасный) подход - использовать события keyup
и keydown
для обнаружения изменений значений.
Автозаполнение устанавливает значение после события keydown
. Когда наблюдаются оба события, следующее гораздо надежнее других решений:
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();
}
Возможно, вы захотите проверить, является ли document.activeElement. Не стесняйтесь использовать мое злобное расширение прототипа.