keydown 事件中的输入验证

发布于 2024-09-05 03:38:56 字数 1077 浏览 7 评论 0原文

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

我正在编写的验证是这样的,

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();        
    }
}

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

  1. 当我输入更多条件进行检查时,条件语句变得越来越长。
  2. keyCodes 可能因浏览器而异。
  3. 我不仅要检查什么是不合法的,还要检查什么是例外的。在上面的示例中,删除退格箭头键是例外。

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

所以我的问题是:

  1. 是否有比通过 keyCode 检查 keyCode 更好的方法来验证 keydown 事件中的输入?
  2. 在浏览器显示用户输入之前,除了 keydown 事件之外,还有其他方法可以捕获用户输入吗?以及一种对其进行验证的方法?

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

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. keyCodes can 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 arrow keys are exceptional.

But the feature that I don't want to lose is having not to display the input in the textarea unless 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 keyup event.

So my question is:

  1. Are there better ways to validate input in keydown event than checking keyCode by keyCode?
  2. Are there other ways to capture the user inputs other than keydown event before browser displays it? And a way to put the validation on it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

拍不死你 2024-09-12 03:38:56

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

还有一些错误:在 Firefox 中,您需要从传递到事件处理函数的参数中获取 Event 对象,并且如果您使用的是 DOM0 事件处理函数而不是 addEventListener()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;
    }
};

If you're checking a printable key, which is exactly what you seem to be doing, you should use the keypress event 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 keydown event. Also, it's a bad idea to suppress arrow keys and delete/backspace keys. What do you gain from doing that?

There's also some errors: in Firefox, you'll need to get the Event object 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:

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;
    }
};
夜雨飘雪 2024-09-12 03:38:56

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

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

这是我使用的 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;
}

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

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 ... case could offer a bit more readability.

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

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;
}
枫以 2024-09-12 03:38:56

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

jsfiddle: keydown/keypress demo w/ info display

看来最新的浏览器使用了 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>

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

jsfiddle: keydown/keypress demo w/ info display

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.

<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>
风向决定发型 2024-09-12 03:38:56

因此,我发现 keypress 对于可打印字符非常有用,而 keydown 对于所有其他字符都非常有用。您可以检查 keypress 上的 event.charCode 是否有可打印字符(如果是不可打印字符,则应为 0)。
您可以在 keydown 上使用 event.keyCode 作为箭头等。

这就是我在 Chrome 和 Firefox 中获得自动完成功能的方法。

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

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文