Поведение события Keyup на вкладке

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

Я решил использовать это решение:

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.');
    });
});

Это решение не запускает предупреждение, если ключ является табуляцией, сдвигом или обоими.

Решение: http://jsfiddle.net/KtSja/13/

Ответ 2

Во время события 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, вы можете внести необходимые корректировки перед использованием других клавиш. См. обновленную скрипту для примера.

Изменить

Основываясь на вашем комментарии, я обновил функцию. JavaScript оказался немного сложным, но я сделаю все возможное, чтобы объяснить. Следуйте вместе с новой демонстрацией здесь.

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(), чтобы отслеживать какой ключ был нажат, и действовать соответственно.

Одно из основных предостережений: , если элемент .captureKeys является последним элементом в DOM, нажатие Tab удаляет фокус из документа в большинстве браузеров, а событие keyup никогда не стреляйте. Вот почему я добавил фиктивную ссылку внизу демо.

Это обеспечивает базовую структуру, поэтому вам нужно изменить ее в соответствии с вашими потребностями. Надеюсь, что это поможет.

Ответ 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

Ожидается поведение. Если мы посмотрим на последовательность событий:

  • Нажмите клавишу вкладки, когда фокус находится в первом текстовом поле.
  • Событие запуска триггера в первом текстовом поле
  • Переместить фокус во второе текстовое поле
  • Поднимите пальцем кнопку закладок
  • Событие Keyup запускается во втором текстовом поле

Для второго текстового окна запускается клавиша, потому что это происходит, когда фокус был сдвинут на этот вход.

Вы не можете предотвратить эту последовательность событий, но вы можете проверить это событие, чтобы узнать, какой ключ был нажат, и вызвать preventDefault(), если это был ключ вкладки.