如何检测按下的键是否会在<input />文本框中产生一个字符?

时间:2010-11-14 21:14:09

标签: javascript jquery keyboard-events

我有一个常规的文本框:

<input type="text"> 

我使用jQuery来处理与键相关的事件:

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

用户专注于文本框并按下键盘上的各种键(通常的键:字母,数字,SHIFT,BACKSPACE,SPACE,......)。我需要检测用户何时按下将增加文本框值长度的键。例如,“A”键会增加它,“SHIFT”键不会。

我记得看过PPK的讲座,他提到了这两者之间的区别。它与事件有关 - keydown与keypress - 可能还有事件属性 - key,char,keyCode。

更新!

我需要知道keydown或keypress处理程序中的这些信息。我不能等待keyup事件发生。

为什么我需要这个:

我有一个文本框,其大小根据用户输入动态变化。您可以查看此演示:http://vidasp.net/tinydemos/variable-size-text-box.html

在演示中,我有一个keydown和keyup处理程序。 keyup处理程序根据输入值调整文本框大小。但是,keydown处理程序将大小设置为比输入值大1个字符。我这样做的原因是,如果我没有,那么角色将溢出文本框外,只有当用户放开键时,文本框才会展开。这看起来很奇怪。这就是我必须预测新角色的原因 - 在文字框中出现角色之前,我会在每个keydown上放大文本框ergo。正如您在演示中看到的,这种方法看起来很棒。

然而,问题是BACKSPACE和ARROW键 - 它们还会扩展keydown上的文本框,并且只有在keyup上才会更正文本框大小。

解决方法:

解决方法是手动检测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来说(并且看起来很棒)。但是,我希望有一个更强大的解决方案。

9 个答案:

答案 0 :(得分:28)

我认为这将完成这项工作,或者如果不是非常接近,只需要进行微小的调整。你必须要记住的是,你无法可靠地告诉任何可能在keydownkeyup事件中输入的字符:所有必须在{{1处理程序。关键事件的权威资源是http://unixpapa.com/js/key.html

您还需要考虑此代码无法处理的粘贴。您需要具有单独的keypress事件处理程序(尽管Firefox&lt; 3.0,Opera和非常旧的WebKit浏览器不支持此事件)。您需要在粘贴处理程序中使用计时器,因为在JavaScript中无法访问即将粘贴的内容。

paste

答案 1 :(得分:9)

我能找到的可能解决方案是检查事件中密钥的长度。

例如: -

<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引起对这种情况的关注。

答案 2 :(得分:6)

这是一个更简单的解决方案,对我来说效果很好:

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元素(这会增加延迟和丑陋)。

答案 3 :(得分:4)

好的,我想我已经明白了。解决方案有点hackish,但实际上效果很好。

在keydown上,执行setTimeout 1毫秒,调用一个函数来检查/更改输入框的长度。

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

它似乎工作得很好,特别是在你的版本没有的几个地方(例如退格,CTRL + V,或选择一大堆文本并点击删除)

编辑:即使是延迟0毫秒的setTimeout似乎也能正常工作!

答案 4 :(得分:3)

你应该在keydown函数中使用属性keyEventArgs.Key,这将返回依赖于系统的数值。

这是一个链接,它具有不同浏览器和操作系统的不同密钥代码:

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

答案 5 :(得分:1)

这可能不是您要查找的方法,但您只需检查keydown函数中this.value.length的值即可。返回值是添加新字符之前输入字段中文本的长度。因此,如果你在keyup函数中再次检查长度,如果用户按下了一个字符,它将会更大,但如果用户按下shift键则相同。

答案 6 :(得分:1)

我认为你在输入字段的长度上设置一个计数器,在这种情况下你不需要那么花哨,你可以继续将字段的长度分配给变量,当用户达到你的最大长度只允许他们像这样按下删除或退格:

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

您也可以使用当前变量来显示计数器,或者使用maxlength - current来计算剩余字符数的倒计时

答案 7 :(得分:1)

您的目标是保持文本框大于输入的文本。

我通过计划在文本框中为两个额外的字符(而不是一个)留出空间来实现这一目标。然后:

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

上述优势在于您无需深入到密钥代码的下层世界。

答案 8 :(得分:1)

要在keydown处理程序中检测按下的键是否产生单个unicode字符,可以对正则表达式使用ES6 unicode u标志。

我们使用KeyboardEvent.key属性,该属性返回所按下键的值。根据文档:

如果按下的键具有打印的表示形式,则返回的值是一个非空的Unicode字符串,其中包含键的可打印表示形式。

inputElement.addEventListener("keydown", ({ key }) => {
  if (/^.$/u.test(key)) {
    // `key` matches a single unicode character
  }
});

该解决方案无法处理粘贴...