Javascript keydown 事件中的输入验证

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2997805/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 02:50:38  来源:igfitidea点击:

Input validation in the keydown event

javascriptvalidationdom-eventskeydown

提问by c4il

I'm attempting to do info validation against user text input in the process of keydownevent. The reason that I am trying to validate in the keydownevent is because I do not want to display the characters those that are considered to be illegal in the inputbox at the beginning.

我正在尝试对keydown事件过程中的用户文本输入进行信息验证。我试图在keydown事件中验证的原因是因为我不想input在开始时在框中显示那些被认为是非法的字符。

The validation I am writing is like this,

我写的验证是这样的,

function validateUserInput(){
   var code = this.event.keyCode;
    if ((code<48||code>57) // numerical
      &&code!==46 //delete
      &&code!==8  //back space
      &&code!==37 // <- arrow 
      &&code!==39) // -> arrow
   {
     this.event.preventDefault();        
    }
}

I can keep going like this, however I am seeing drawbacks on this implementation. Those are, for example:

我可以继续这样,但是我看到了这个实现的缺点。例如:

  1. Conditional statement become longer and longer when I put more conditions to be examined.
  2. keyCodescan be different by browsers.
  3. I have to not only check what is not legal but also have to check what are exceptional. In above examples, delete, backspace, and arrowkeys are exceptional.
  1. 当我要检查更多条件时,条件语句会变得越来越长。
  2. keyCodes可能因浏览器而异。
  3. 我不仅要检查什么是不合法的,还要检查什么是例外的。在上面的例子中deletebackspace、 和arrow键是例外。

But the feature that I don't want to lose is having not to display the input in the textareaunless it passes the validation. (In case the user try to put illegal characters in the textarea, nothing should appear at all) That is why I am not doing validation upon keyupevent.

但是我不想失去的功能是,textarea除非通过验证,否则不必在 中显示输入。(如果用户尝试在 中放入非法字符,则textarea根本不应该出现任何内容)这就是为什么我没有对keyup事件进行验证。

So my question is:

所以我的问题是:

  1. Are there better ways to validate input in keydownevent than checking keyCodeby keyCode?
  2. Are there other ways to capture the user inputs other than keydownevent before browser displays it? And a way to put the validation on it?
  1. 有没有keydown比 check keyCodeby更好的方法来验证事件中的输入keyCode
  2. keydown在浏览器显示之前,除了事件之外,还有其他方法可以捕获用户输入吗?以及一种对其进行验证的方法?

回答by Tim Down

If you're checking a printable key, which is exactly what you seem to be doing, you should use the keypressevent instead, since that's the only place you're going to be able to get reliable information about the character the keypress represents. You can't detect numeric keypresses reliably in the keydownevent. Also, it's a bad idea to suppress arrow keys and delete/backspace keys. What do you gain from doing that?

如果您正在检查一个可打印的键,这正是您正在做的事情,您应该改用该keypress事件,因为这是您将能够获得有关按键所代表的字符的可靠信息的唯一地方。您无法在keydown事件中可靠地检测数字按键。此外,抑制箭头键和删除/退格键也是一个坏主意。你这样做有什么好处?

There's also some errors: in Firefox, you'll need to get the Eventobject from the parameter passed into the event handler function, and if you're using a DOM0 event handler function rather than addEventListener()or attachEvent(), you should use return false;to suppress default behaviour. Here's my recommended code:

还有一些错误:在 Firefox 中,您需要Event从传递给事件处理程序函数的参数中获取对象,如果您使用的是 DOM0 事件处理程序函数而不是addEventListener()or attachEvent(),则应该使用return false;来抑制默认行为。这是我推荐的代码:

var input = document.getElementById("your_input_id");

input.onkeypress = function(evt) {
    evt = evt || window.event;
    var charCode = evt.which || evt.keyCode;
    var charStr = String.fromCharCode(charCode);
    if (/\d/.test(charStr)) {
        return false;
    }
};

回答by KooiInc

I don't think you need the preventDefault part. If you want to catch keys (by event.keyCode, or combinations using for example event.ctrlKey+ event.keyCode), you check if the keyCodeis allowed. If it is, simply return true, otherwise return false. If you return false, the key input will not be written to the input field, otherwise it will.

