Javascript 如何检测按下的键是否会在 <input> 文本框中产生一个字符?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4179708/
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
How to detect if the pressed key will produce a character inside an <input> text-box?
提问by ?ime Vidas
I have a regular text-box:
我有一个普通的文本框:
<input type="text">
I use jQuery to handle key-related events:
我使用 jQuery 来处理与键相关的事件:
$("input:text").keydown(function() {
// keydown code
}).keypress(function() {
// keypress code
}).keyup(function() {
// keyup code
});
The user focuses on a text-box and presses various keys on his keyboard (the usual ones: letters, numbers, SHIFT, BACKSPACE, SPACE, ...). I need to detect when the user presses a key that is going to increase the length of the text-box value. For example, the "A" key will increase it, the "SHIFT" key wont.
用户专注于文本框并按下键盘上的各种键(通常的键:字母、数字、SHIFT、BACKSPACE、SPACE 等)。我需要检测用户何时按下将增加文本框值长度的键。例如,“A”键会增加它,“SHIFT”键不会。
I remember watching a lecture by PPK where he mentioned the difference between those two. It has something to do with the event - keydown vs. keypress - and possibly with the event properties - key, char, keyCode.
我记得看过 PPK 的一个讲座,他提到了这两者之间的区别。它与事件有关 - keydown 与 keypress - 可能与事件属性有关 - key、char、keyCode。
Update!
更新!
I need to know this information within the keydown or keypress handlers. I cannot wait for the keyup event to occur.
我需要在 keydown 或 keypress 处理程序中知道这些信息。我不能等待 keyup 事件发生。
Why I need this:
为什么我需要这个:
I have a text-box which size dynamically changes based on the user input. You can have a look at this demo: http://vidasp.net/tinydemos/variable-size-text-box.html
我有一个文本框,它的大小根据用户输入动态变化。你可以看看这个演示:http: //vidasp.net/tinydemos/variable-size-text-box.html
In the demo, I have a keydown and keyup handler. The keyup handler adjusts the text-box size based on the input value. However, the keydown handler sets the size to be 1 character larger then the input value. The reason I do this is that if I didn't, then the character would overflow outside the text-box and only when the user would let go of the key, the text-box would expand. This looks weird. That's why I have to anticipate the new character - I enlarge the text-box on each keydown, ergo, before the character appears in the text-box. As you can see in the demo, this method looks great.
在演示中,我有一个 keydown 和 keyup 处理程序。keyup 处理程序根据输入值调整文本框大小。但是,keydown 处理程序将大小设置为比输入值大 1 个字符。我这样做的原因是,如果我不这样做,那么字符会溢出文本框之外,只有当用户松开键时,文本框才会展开。这看起来很奇怪。这就是为什么我必须预测新字符的原因 - 在字符出现在文本框中之前,我会放大每个按键上的文本框。正如您在演示中看到的,这种方法看起来很棒。
However, the problem are the BACKSPACE and ARROW keys - they will also expand the text-box on keydown, and only on keyup the text-box size will be corrected.
但是,问题在于 BACKSPACE 和 ARROW 键 - 它们还会在 keydown 上扩展文本框,并且只有在 keyup 上,文本框大小才会得到纠正。
A work-around:
解决方法:
A work-around would be to detect the BACKSPACE, SHIFT, and ARROW keys manually and act based on that:
一种变通方法是手动检测 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);
}
}
This works (and looks great) for BACKSPACE, SHIFT, ARROW LEFT and ARROW RIGHT. However, I would like to have a more robust solution.
这适用于(并且看起来很棒)BACKSPACE、SHIFT、ARROW LEFT 和 ARROW RIGHT。但是,我想要一个更强大的解决方案。
采纳答案by Tim Down
This I think will do the job, or if not is very close and will need only minor tweaking. The thing you have to remember is that you can't reliably tell anything at all about any character that may be typed in a keydown
or keyup
event: that all has to be done in a keypress
handler. The definitive resource for key events is http://unixpapa.com/js/key.html
我认为这可以完成工作,或者如果不是非常接近并且只需要进行微小的调整。您必须记住的是,您根本无法可靠地告诉任何可能在 akeydown
或keyup
事件中键入的字符:所有这些都必须在keypress
处理程序中完成。关键事件的权威资源是http://unixpapa.com/js/key.html
You also need to consider pastes, which this code won't handle. You will need to have separate paste
event handler (although this event isn't supported in Firefox < 3.0, Opera, and very old WebKit browsers). You'll need a timer in your paste handler since it's impossible in JavaScript to access the content that's about to be pasted.
您还需要考虑粘贴,此代码无法处理。您需要有单独的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))">
回答by mike-shtil
Here's a much simpler solutionwhich worked well for me:
这是一个更简单的解决方案,对我来说效果很好:
document.addEventListener('keyup', event => {
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'
}
});
This doesn't require probing a DOM element (which would add latency and ugliness).
这不需要探测 DOM 元素(这会增加延迟和丑陋)。
Updated example use:
更新示例使用:
回答by Visruth
The possible solution I can find is checking the length of key in event.
我能找到的可能解决方案是检查事件中键的长度。
Eg:-
例如:-
<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>
So, if you press any characters/symbols, the event.key
will contain that character and its length will be 1. If you press character Vthen the event.key
will have value Vbut if you press enter key then it will contain value Enter, if you press shift then Shiftand so on. Therefore, if a key doesn't produce a character then its length will be greater than 1.
因此,如果您按任何字符/符号,event.key
将包含该字符,其长度将为 1。如果您按字符V则其event.key
值为V但如果您按 enter 键则它将包含值Enter,如果您按 shift然后Shift等等。因此,如果一个键不产生一个字符,那么它的长度将大于 1。
Updated
更新
Some special keys in the keyboard produce symbol and its length may be greater than 1 so I modified the code so that it can alert even if it's not a symbol. Eg:- its length is 2. Some mobile keyboards have shortcut keys for such symbols.
键盘中的一些特殊键会产生符号,其长度可能大于 1,因此我修改了代码,使其即使不是符号也能发出警报。例如:- 它的长度是 2。一些移动键盘有这些符号的快捷键。
A non character/symbol key in the keyboard will always be a combination of alphabets, number characters or of both, Eg:- F2, Shift.
键盘中的非字符/符号键将始终是字母、数字字符或两者的组合,例如:- F2、Shift。
Thanks @Vicky Chijwani for bringing attention to this scenario.
感谢 @Vicky Chijwani 引起人们对这种情况的关注。
回答by Jeff
OK, I think I've got it. The solution is a bit hackish, but actually works really well.
好的,我想我明白了。该解决方案有点hackish,但实际上效果很好。
On keydown, do a setTimeout for 1 millisecond, that calls a function to check/change the length of your input box.
在 keydown 上,执行 1 毫秒的 setTimeout,调用函数来检查/更改输入框的长度。
http://jsfiddle.net/rygar/e2wQM/
http://jsfiddle.net/rygar/e2wQM/
It seems to work really well, especially in a few places where your version doesn't (e.g. backspace, CTRL+V, or selecting a whole bunch of text and hitting delete)
它似乎工作得很好,尤其是在您的版本没有的一些地方(例如退格、CTRL+V 或选择一大堆文本并点击删除)
Edit: Even setTimeout with a 0ms delay seems to work!
编辑:即使 setTimeout 延迟为 0ms 似乎也有效!
回答by mariana soffer
You should use the property keyEventArgs.Key in the keydown function, this will return the numeric value that will depend on the system.
您应该在 keydown 函数中使用属性 keyEventArgs.Key,这将返回取决于系统的数值。
here is a link that has the different key codes for the different browsers and OS:
这是一个链接,其中包含针对不同浏览器和操作系统的不同密钥代码:
回答by Larry K
Your goal of keeping the textbox larger than the text that has been entered into it.
您的目标是保持文本框大于输入的文本。
I'd accomplish this by planning on having room for two additional characters (not one) in the text box. Then:
我会通过计划在文本框中为两个额外的字符(不是一个)留出空间来实现这一点。然后:
// 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.
}
}
The advantage of the above is that you don't need to descend into the nether world of keycodes.
上面的好处是你不需要深入到键码的世界。
回答by Jeff
This may not be the method that you're looking for, but you can just check the value of this.value.length
in your keydown function. The return value is the length of the text in the input field BEFORE the new character is added. So if you check the length again in the keyup function, it will be greater if the user pressed a character, but the same if the user hit the shift key.
这可能不是您正在寻找的方法,但您可以检查this.value.length
keydown 函数中的值。返回值是在添加新字符之前输入字段中文本的长度。所以如果你在keyup函数中再次检查长度,如果用户按下一个字符会更大,但如果用户按下shift键则相同。
回答by Liam Bailey
I presume you are setting up a counter on the length of an input field, in which case you don't need to be so fancy, you can just keep assigning the length of the field to a variable, and when the user gets to your max length only allow them to press delete or backspace like so:
我假设您正在对输入字段的长度设置一个计数器,在这种情况下,您不需要那么花哨,您可以继续将字段的长度分配给一个变量,当用户到达您的最大长度只允许他们按删除或退格键,如下所示:
$("input:text").keypress(function() {
var current = $(this).val().length;
if (current >= 130) {
if (e.which != 0 && e.which != 8) {
e.preventDefault();
}
}
}
You can use the current variable to display the counter as well, or do maxlength - current to do a countdown of how many charachters are left
您也可以使用 current 变量来显示计数器,或者执行 maxlength - current 来倒计时剩余的字符数