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

Šim*_*das 34 javascript jquery keyboard-events

我有一个常规的文本框:

<input type="text"> 
Run Code Online (Sandbox Code Playgroud)

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

$("input:text").keydown(function() {
    // keydown code
}).keypress(function() {
    // keypress code
}).keyup(function() {
    // keyup code
});
Run Code Online (Sandbox Code Playgroud)

用户专注于文本框并按下键盘上的各种键(通常的键:字母,数字,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上放大文本框.正如您在演示中看到的,这种方法看起来很棒.

然而,问题是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);
    }
}
Run Code Online (Sandbox Code Playgroud)

这对于BACKSPACE,SHIFT,ARROW LEFT和ARROW RIGHT来说(并且看起来很棒).但是,我希望有一个更强大的解决方案.

Tim*_*own 29

我认为这将完成这项工作,或者如果不是非常接近,只需要进行微小的调整.你必须要记住的是,你无法可靠地告诉任何关于可能在一个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))">
Run Code Online (Sandbox Code Playgroud)

  • 箭头键在`evt.which`中给出一个数字 (5认同)
  • 这是一些非常有用的信息。我已经用我自己的解决方法更新了我的演示,它运行良好,但我肯定也会测试你的代码。 (2认同)

val*_*tin 12

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

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

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

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

该解决方案不处理粘贴...


Mik*_*keX 10

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

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'
}
Run Code Online (Sandbox Code Playgroud)

这不需要探测DOM元素(这会增加延迟和丑陋).

  • 不幸的是,这不能处理某些多字节字符,例如表情符号。 (3认同)
  • 使用 `.key()` 而不是 `.keyCode()`。 (3认同)
  • 知道为什么这个答案不更高会很有趣......很好的解决方案! (2认同)
  • 虽然这确实对我的个人问题有帮助,但这个答案还有另一个问题:任何特殊字符(如句号、逗号、冒号等)都不会被覆盖,尽管它们会增加字符串的长度。 (2认同)

Vis*_*uth 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>
Run Code Online (Sandbox Code Playgroud)

因此,如果你按任何字符/符号,event.key将包含该字符,其长度将为1.如果按字符V,event.key则将具有值V,但如果按下回车键,则它将包含值Enter,如果按shift键然后转移等等.因此,如果一个键不产生一个字符,那么它的长度将大于1.

更新

键盘中的某些特殊键产生符号,其长度可能大于1,因此我修改了代码,以便即使它不是符号也可以发出警报.例如: - 其长度为2.某些移动键盘具有此类符号的快捷键.

键盘中的非字符/符号键将始终是字母,数字字符或两者的组合,例如: - F2,Shift.

感谢@Vicky Chijwani引起对这种情况的关注.

  • 这对我来说并不重要,但有趣的琐事:`"".length` 会给你 2 虽然它在视觉上只是一个“字符”:P (2认同)