我认为您不需要 preventDefault 部分。如果要捕获键(byevent.keyCode或使用例如event.ctrlKey+ 的组合event.keyCode),请检查 是否keyCode允许。如果是,只需 return true,否则 return false。如果 return false,键输入不会写入输入字段,否则会。

I can't think of better ways to then using keyCode. You can use String.fromCharCode([keyCode])if you want to check for specific character values, but it keeps boiling down to some loop to check the keyCodes you want to validate. May be a switch ... casecould offer a bit more readability.

我想不出更好的方法来使用 keyCode。String.fromCharCode([keyCode])如果您想检查特定的字符值,您可以使用它,但它会一直归结为某个循环以检查您要验证的键码。可能switch ... case会提供更多的可读性。

Here's a piece of code from a keydown event handler I use (just for demonstration, it doesn't actually do anything):

这是我使用的 keydown 事件处理程序中的一段代码(仅用于演示,它实际上并没有做任何事情):

function handleKey(e, thisFld) {
        thisFld = (thisFld || this);
              e = e || event;
    if (!e) {
      return true;
    }

    var isCtrl = e.ctrlKey,
        isShift = e.shiftKey,
        isAlt = e.altKey,
        kc = e.keyCode || e.which,
        codes = [27, 38, 40],
        keys = {
                 escape: 27,
                 up: 38,
                 down: 40,
                 ins: 45,
                 del: 46,
                 one: 49
                };

    if (isCtrl && kc === keys.del) { ... }
    if (isAlt && kc === keys.ins) { ... }
        //etc
    return true;
}

回答by jaf0

here's a fiddle that you can play with and may provide more insight.

这是一个你可以玩的小提琴,可能会提供更多的见解。

jsfiddle: keydown/keypress demo w/ info display

jsfiddle:带信息显示的按键/按键演示

It would appear that the latest browsers use preventDefault(). The code below is similar to what i put on jsfiddle but is standalone and can be pasted into an html file that you can access locally to test (note it's mobile friendly for device testing.

最新的浏览器似乎使用 preventDefault()。下面的代码类似于我放在 jsfiddle 上的代码,但它是独立的,可以粘贴到一个 html 文件中,您可以在本地访问该文件进行测试(注意它对设备测试是移动友好的。

<html>
<head>
<meta name="viewport" content="initial-scale=1, minimum-scale=1, maximum-scale=1, width=device-width, user-scalable=no"/>
<style>
.b {color:blue;}
.r {color:red;}
input {font-size:18px;}
</style>
<script>
function byId(el) {return document.getElementById(el)}
function sfcc (n) {return String.fromCharCode(n);}
function foo(event) {
    var he='&#x'+event.keyIdentifier.split('+')[1]+';';
    var html=''
    var cn=event.target.className;
    html+='kc: [<span class="b">'+sfcc(event.keyCode)+'</span>] ';
    html+='wh: [<span class="b">'+sfcc(event.which)+'</span>] ';
    html+='he: [<span class="b">'+he+'</span>]<br>';
    for (i in event) 
        if (["string","boolean","number"].indexOf(typeof event[i]) >-1 && i.toUpperCase()!=i)
            html+='<span>'+i + '</span>: [<span class="r">'+event[i]+'</span>]<br>';
    byId('kc').innerHTML=html;
    switch (cn) {
        case "pd": event.preventDefault(); return;
        case "rf": return false;
    }
}
</script>
</head>
<body>
kp/pd: <input class="pd" type="text" onkeypress="foo(event)"/><br>
kp/rf: <input class="rf" type="text" onkeypress="foo(event)"/><br>
kd/pd: <input class="pd" type="text" onkeydown="foo(event)"/><br>
kd/rf: <input class="rf" type="text" onkeydown="foo(event)"/><br>
<div id="kc"></div>
</body>
</html>

回答by Mauricio Morales

So, I've found that keypress is great for printable characters, and keydown for all the rest. You can check the event.charCodeon keypressfor printable characters (it should be 0 for non-printable). You can use event.keyCodeon keydownfor arrows and such.

所以,我发现 keypress 非常适合可打印的字符,而 keydown 则适合所有其他字符。您可以检查可打印字符的event.charCode开启keypress(对于不可打印,它应该是 0)。您可以将event.keyCodeonkeydown用于箭头等。

This is how I just got an autocomplete to work in Chrome and Firefox.

这就是我刚刚在 Chrome 和 Firefox 中使用自动完成功能的方式。