Question

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?

Was it helpful?

Solution

To preserve cursor position, backup input.selectionStart before changing value.

The problem is that WebKit reacts to keydown and Opera prefers keypress, so there's kludge: 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);

OTHER TIPS

I found that a better solution is just to return false; to prevent the default arrow key behavior:

input.addEventListener("keydown", function(e) {
    if (e.key === 'ArrowUp' || e.key === 'ArrowDown') return false;
}, false);

Actually, there is a better and simpler method to do this job.

$('input').bind('keydown', function(e){
    if(e.keyCode == '38' || e.keyCode == '40'){
        e.preventDefault();
    }
});

Yes, it is so easy!

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.

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);

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top