正则表达式模式用于删除、箭头和转义键

7
我正在编写一段 JavaScript 代码,以限制可以输入到文本框中的键。
function keyRestricted(e) {
    var keypressed;
    var keychar;
    var keycheck;
    // IE - keyCode
    // Netscape/Firefox/Opera - which
    keypressed = e.keyCode || e.which;
    keychar = String.fromCharCode(keypressed);
    //alert(keychar);
    keycheck = /[a-zA-Z0-9\b]/;
    return keycheck.test(keychar);
} //keyrestricted

我的正则表达式现在是/[a-zA-Z0-9\b]/,允许字母数字和退格。我想在Firefox(3.6)中使删除、L/R箭头和ESC键能够工作。
我不确定这些键的符号是什么。
在ie8中,即使从正则表达式中排除了\e开关,按下ESC键(和del/arrows)仍然处于活动状态,当按下时,它会重置/清空文本框。
在FF中,我将escape放入表达式/[a-zA-Z0-9\b\e]/中,但似乎对Firefox不起作用,也就是说,当按下escape键时,它不会重置/清空文本框。
哪些符号是正则表达式中允许字母数字、L/R箭头、删除和ESC的有效符号?
此外,[a-zA-Z0-9\-\_]的翻译是什么?它旨在匹配字母数字和连字符。但为什么连字符前面有一个斜杠,因为连字符不需要斜杠?还有\_是什么,因为下划线不被表达式匹配?
谢谢。
使用nnnnn建议的按键代码数字并不能为我(对其他人?)工作的原因是,65-90的按键代码是大写字母的,尽管一些网站声称这些按键代码适用于大小写字母。这个http://www.lookuptables.com/网站显示小写字母的范围是97-122。不幸的是,这个范围与一些字符存在未映射的重叠。例如,\字符列为有220个按键代码。但我的过滤器仍会允许\通过,因为它的按键代码大于122。还有其他的例子。我已经使用笔记本电脑键盘和外部全尺寸键盘进行了测试。
编辑2
我已经将正则表达式和按键代码参数合并为一个函数。该函数原则上可以工作,但由于按键代码冲突太多,它无法处理百分号(%)键。需要同时使用onkeydown和onkeypress才能捕获所有按键(除了%键)。请查看我的讨论这里javascript regex for key event input validations troubleshooting help
<head>
<script type="text/javascript">
function keyRestricted(evt) {
    var theEvent = evt || window.event;
    var key = theEvent.keyCode || theEvent.which;
    var keychar = String.fromCharCode(key);
    //alert(keychar);
    var keycheck = /[a-zA-Z0-9]/;
    // backspace || delete || escape || arrows
    if (!(key == 8 || key == 27 || key == 46 || key == 37 || key == 39)) {
        if (!keycheck.test(keychar)) {
            theEvent.returnValue = false; //for IE
            if (theEvent.preventDefault) theEvent.preventDefault(); //Firefox
        }
    }
}
</script>
</head>
<body>
    Please modify the contents of the text field.
    <input 
        type="text" value="" 
        onKeypress="return keyRestricted(event)" 
        onKeydown="return keyRestricted(event)" 
    />
</body>

需要使用正则表达式吗?仅仅检查 keypressed 是否与删除等代码相匹配会更直接。 - pimvdb
看看我的答案,它会给你一些可靠的方法来完成这个任务,而不需要使用正则表达式。但是请注意,我不建议这样做:通常最好在 onchangeonbluronsubmit 时验证字段,除非你有一种牢固的方法来阻止用户粘贴和/或拖放无效字符(如果你有,那么你是唯一一个)。无论如何,别忘了你还必须在服务器端再次验证它。 - nnnnnn
例如,右箭头的键码是39,在正则表达式开关中如何转换? - Jamex
正则表达式测试字符字符串。并非所有键都有相应的字符,因此您无法使用正则表达式处理这些键。换句话说,这些键对于正则表达式是不可见的。_所有键都有相应的键码,因此您可以轻松地进行测试_而不需要_正则表达式_,并且您可以通过测试keypressed变量是否与您关心的键的数字代码匹配(如我的答案中所示),将这样的测试轻松适合于您问题中的函数中。正则表达式不是这项工作的正确工具。接受它并继续前进(就像我要做的那样)。 - nnnnnn
你提到使用 oninput。根据 MDN 的说明,“只有在显示的文本更改时才调用此事件,因此当用户按下不可显示的键时不会调用它。” 因此,它无论如何都不能用于箭头键。而且在旧版本的 IE 或其他一些浏览器中也不支持。 - nnnnnn
显示剩余4条评论
2个回答

10
据我所知,正则表达式 - 至少 JavaScript 版本 - 并不允许你测试一些特殊字符,比如转义符和箭头键(虽然我相信你可以测试退格键)。
我更喜欢使用标准的if语句来实现这种功能:
var keypressed = e.which || e.keyCode;

if ((keypressed >=65 && keypressed <= 90) // letters
    || (keypressed >=48 && keypressed <= 57) // digits
    || keypressed === 8 // backspace
    || keypressed === 27 // escape
    || keypressed === 46 // delete
    || (keypressed >= 35 && keypressed <= 40) // end, home, arrows
    // TODO: shift, ctrl, alt, caps-lock, etc
    ) {
  // do something
}

// If the keys you care about don't follow any particular pattern
// a switch might be more convenient:
switch (keypressed) {
  case 8:
  case 27:
  case 46:
     // valid key, do something
     break;
  default:
     // invalid key, do something else
     break;
}


// You can also do something like this:    
var permittedKeyCodes = {
  "8" : true,  // backspace
  "27" : true, // escape
  "46" : true  // delete
};
if (permittedKeyCodes[keypressed]) {
  // do something
}

如果您采用后一种方法,最好在函数外部定义permittedKeyCodes对象,这样效率更高。
有许多地方(这里是其中之一)可以获得所有键码的列表。
请注意,如果您捕获了keydown或keyup事件,则返回的键码与键相关联,而不是字符,因此大写和小写A都具有相同的代码。keypress事件的工作方式不同。

谢谢nnnnnnnnnn,我一直在使用类似于你的代码。不知道是我编码有误或者不完整,它没有按照预期工作。我会尝试你的代码。顺便问一下,你能回答我上一个段落中的语法问题吗?TIA。 - Jamex
额外的反斜杠通常会被忽略。我期望该表达式匹配字母、数字、连字符和下划线。 - nnnnnn
它实际上并不匹配下划线。这就是为什么我感到困惑的原因。 - Jamex

2
只需阅读 http://unixpapa.com/js/key.html,它会告诉您解决此问题所需的一切。
摘要: - 您需要使用`keydown`(而不是`keypress`)事件来检测非可打印键,例如箭头键 - 事件的`keyCode`属性将在所有浏览器中起作用,因此不需要使用`which`属性。 - `keyCode`与`keydown`和`keyup`中键入的字符无关,因此不要尝试从事件获取字符。 - Opera仅允许您在`keypress`事件(而不是`keydown`)中禁止默认的浏览器行为,因此为了支持Opera,您需要处理`keypress`事件,并在`keydown`事件中设置一个标志,以供`keypress`处理程序检查。

谢谢,我决定不值得为了解决不一致性而麻烦。 - Jamex

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接