Подтвердить что ты не робот

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

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

<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.

Обновить!

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

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

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

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

Однако проблема заключается в ключах 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, ARROW LEFT и ARROW RIGHT. Тем не менее, я хотел бы иметь более надежное решение.

4b9b3361

Ответ 1

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

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

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))">

Ответ 2

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

Например: -

<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, но если вы нажмете клавишу ввода, будет содержать значение Enter, если вы нажмете shift, затем Shift и т.д. Поэтому, если ключ не создает символ, тогда его длина будет больше 1.

Обновление

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

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

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

Ответ 3

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

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

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

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

Изменить: даже SetTimeout с задержкой 0 мс работает!

Ответ 4

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

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

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

Ответ 5

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

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 (что добавит латентность и уродство).

Ответ 6

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

Ответ 7

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

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

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

Ответ 8

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

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

// 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.
  }
}

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