Как определить, будет ли нажатая клавиша выдавать символ внутри текстового поля <input>? - PullRequest
34 голосов
/ 15 ноября 2010

У меня есть обычное текстовое поле:

<input type="text"> 

Я использую jQuery для обработки событий, связанных с ключами:

$("input:text").keydown(function() {
    // keydown code
}).keypress(function() {
    // keypress code
}).keyup(function() {
    // keyup code
});

Пользователь фокусируется на текстовом поле и нажимает различныеклавиши на клавиатуре (обычные: буквы, цифры, SHIFT, BACKSPACE, SPACE, ...).Мне нужно определить, когда пользователь нажимает клавишу, чтобы увеличить длину значения текстового поля.Например, клавиша «A» увеличит его, клавиша «SHIFT» не увеличит.

Я помню, как смотрел лекцию ППК, где он упомянул разницу между этими двумя.Это как-то связано с событием - keydown vs. keypress - и, возможно, со свойствами события - key, char, keyCode.

Обновление!

Мне нужно знать эту информацию в обработчиках нажатия клавиш или нажатия клавиш.Я не могу дождаться события keyup.

Зачем мне это нужно:

У меня есть текстовое поле, размер которого динамически изменяется в зависимости от ввода пользователя.Вы можете взглянуть на это демо: http://vidasp.net/tinydemos/variable-size-text-box.html

В демоверсии у меня есть обработчик нажатия клавиш и нажатия клавиш.Обработчик keyup регулирует размер текстового поля на основе введенного значения.Однако обработчик нажатия клавиш устанавливает размер на 1 символ больше входного значения.Причина, по которой я это делаю, заключается в том, что если бы я этого не сделал, то символ переполнялся бы за пределами текстового поля, и только когда пользователь отпустил клавишу, текстовое поле расширилось бы.Это выглядит странно.Вот почему я должен предвидеть нового персонажа - я увеличиваю текстовое поле при каждом нажатии клавиши, т.е. до того, как символ появляется в текстовом поле.Как вы можете видеть в демоверсии, этот метод выглядит великолепно.

Однако проблема заключается в клавишах BACKSPACE и ARROW - они также расширяют текстовое поле при нажатии клавиши, и только при включении клавиши размер текстового поля будет исправлен.

Обходной путь:

Обходным способом будет обнаружение клавиш BACKSPACE, SHIFT и ARROW вручную и действие на основечто:

// keydown handler
function(e) {
    var len = $(this).val().length;
    if (e.keyCode === 37 || e.keyCode === 39 ||
        e.keyCode === 16) { // ARROW LEFT or ARROW RIGHT or SHIFT key
        return;
    } else if (e.keyCode === 8) { // BACKSPACE key
        $(this).attr("size", len <= 1 ? 1 : len - 1);
    } else {
        $(this).attr("size", len === 0 ? 1 : len + 1);
    }
}

Это работает (и выглядит отлично) для BACKSPACE, SHIFT, СТРЕЛКА ВЛЕВО и СТРЕЛКА ВПРАВО.Однако мне бы хотелось иметь более надежное решение.

Ответы [ 8 ]

28 голосов
/ 15 ноября 2010

Это, я думаю, сработает, или, если не очень близко, потребует лишь незначительной настройки. Вы должны помнить, что вы вообще не можете ничего сказать о любом символе, который может быть напечатан в событии keydown или keyup: все это должно быть сделано в обработчике keypress. Основным ресурсом для ключевых событий является http://unixpapa.com/js/key.html

Вам также нужно учитывать пасты, которые этот код не будет обрабатывать. Вам потребуется отдельный обработчик событий paste (хотя это событие не поддерживается в Firefox <3.0, Opera и очень старых браузерах WebKit). Вам понадобится таймер в обработчике вставки, поскольку в JavaScript невозможно получить доступ к содержимому, которое должно быть вставлено. </p>

function isCharacterKeyPress(evt) {
    if (typeof evt.which == "undefined") {
        // This is IE, which only fires keypress events for printable keys
        return true;
    } else if (typeof evt.which == "number" && evt.which > 0) {
        // In other browsers except old versions of WebKit, evt.which is
        // only greater than zero if the keypress is a printable key.
        // We need to filter out backspace and ctrl/alt/meta key combinations
        return !evt.ctrlKey && !evt.metaKey && !evt.altKey && evt.which != 8;
    }
    return false;
}

<input type="text" onkeypress="alert(isCharacterKeyPress(event))">
9 голосов
/ 02 декабря 2016

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

Например: -

<input type="text" id="testId" onkeyup="keyChecking(event)" />

