Caret position not keeping track?

我只是一个虾纸丫 提交于 2020-01-04 05:35:57

问题


What I'm trying to do is put key codes in an array, to do some interesting stuff with later on. So, I capture the keystrokes, get the caret position and put the key code in the array (with some help from MooTools):

var keyArray = [];
$('form').addEvent('keyup', function(event) {
    var pos = document.activeElement.getCaretPosition();

    keyArray[pos] = event.code;
});

Generally speaking, this works great. However, I noticed some undefined values in my array when showing the complete array in my console. Exploring this further, I found out that when typing quickly, the caret position seems to lose track, or being quick/slow to respond. I've made a jsfiddle to demonstrate this: http://jsfiddle.net/HQVR8/1/

If you type quickly in this example, you'll see a caret position sequence like

- 1 - 2 - 3 - 5 - 6 - 6.

But when typing slowly, it's

- 1 - 2 - 3 - 4 - 5 - 6. 

Of course, the trouble now when typing quickly is that I have a undefined value in my array and I overwrite one array item. So the result is different.

My question is if I can somehow let the caret position keep track. I've tried using the 'native' selectionStart instead, but results are the same. I also tried capturing the caret position in a keydown event and putting it in an array in the keyup event. No difference. I'm wondering if using little pauses (ie. forcing the user to type slower) might solve it, but this feels like a hack and I would prefer a 'proper' solution. Hopefully, there is one.


回答1:


you are basically making a mess by using an array instead of an object.

array indexes are dodgy and can create sparse arrays if you are not careful. for instance:

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

so if you type too fast and skip the return value, it is probably doing just that. also, pasting etc can push caret further down...

you can probably use an object though there are no guarantees on the order of keys in vs keys out in all browsers - particularly webkit, who tend to reorder and put numeric keys at top of object key loops... but if you prefix the key like "pos" + caretIndex, you ought to get FIFO

one way to solve your need to extract the actual codes w/o the undefined is via Array.filter.

eg.

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

With an object, you can just do:

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



回答2:


After some more tests, it appears to be a behavior specific to keyup. When I use keydown I do get a consistent sequence: http://jsfiddle.net/HQVR8/3/

One disadvantage is that keydown is a step behind keyup when you're doing the 'value collecting' I'm doing, but in my setting, this is only a minor issue.

The difference in behavior appears odd to me: when you press four keys at a time, the keyup displays the same caret position for all of them, while keydown is showing four separate caret positions. This seems odd because you press them at once, but also depress them at once, so the caret 'readings' should be the same.




回答3:


go to the JSfiddle and fiddle with this:

a) depress 'q', then depress 'w', then release 'q', then release 'w' (fast enough to avoid autorepeat). That kind of sequence happens quite often when you type 'quickly' with more than one finger :).

b) leave any key depressed long enough for the autorepeat to kick in.

The differences are in plain view

Basically, keyUp fires when the physical key is released, but

  • another key can be depressed before the previous one is released
  • keyDown is called in case of autorepeat, while keyUp isn't

Since carret position and whatever text area updates are kept in sync with keyDown, you will simply miss the intermediate steps when monitoring keyUp.

In case (a), the keyUp handler sees carret pos jump from 0 to 2 as 'q' is released because two characters have been typed before the first key was released. The release of 'w' does not change carret position, so the handler ends up storing both q and w at position 2.

In case (b), the handler misses the repeats completely, and stores only the last instance of the key.

As a conclusion, using KeyUp will never achieve the intended meaning.

keyDown could, but personnally I would rather hook the changed event.

I reckon it is no less reliable to detect a bot filling the field (after all, a legit user could want to paste the password too), and you won't have to bother with control keys like backspace or whatever other non-keyboard means of clearing the input.

You could use keyUp as an extra paranoid check, as long as you don't expect to reconstruct the exact input. For instance, you could simply check that the released key matches the character at current cursor position. But frankly I'm not sure it is worth the bother.



来源:https://stackoverflow.com/questions/10512272/caret-position-not-keeping-track

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!