views:

874

answers:

3

I’m working with basic HTML <input type="text"/> text field with a numeric value.

I’m adding JavaScript event keyup to see when user presses arrow up key (e.which == 38) – then I increment the numeric value.

The code works well, but there’s one thing that bugs me. Both Safari/Mac and Firefox/Mac move cursor at the very beginning when I’m pressing the arrow up key. This is a default behavior for every <input type="text"/> text field as far as I know and it makes sense.

But this creates not a very aesthetic effect of cursor jumping back and forward (after value was altered).

The jump at the beginning happens on keydown but even with this knowledge I’m not able to prevent it from occuring. I tried the following:

input.addEventListener('keydown', function(e) {
    e.preventDefault();
}, false);

Putting e.preventDefault() in keyup event doesn’t help either.

Is there any way to prevent cursor from moving?

A: 

Probably not. You should instead seek for a solution to move the cursor back to the end of the field where it was. The effect would be the same for the user since it is too quick to be perceived by a human.

I googled some and found this piece of code. I can't test it now and it is said to not to work on IE 6.

textBox.setSelectionRange(textBox.value.length, textBox.value.length);

Leahn Novash
Thanks. Actually updating input.value will result in cursor moving back at the end. So I might detect cursor’s position and then restore it after change is made (if it’s in the middle of number, for example).But I’m still looking for better solution, if it’s available.
riddle
A: 

I tested the code and it seems that it cancels the event but if you don't press the arrow for very short time - it fires keypress event and that event actually moves cursor. Just use preventDefault() also in keypress event handler and it should be fine.

Unfortunately, `e.preventDefault()` in `keypress` event prevents me from entering anything there (I want inputs to work like in Firebug). And it doesn’t solve my problem, at least in my browser – cursor still jumps at the very beginning.
riddle
+3  A: 

To preserve cursor position, backup input.selectionStart before changing value (that's probably non-standard, but I couldn't be bothered to use DOM Ranges).

The problem is that WebKit reacts to keydown and Opera prefers keypress, so there's cludge: both are handled and throttled.

var ignoreKey = false;
var handler = function(e)
{
    if (ignoreKey)
    {
        e.preventDefault();
        return;
    }
    if (e.keyCode == 38 || e.keyCode == 40) 
    {
        var pos = this.selectionStart;
        this.value = (e.keyCode == 38?1:-1)+parseInt(this.value,10);        
        this.selectionStart = pos; this.selectionEnd = pos;
        ignoreKey = true; setTimeout(function(){ignoreKey=false},1);
        e.preventDefault();
    }
};

input.addEventListener('keydown',handler,false);
input.addEventListener('keypress',handler,false);
porneL
Busted it! Thanks a lot, it’s perfect. :)
riddle