【问题标题】:Caret position not keeping track?插入符号位置没有跟踪?
【发布时间】:2012-05-09 08:15:17
【问题描述】:

我正在尝试做的是将关键代码放在一个数组中,以便以后做一些有趣的事情。因此,我捕获击键,获取插入符号位置并将键代码放入数组中(在 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 值,我覆盖了一个数组项。所以结果不一样。

我的问题是我是否可以以某种方式让插入符号位置保持跟踪。我尝试使用“本机”selectionStart,但结果是一样的。我还尝试在keydown 事件中捕获插入符号位置,并将其放入keyup 事件中的数组中。没有不同。我想知道是否使用小暂停(即强迫用户输入更慢)可以解决它,但这感觉就像一个黑客,我更喜欢一个“正确”的解决方案。希望有一个。

【问题讨论】:

  • 你为什么要这样做?键码有什么用?
  • 我将所有密钥代码加起来,并使用这个数字作为额外的安全措施。关键是我想确保人们正在输入(在这种情况下是密码),所以我会捕获击键(省略功能键等)。总和应该始终相同,但不会公开实际密码(因为其他字母可能加起来相同)。
  • 对。那么,您还有其他问题,因为用户可以在您的密码框中使用箭头键或鼠标通过在任何位置插入和删除字符来编辑密码。老实说,我认为这不是首发。
  • 这不是问题,因为保存了插入字符的位置。鼠标、选择、箭头键没有区别。

标签: javascript mootools mootools-events


【解决方案1】:

你基本上是在使用数组而不是对象来制造混乱。

数组索引很狡猾,如果你不小心,可以创建sparse arrays。例如:

var foo = [];
foo[0] = "one!"; // foo.length = 1;
foo[2] = "two!"; // foo.length = 3, foo[1] = undefined

所以如果你输入得太快而跳过返回值,它可能就是这样做的。此外,粘贴等可以将插入符号进一步向下推...

你可能可以使用一个对象,尽管在所有浏览器中都不能保证键的顺序与键的顺序 - 特别是 webkit,他们倾向于重新排序并将数字键放在对象键循环的顶部......但是如果你像 "pos" + caretIndex 这样的键前缀,你应该得到 FIFO

解决您需要提取没有未定义的实际代码的一种方法是通过 Array.filter。

例如。

retArray = Array.filter(retArray, function(el) {
    return el !== undefined;
});

有了一个对象,你可以这样做:

console.log(Object.values(foo));

【讨论】:

  • 这解决了undefined 问题,但我看不出它如何解决索引(插入符号)不正确 - 或者,不是您认为的位置。实际上,我在早期版本中有一个对象,无法让它与sum() 一起使用,所以我切换到了数组。但是,我想我通过使用keydown 而不是keyup 解决了这个问题。我会在这里发布我的答案。
  • 您应该禁止粘贴而不是执行所有这些操作 - 您可以通过将粘贴设置为原生事件然后简单地添加一个停止事件的 onPaste 处理程序来轻松做到这一点。
  • 有了数组,你就不能arr.clean()吗?我的目标不仅仅是停止粘贴,还包括生成额外的安全代码并提供一些视觉反馈。
  • Array.filter 清理得很好,但这会重新索引数组,因此索引失去了作为插入符号链接的意义。您也可以在 keyup 和 re-base 上遍历字符串。有关他们做得如何的反馈,请考虑:github.com/DimitarChristoff/StrongPass - 您可以只使用事件并调整正则表达式/通过级别或让它输出,具体取决于您的需要。这是一个带有纯文本警告的示例小提琴。 jsfiddle.net/dimitar/nZn6A。无论如何,您都可以根据字符串的哈希生成安全代码。
  • mootools.net/forge/p/moocrypt - moocrypt(更新)可以让你做一些花哨的事情来增加安全性。
【解决方案2】:

经过更多测试,这似乎是keyup 特有的行为。当我使用keydown 时,我确实得到一个一致的序列:http://jsfiddle.net/HQVR8/3/

一个缺点是keydown 在您进行我正在做的“价值收集”时比keyup 落后一步,但在我的设置中,这只是一个小问题。

在我看来,行为上的差异很奇怪:当您一次按下四个键时,keyup 会为所有这些键显示相同的插入符号位置,而 keydown 则显示四个单独的插入符号位置。这看起来很奇怪,因为您同时按下它们,但同时又按下它们,所以插入符号的“读数”应该是相同的。

【讨论】:

    【解决方案3】:

    转到 JSfiddle 并摆弄这个:

    a) 按下“q”,然后按下“w”,然后释放“q”,然后释放“w”(足够快以避免自动重复)。当您用一个以上的手指“快速”键入时,这种顺序经常发生:)。

    b) 按住任意键的时间足够长,以便自动重复开始。

    区别一目了然

    基本上,keyUp 在释放物理键时触发,但是

    • 可以在释放前一个键之前按下另一个键
    • keyDown 在自动重复的情况下被调用,而 keyUp 不是

    由于 carret 位置和任何文本区域更新都与 keyDown 保持同步,因此您在监视 keyUp 时会错过中间步骤。

    在情况 (a) 中,keyUp 处理程序看到 carret pos 在释放 'q' 时从 0 跳转到 2,因为在释放第一个键之前已经键入了两个字符。 'w' 的释放不会改变 carret 位置,因此处理程序最终将 q 和 w 都存储在位置 2。

    在情况 (b) 中,处理程序完全错过重复,并且只存储键的最后一个实例。

    作为结论,使用KeyUp 永远不会达到预期的含义。

    keyDown 可以,但就我个人而言,我更愿意挂钩 changed 事件。

    我认为检测填充该字段的机器人同样可靠(毕竟,合法用户也可能想要粘贴密码),并且您不必担心退格或其他任何非控制键-键盘清除输入的方法。

    您可以使用keyUp 作为额外的偏执检查,只要您不期望重建确切的输入。例如,您可以简单地检查释放的键是否与当前光标位置的字符匹配。但坦率地说,我不确定这是否值得。

    【讨论】:

      猜你喜欢
      • 2013-07-18
      • 1970-01-01
      • 1970-01-01
      • 2012-03-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-06
      相关资源
      最近更新 更多