Перехватывайте клавишу ввода, но не при выборе предложения браузера по автозаполнению

StackOverflow https://stackoverflow.com/questions/1648993

  •  22-07-2019
  •  | 
  •  

Вопрос

У меня есть несколько текстовых полей на странице, и я хочу щелкнуть ссылку, когда пользователь нажмет enter в любом из них.

Я могу легко перехватить кнопку ввода с помощью javascript (поискав 13 в event.keyCode и event.which), но я столкнулся с проблемой, когда включается функция автозаполнения браузера и подсказывает, что пользователь, возможно, захочет ввести.Мы обнаружили, что пользователи часто нажимают enter, чтобы принять предложение браузера, а не tab.Это сбивает пользователей с толку, поскольку ссылка нажимается сразу, в то время как они все еще намеревались ввести текст в некоторые другие поля.

Я знаю, что было бы лучше использовать здесь форму и кнопку отправки, но по разным причинам это непрактично.

Я использую jQuery, поэтому не стесняйтесь предлагать решения jQuery.

Это было полезно?

Решение

Пользователь всегда должен нажимать клавишу «Вниз», если он выбирает право выбора одного из автозаполненных текстов, почему бы не присвоить переменной значение, когда он нажимает клавишу «Вниз», а затем, если он делает ввод, после этого вы проверяете переменная. Вы не должны выполнять функцию щелчка по ссылке, если переменная установлена, иначе делайте это как обычно.

Другие советы

Используя идею 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'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);

Попробуйте отключить автозаполнение на своем флажке, хотя это не является стандартным для всех браузеров, но работает в обычных браузерах.

<input type="text" autocomplete="off" />

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;
    }
}

отслеживание клавиши ввода при событии keyup, выбор завершается к тому времени, когда вы обнаружите клавишу ввода по событию keyup.

обнаружение клавиши ввода при нажатии клавиши и выполнение операции мешают работе автозаполнения.

Это работает для меня:

$('input').keypress(function(e) {
    if(e.which == 13) {
        if(this.value)
        {
            $("#submitbutton").click();
        }
    }
});

Если вы используете новые типы полей формы html5, вы можете изменить код teedyay следующим образом:

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)
                    {
                        ...

Обратите внимание на новые типы ввода.

Я не уверен, что вы отслеживаете нажатия клавиш в окне или на определенных элементах DOM. Вы должны сделать последнее (например, в элементе form ), а затем в своем обработчике событий найти объект события, чтобы определить, какой элемент DOM был источником события. Если это текстовое поле с автозаполнением, то return false; .

Взгляните на .keypress () в jQuery. > обработчик событий и event.target свойство объекта события.

Я столкнулся с той же проблемой, и, хотя она была не идеальной, я использовал другой подход, который считаю более простым.При создании автозаполнения я устанавливаю текущее время для события выбора, а затем сравниваю его, прежде чем предпринимать какие-либо действия:

$('#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>

Другой (более безопасный) подход состоит в том, чтобы использовать события 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 входным. Не стесняйтесь использовать мое злое расширение прототипа .

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top