在文本框中按下回车键后,防止模糊和keyup事件触发。

15

按下 enter 后,我希望只触发 keyup 事件,但是先触发了 blur。如何在使用 enter 键触发 keyup 时取消 blur

请不要建议将 blurkeyup 绑定到单个 live() 方法中。

$(".textbox").on("blur",function () { 
    alert("blur Event fired");
});

$(".textbox").on("keyup",function (event) { 
    if(event.keyCode == 13){ // Detect Enter
        alert("KeyUp fired after pressing Enter");
    }
});

那么,谁说blur不应该触发呢?注意:live()已经被弃用,即使这个事实与你在这里的问题无关。 - kapa
尝试使用 keypress 替代 keyup,并使用 on 替代 live - Dhiraj
2
嘿,这是一个相关的问题。请重新打开它。这是我刚遇到的一个真实问题,必须在模糊之前使keyup起作用。 - Félix Adriyel Gagnon-Grenier
8个回答

9

编辑

为了防止两个事件同时触发,你需要在导致失焦前标记该元素。这样,你的blur事件处理程序就可以判断该事件是keyup事件的影响,还是合理地失去焦点。像这样:

$(".textbox").live("blur",function (event) {
    if (!$(this).hasClass('keyupping'))
        alert("blur Event fired");
});

$(".textbox").live("keyup",function (event) {
    $(this).addClass('keyupping');
    if(event.keyCode == 13){ // Detect Enter
        alert("KeyUp fired after pressing Enter");
    }
    $(this).removeClass('keyupping');
});

尝试一下:http://jsfiddle.net/GRMule/sR6zm/

原始回答

keyup事件触发时,它准备绘制浏览器警报对话框,这将使焦点从文档移开并应用于模态对话框。这将导致blur事件的触发。

然后,blur事件跳入并在keyup不知所措之前完成其执行上下文。

通过使用不会将焦点从元素移开的内容来演示这一点,例如console.loghttp://jsfiddle.net/GRMule/7vRLW/

事件触发的顺序是特定于实现的,这意味着您不能指望Firefox的表现像IE一样。请参见规范:http://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113/events.html#Events-eventgroupings。在IE中尝试警报的情况下,您将看到blur在IE 7之前会被触发 - blur在Chrome中不会触发!


但问题是,我能否在按下Enter键后取消blur事件的触发? - Bhavesh G
由于blur不接收任何键盘信息,因此您将无法检测到涉及哪个键。实际上,键并不是元素失去焦点的原因,而是警报在起作用。 - Chris Baker

5
我遇到了类似的问题。我允许用户编辑单个字段,当他们按下Enter键或移动到该字段时,我发送一个Ajax请求来更新它。我发现当我按下Enter键时,Ajax请求会发送两次。
所以,我尝试在输入框上调用 $input.blur() 而不是在按下Enter键时调用请求,这样就可以解决问题了!这让我想到...如果按下Enter键会导致模糊,那么我是否需要尝试捕获它呢?
在我的情况下,我不需要。我发现只需要模糊就可以了,因为Enter键会自动触发它。我不确定在所有浏览器中都是100%有效的,但我已经在当前版本的Chrome,Firefox,IE和Safari上进行了测试,所有这些浏览器都可以正常工作。
因此,我建议您要么根本不捕获Enter键,要么只需调用blur()即可触发所需的操作。

很好的解决方案。对我来说,按Enter键并不会自动触发我正在处理的输入框的模糊事件。因此,我必须捕获keydown事件,如果是13,则手动触发模糊事件。也许是因为我的输入框不在<form>元素内。我不确定,但这只是一个提醒,要注意模糊事件似乎并不总是会触发。 - osullic

3

我有一个输入框,用户可以更改它,焦点移出或按下回车键。

但是当您按下回车键时,会触发keydownblur两个事件,因此myFunction()会被触发两次。

所以,不需要编写两个单独的函数来处理keydownblur事件,您可以将它们放入一个单一的函数中:

my_input.on('keydown blur', function (e) {

    // was it the Enter key?
    if (e.which == 13) {
        $(this).blur();
    }

    if (e.type == 'blur') {
        myFunction();
    }

});