<script type="text/javascript">
function keyChecking(event) {

    if (event.key.length == 1) {
        alert("key produced character " + event.key);
    } else {
        alert("Key DOES NOT produce character");

        const alphabets = "AZaz09";
        const key = event.key;
        var notEvenASymbol = false;

        for (let i = 0; i < key.length; i++) {
            var charCode = key.charCodeAt(i);
            if ((charCode >= alphabets.charCodeAt(0) && charCode <= alphabets.charCodeAt(1)) ||
                (charCode >= alphabets.charCodeAt(2) && charCode <= alphabets.charCodeAt(3)) ||
                (charCode >= alphabets.charCodeAt(4) && charCode <= alphabets.charCodeAt(5))
            ) {
                notEvenASymbol = true;
                console.log(charCode);
                break;
            }
        }

        if (notEvenASymbol) {
            alert("Key DOES NOT produce even a symbol");
        }
        console.log(event.key);

    }
}    
</script>

Так что, если вы нажимаете какие-либо символы / символы, event.keyбудет содержать этот символ, и его длина будет 1. Если вы нажмете символ V , тогда event.key будет иметь значение V , но если вы нажмете клавишу ввода, то он будет содержать значение Введите , если вы нажмете Shift, тогда Shift и так далее.Поэтому, если клавиша не производит символ, его длина будет больше 1.

Обновлено

Некоторые специальные клавиши на клавиатуре производят символ и его длинуможет быть больше 1, поэтому я изменил код, чтобы он мог предупреждать, даже если это не символ.Например: - length его длина 2. Некоторые мобильные клавиатуры имеют сочетания клавиш для таких символов.

Не символьная / символьная клавиша на клавиатуре всегда будет комбинацией букв, цифр или того и другого, например: - F2 , Shift .

Спасибо @Vicky Chijwani за внимание к этому сценарию.

7 голосов
/ 12 марта 2017

Вот гораздо более простое решение , которое хорошо сработало для меня:

if(String.fromCharCode(event.keyCode).match(/(\w|\s)/g)) {
  //pressed key is a char
} else {
  //pressed key is a non-char
  //e.g. 'esc', 'backspace', 'up arrow'
}

Это не требует проверки элемента DOM (что добавило бы задержку и уродство).

4 голосов
/ 15 ноября 2010

ОК, я думаю, что понял. Решение немного хакерское, но на самом деле работает очень хорошо.

При нажатии клавиши выполните setTimeout в течение 1 миллисекунды, которая вызывает функцию для проверки / изменения длины вашего поля ввода.

http://jsfiddle.net/rygar/e2wQM/

Кажется, что он работает очень хорошо, особенно в некоторых местах, где ваша версия не работает (например, backspace, CTRL + V или выделение целой пачки текста и нажатие клавиши delete)

Редактировать: Кажется, работает даже setTimeout с задержкой 0 мс!

3 голосов
/ 15 ноября 2010

Вы должны использовать свойство keyEventArgs.Key в функции keydown, это вернет числовое значение, которое будет зависеть от системы.

вот ссылка с разными кодами клавиш для разных браузеров и ОС:

http://www.quirksmode.org/js/keys.html

1 голос
/ 15 ноября 2010

Ваша цель сохранить текстовое поле больше, чем текст, введенный в него.

Я бы выполнил это, запланировав место для двух дополнительных символов (не одного) в текстовом поле. Тогда:

// pseudo-code.... 
old_len = textbox.value.length
keyUp function() {
  var new_len = textbox.value.length
  if (new_len != old_len) {
    old_len = new_len
    textbox.style.size = new_len + 2 // pseudo code.
  }
}

Преимущество вышесказанного в том, что вам не нужно спускаться в нижний мир кодов клавиш.

1 голос
/ 15 ноября 2010

Я предполагаю, что вы устанавливаете счетчик на длину поля ввода, и в этом случае вам не нужно быть таким необычным, вы можете просто продолжать присваивать длину поля переменной, и когда пользовательдойдя до вашей максимальной длины, разрешите им только нажать delete или backspace следующим образом:

$("input:text").keypress(function() {
var current = $(this).val().length;
if (current >= 130) {
if (e.which != 0 && e.which != 8) {
e.preventDefault();
}
}
}

Вы можете также использовать переменную current, чтобы отобразить счетчик, или сделать maxlength - current, чтобы сделать обратный отсчет, сколькоперсонажи остались

1 голос
/ 15 ноября 2010

Возможно, это не тот метод, который вы ищете, но вы можете просто проверить значение this.value.length в функции нажатия клавиш. Возвращаемое значение - это длина текста в поле ввода ДО добавления нового символа. Поэтому, если вы снова проверите длину в функции keyup, будет больше, если пользователь нажал символ, но то же самое, если пользователь нажал клавишу Shift.

...