选项卡上的按键事件行为

Posted

技术标签:

【中文标题】选项卡上的按键事件行为【英文标题】:Keyup event behavior on tab 【发布时间】:2013-08-03 21:55:08 【问题描述】:

html

<form id="myform">
    <input id="firstfield" name="firstfield" value="100" type="text" />
    <input id="secondfield" name="secondfield" value="200" type="text" />
</form>

jQuery:

jQuery(document).ready(function() 
    $('#firstfield').keyup(function() 
      alert('Handler for firstfield .keyup() called.');
    );
    $('#secondfield').keyup(function() 
      alert('Handler for secondfield .keyup() called.');
    );
);

演示:http://jsfiddle.net/KtSja/3/

在此演示中,如果您将光标放在第一个字段中然后跳出(不进行任何更改),则在第二个字段上触发 keyup 事件。即,您正在跳出第一个字段并进入第二个字段。这种行为正确吗?我怎样才能防止这种情况发生?同样适用于 shift + tab。

注意:

a) 我相信所有其他键(可打印和不可打印)都会在第一个字段上触发 keyup 事件。

b) 如果您一直按住选项卡直到它移出两个字段,则根本不会触发该事件。

【问题讨论】:

【参考方案1】:

一个键的默认操作是在keydown 事件期间执行的,所以很自然地,当keyup 传播时,Tab 键已经将焦点转移到下一个字段。

你可以使用:

jQuery(document).ready(function() 
    $('#firstfield, #secondfield').on(
        "keydown": function(e) 
            if (e.which == 9) 
                alert("TAB key for " + $(this).attr("id") + " .keydown() called.");
            
        ,
        "keyup": function(e) 
            if (e.which != 9) 
                alert("Handler for " + $(this).attr("id") + " .keyup() called.");
            
        
    );
);

这样,如果按下 Tab 键,您可以在处理其他键之前进行任何必要的调整。 See your updated fiddle for an exampe.

编辑

根据您的评论,我改进了该功能。 javascript 最终变得有点复杂,但我会尽力解释。 Follow along with the new demo here.

jQuery(document).ready(function() 
    (function($) 
        $.fn.keyAction = function(theKey) 
            return this.each(function() 
                if ($(this).hasClass("captureKeys")) 
                    alert("Handler for " + $(this).attr("id") + " .keyup() called with key "+ theKey + ".");
                    // KeyCode dependent statements go here.
                
            );
        ;
    )(jQuery);

    $(".captureKeys").on("keydown", function(e) 
        $("*").removeClass("focus");
        $(this).addClass("focus");
    );
    $("body").on("keyup", "*:focus", function(e) 
        if (e.which == 9) 
            $(".focus.captureKeys").keyAction(e.which);
            $("*").removeClass("focus");
        
        else 
            $(this).keyAction(e.which);
        
    );
);

基本上,您将class="captureKeys" 分配给您想要监控按键的任何元素。首先看第二个函数:当keydown 被你的一个captureKeys 元素触发时,它会被赋予一个名为focus 的虚拟类。这只是为了跟踪最近的元素以获得焦点(我在演示中为.focus 提供了背景作为视觉辅助)。因此,无论按下什么键,只要它也有.captureKeys,它所按下的当前元素都会被赋予.focus 类。

接下来,当keyup任何地方 被触发时(不仅仅是在.captureKeys 元素上),该函数会检查它是否是一个选项卡。如果是,那么焦点已经转移,自定义的.keyAction() 函数会在最后一个获得焦点的元素(.focus)上调用。如果它不是选项卡,则在当前元素上调用 .keyAction()(但同样,仅当它具有 .captureKeys 时)。

这应该可以达到你想要的效果。您可以在keyAction() 函数中使用变量theKey 来跟踪which key was pressed,并采取相应措施。

对此的一个主要警告:如果 .captureKeys 元素是 DOM 中的最后一个元素,在大多数浏览器中,按 Tab 将移除文档的焦点,keyup 事件将从不开火。这就是我在演示底部添加虚拟链接的原因。

这提供了一个基本框架,因此您可以根据自己的需要对其进行修改。希望对您有所帮助。

【讨论】:

您的解决方案在第一个字段中引入了一个额外的空格字符。另外,我只想避免 tab 和 shift + tab 上的 keyup 事件。【参考方案2】:

这是预期的行为。如果我们看看发生的一系列事件:

    焦点位于第一个文本框时按 Tab 键 在第一个文本框触发按键事件 将焦点移到第二个文本框 手指离开 Tab 键 Keyup 事件在第二个文本框触发

为第二个文本框触发 Key up,因为这是焦点转移到该输入后发生的位置。

您无法阻止这一系列事件的发生,但您可以检查事件以查看按下了哪个键,如果是 Tab 键,则调用 preventDefault()

【讨论】:

【参考方案3】:

我最近正在为placeholder polyfill 处理这个问题。我发现如果您想在原始字段中捕获 keyup 事件,您可以监听 keydown 事件并在按下选项卡时触发 keyup 事件。

而不是这个:

$(this).on('keyup': function() 
                //run code here
            
        );

改成这样:

$(this).on('keydown': function(e) 
                // if tab key pressed - run keyup now
                if (e.keyCode == 9) 
                    $(this).keyup();
                    e.preventDefault;
                
            ,
            'keyup': function() 
                //run code here
            
        );

【讨论】:

【参考方案4】:

我最终使用了这个解决方案:

HTML:

<form id="myform">
    <input id="firstfield" name="firstfield" value="100" type="text" />
    <input id="secondfield" name="secondfield" value="200" type="text" />
</form>

jQuery:

jQuery(document).ready(function () 
    $('#firstfield').keyup(function (e) 
        var charCode = e.which || e.keyCode; // for cross-browser compatibility
        if (!((charCode === 9) || (charCode === 16)))
            alert('Handler for firstfield .keyup() called.');
    );
    $('#secondfield').keyup(function (e) 
       var charCode = e.which || e.keyCode; // for cross-browser compatibility
       if (!((charCode === 9) || (charCode === 16)))
            alert('Handler for secondfield .keyup() called.');
    );
);

如果键是 tab、shift 或两者,此解决方案不会运行警报。

解决方案:http://jsfiddle.net/KtSja/13/

【讨论】:

以上是关于选项卡上的按键事件行为的主要内容,如果未能解决你的问题,请参考以下文章

按键事件处理

捕获 DIV 元素上的按键(或 keydown)事件

在jQuery中检测单个按键事件上的多个键

如何以编程方式控制 NSPopUpButton 上的 TAB 按键事件

Vue中的事件修饰符,按键修饰符

JavaScript实现按键精灵