聚焦被触发两次

时间:2012-07-29 23:33:14

标签: jquery jquery-ui jquery-ui-dialog

我有一个文本框和一个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之后的{{1}}处理程序。这会导致创建两个背景叠加层,当我关闭对话框时,一个叠加层仍然可见。

我做错了什么?有没有更好的方法来处理这种情况 - '在文本字段中按下一个输入打开一个jQuery对话框'。感谢。

3 个答案:

答案 0 :(得分:3)

最明显的解决方案可能是使用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事件处理程序?

答案 1 :(得分: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事件自动触发。

答案 2 :(得分:0)

http://jsfiddle.net/7Fpm4/2/我更新了你的例子,只是将input.focusin(function()更改为input.change(function()