选项卡上的Keyup事件行为

时间:2013-08-02 14:58:52

标签: javascript jquery

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)我相信所有其他键,可打印和不可打印,会触发第一个字段上的键盘事件。

b)如果按住标签直到它移出两个字段,则根本不会触发事件。

4 个答案:

答案 0 :(得分:11)

密钥的默认操作是在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背景作为视觉辅助)。因此,无论按下什么键,只要它还有.focus,它被按下的当前元素将被赋予.captureKeys类。

接下来,当keyup被解雇任何地方(不仅仅是.captureKeys元素)时,该函数会检查它是否为标签。如果是,则焦点已经移动,并且在最后一个具有焦点的元素(.keyAction())上调用自定义.focus函数。如果它不是标签,则会在当前元素上调用.keyAction()(但同样,仅当它具有.captureKeys时)。

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

一个主要的警告:如果.captureKeys元素是DOM中的最后一个元素,按Tab键会在大多数浏览器中删除文档中的焦点,{{1事件永远不会激发。这就是为什么我在演示的底部添加了虚拟链接。

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

答案 1 :(得分:4)

我最近在为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
            }
        });

答案 2 :(得分:3)

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

  1. 焦点位于第一个文本框
  2. 时按Tab键
  3. 在第一个文本框中触发按键事件
  4. 将焦点移至第二个文本框
  5. 抬起手指关闭标签键
  6. 在第二个文本框中触发了键盘事件
  7. 为第二个文本框触发了键,因为这是因为焦点已转移到该输入而发生的位置。

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

答案 3 :(得分:2)

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

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/