Фокусировка срабатывает дважды

У меня есть текстовое поле и диалоговое окно Jquery UI. Когда пользователь закончит вводить текстовое поле и нажмет Enter, я хочу отобразить диалоговое окно. Для этого я использую следующий код:

$(document).ready(function () {
    var helpDial = $('#helpDialog');
    var input = $('#helpSearch');

    helpDial.dialog({
        width: 800,
        autoOpen: false,
        modal: true,
        title: "Templates",
        position: [165, 158]
    });

    input.focusin(function () {
        helpDial.dialog('close');
    }).focusout(function () {
        helpDial.dialog('open');
    }).on('keypress', function (e) {
        var code = (e.keyCode ? e.keyCode : e.which);
        if (code == 13) {
            input.focusout();
            return false;
        }
    });
});

<input id="helpSearch" />
<div id="helpDialog"></div>

http://jsfiddle.net/7Fpm4/1

Проблема в том, что когда я нажимаю Enter, focusout вызывается дважды, один из input.focusout() и второй раз сразу после helpDial.dialog('open') в focusout обработчик события. Это приводит к созданию двух фоновых наложений, и когда я закрываю диалоговое окно, одно наложение остается видимым.

Что я делаю неправильно? Есть ли лучший способ справиться с этим сценарием - "нажатие клавиши ввода в текстовом поле открывает диалог jQuery". Благодарю.

3 ответа

Решение

Единственный способ предотвратить запуск события - это отсоединить обработчик события. Или, в зависимости от ситуации, примите дифференциальные меры на основе информации, доступной на момент возникновения события.

focusout событие срабатывает каждый раз, когда элемент теряет фокус. В этом случае каждый раз, когда пользователь нажимает на текстовое поле, focusin событие сработало. Как только курсор покидает текстовое поле (что происходит при открытии диалогового окна), focusout событие сработало.

Проблема с вашим кодом в том, что вы принудительно вызываете focusout событие, а затем focusout Событие вызывается естественно, когда вы открываете диалог. Итак, измените ваш код следующим образом:

$(document).ready(function () {
    var helpDial = $('#helpDialog');
    var input = $('#helpSearch');

    helpDial.dialog({
        width: 800,
        autoOpen: false,
        modal: true,
        title: "Templates",
        position: [165, 158]
    });

    input.on('focusin', function () {
        input.on("focusout", textboxFocusOut);
    }).on('keypress', function (e) {
        var code = (e.keyCode ? e.keyCode : e.which);
        if (code == 13) {
            textboxFocusOut();
        }
    });

    function textboxFocusOut() {
        input.off("focusout", textboxFocusOut);
        helpDial.dialog('open');                
    }

});

http://jsfiddle.net/8L7EL/1/

Этот код делает привязку функции к focusout в пределах focusin обработчик Если пользователь отходит от текстового поля, focusout будет вызван обработчик события, который немедленно отменяет привязку focusout событие (для предотвращения связывания функции несколько раз). Если пользователь нажимает клавишу ввода, то функция вызывается вручную, что удаляет focusout обработчик событий перед открытием диалога, чтобы предотвратить запуск focusout событие от автоматического запуска при открытии диалога.

Наиболее очевидным решением может быть использование такой переменной, как enter_pressed информировать focusout функция:

$(function () {
    var helpDial = $('#helpDialog'),
        input = $('#helpSearch'),
        enter_pressed = false;

    helpDial.dialog({
        width: 800,
        autoOpen: false,
        modal: true,
        title: "Templates",
        position: [165, 158]
    });

    input.on('focusout', function () {
        if( !enter_pressed ) {
            helpDial.dialog('open');
        } else {
            enter_pressed = false;
        }
    }).on('keypress', function (e) {
        var code = (e.keyCode ? e.keyCode : e.which);
        if (code == 13) {
            enter_pressed = true;
            helpDial.dialog('open');
        }
    });
});

http://jsfiddle.net/joplomacedo/7Fpm4/7/

Тем не менее, я считаю, что есть более чистое решение. Я постараюсь придумать это.

В сторону
Действительно ли нужен обработчик событий.focusin?

http://jsfiddle.net/7Fpm4/2/ я обновил ваш пример, просто изменил input.focusin(function () на input.change(function ())

Другие вопросы по тегам