我想做的是将键控代码放入一个数组中,以便以后做一些有趣的事情。因此,我捕获了击键,获得了插入符号的位置,并将键代码放入数组中(在MooTools的帮助下):
var keyArray = [];
$('form').addEvent('keyup', function(event) {
var pos = document.activeElement.getCaretPosition();
keyArray[pos] = event.code;
});
通常来说,这很好。但是,在控制台中显示整个数组时,我注意到数组中有一些undefined
值。进一步探讨这一点,我发现快速键入时,插入符号位置似乎失去了跟踪,或者响应速度很快/很慢。我做了一个jsfiddle来演示这一点:http://jsfiddle.net/HQVR8/1/
如果在此示例中快速键入,您将看到一个插入符号位置序列,如
- 1 - 2 - 3 - 5 - 6 - 6.
但是慢速输入时是
- 1 - 2 - 3 - 4 - 5 - 6.
当然,现在快速键入时的麻烦是我的数组中有一个undefined
值,并且覆盖了一个数组项。因此结果是不同的。
我的问题是,是否可以让插入符号的位置保持跟踪。我尝试使用'native'selectionStart
代替,但结果相同。我还尝试在keydown
事件中捕获插入符位置,然后将其放入keyup
事件中的数组。没有不同。我想知道是否只需稍作停顿(即强迫用户键入较慢的声音)就可以解决问题,但这感觉就像是骇客,我更喜欢“适当的”解决方案。希望有一个。
您基本上是通过使用数组而不是对象来弄乱的。
数组索引是狡猾的,如果不小心,可以创建sparse arrays
。例如:
var foo = [];
foo[0] = "one!"; // foo.length = 1;
foo[2] = "two!"; // foo.length = 3, foo[1] = undefined
因此,如果您输入得太快而跳过返回值,则可能就是这样做。另外,粘贴等可以将插入符号进一步向下推...
您可能可以使用一个对象,尽管并不能保证所有浏览器中的键与键的顺序,尤其是Webkit,Webkit倾向于重新排序并将数字键放在对象键循环的顶部...但是如果您加上前缀键,例如“ pos” + caretIndex,您应该获得FIFO
解决您需要提取未定义的实际代码的一种方法是通过Array.filter。
例如
retArray = Array.filter(retArray, function(el) {
return el !== undefined;
});
有了一个对象,您可以做:
console.log(Object.values(foo));
[经过更多测试后,它似乎是特定于keyup
的行为。当我使用keydown
时,我do得到一致的序列:http://jsfiddle.net/HQVR8/3/
[一个缺点是,当您正在执行'值收集'时,keydown
落后于keyup
,但是在我的环境中,这只是一个小问题。
[行为上的差异对我来说似乎很奇怪:当您一次按四个键时,keyup
对所有这些键都显示相同的插入符位置,而keydown
显示四个独立的插入符位置。这似乎很奇怪,因为您一次按下它们,但又一次按下它们,因此插入符号的“读数”应该相同。
转到JSfiddle并用这个来摆弄:
a)按下'q',然后按下'w',然后释放'q',然后释放'w'(足够快以避免自动重复)。当您用一根以上的手指快速输入时,这种序列很常见:)。
b)按住任何键足够长时间,以使自动重复启动。
差异清晰可见
基本上,keyUp
在释放物理键时触发,但是
keyDown
被自动重复调用,而keyUp
不是由于字体位置和任何文本区域更新都与keyDown
保持同步,因此在监视keyUp
时,您将完全错过中间步骤。
在情况(a)中,keyUp
处理程序会在释放“ q”时看到carret pos从0跳到2,因为在释放第一个键之前已经键入了两个字符。释放“ w”不会改变刀架的位置,因此处理程序最终将q和w都存储在位置2。]
在情况(b)中,处理程序完全错过了重复项,并且仅存储键的最后一个实例。
作为结论,使用KeyUp
将永远达不到预期的意义。
[keyDown
可以,但是就我个人而言,我宁愿钩住changed
事件。
我认为检测到一个自动程序填充该字段同样可靠(毕竟,合法用户也想粘贴密码),而且您不必费心使用诸如退格键或其他任何非控制键的控制键。键盘清除输入的方法。
您可以使用keyUp
作为额外的偏执检查,只要您不希望重建确切的输入即可。例如,您可以简单地检查释放的键是否与当前光标位置的字符匹配。但坦率地说,我不确定是否值得打扰。