0

以下代码在primefaces 5.2.5中适用:

<p:inputText onkeydown="if (event.keyCode === 13) {return false; }" value="#{myForm.name}"> <p:ajax event="blur" update="@this" listener="#{bean.func()}" /> </p:inputText>

即使按下Enter键,模糊事件也不会触发。


0
尝试下面的方式。在keyup事件处理程序中添加一个类——在此示例中添加——并修改模糊事件的选择器将防止触发模糊事件处理程序。
$(".textbox:not(.added)").on("blur", function () { 
    alert("blur Event fired");
});

$(".textbox").on("keyup", function (event) { 
    if (event.keyCode == 13) {
        $(event.currentTarget).addClass('added');
        alert("KeyUp fired after pressing Enter");
    }
});

0
基本上,keyup 是触发 blur 事件的一个触发器。当 keyup 触发时,您应该添加一个标志:
 $('#exemple').keyup(function (e) {
        if (e.which == 13) {
            $('#exemple').addClass('keyupfired');
            alert('whatever');
        }
    });

然后,当触发 blur 事件时,它应该询问是否已经触发了 keyup 事件。如果你想让用户离开文本框时再次触发事件,请记得移除标志:

$('#exemple').on("blur", function () {
        if (!$('#exemple').hasClass('keyupfired')) {
            alert('whatever');
        }
        $('#exemple').removeClass('keyupfired');
    });

-1

我无法更改class属性,所以最终得到了以下结果:

$(".textbox").on("blur",function () { 
    if($(this).attr('flag')!='1') 
        alert("blur Event fired");
});

$(".textbox").on("keyup",function (event) { 
    $(this).attr('flag','1');
    if(event.keyCode == 13){ // Detect Enter
        alert("KeyUp fired after pressing Enter");
    }
    $(this).attr('flag','0');
});

-3
我注意到,与其提供提示,不如给出更完整的解释和代码示例,因此在这里: 总是有一种便宜的方法来设置外部变量:
var triggerBlur = true;
$(".textbox")
    .live({
       blur : function () { 
        if (triggerBlur) {// if not preceded by keyup 'Enter' event
            alert("blur Event fired");
        }
        // reset variable to true to allow the blur event to be triggered subsequently when not preceded by keyup 'Enter' event
        triggerBlur = true;
      },
      keyup : function (event) { 
        if(event.which === 13){ // Detect Enter
            alert("KeyUp fired after pressing Enter");
            triggerBlur = false;
        }
      });

同时,最好使用 event.which 而不是 event.keyCode(请参见 http://api.jquery.com/event.which/ 了解原因),并且建议在 JavaScript 中使用身份运算符 '===' 而不是相等运算符 '==',因为后者已经失效(请参见 Which equals operator (== vs ===) should be used in JavaScript comparisons?


那样做只能起作用一次,并且会污染全局范围。这是不好的实践。 - Chris Baker
“那只能起一次作用,而且只有一次”:这实际上取决于您如何组织整个代码;“污染全局范围”:同样如此;好吧,这确实是一种相当便宜的方法,但他正在寻找解决方案;您的解决方案使用DOM来存储数据,这也是不良实践。 - bstenm
1
需要引用来源 -- 将类添加到DOM元素并不是不良实践。 - Chris Baker
Chris,如果只是为了记住状态,那就可以这样做。我会尽量避免仅仅为此与DOM交互,因为那不是它的工作。在document.ready中使用变量并不是全局范围 ;)。你看,我不会放手 :D! - bstenm
再次强调,需要引用出处。尽管你没有放手,但事实仍然存在:你回答中的代码从未将“triggerBlur”变量重置为“true”,因此它只能工作一次——这不是一个功能性的解决方案。我的解决方案不仅可以多次使用,而且还能处理页面上的多个表单元素。在这方面,你的代码也无法胜任。我希望你意识到,无论如何评论或辩论都无法改进这个答案中的代码,这不是比赛。代码要么有效,要么无效;这段代码无效,我的有效。我们正在处理事实。 - Chris Baker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接