Prevent default behavior in text input while pressing arrow up

39,100

Solution 1

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

Solution 2

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

Solution 3

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!

Share:
39,100
riddle
Author by

riddle

Updated on October 20, 2020

Comments

  • riddle
    riddle over 3 years

    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?

  • riddle
    riddle almost 15 years
    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
    riddle almost 15 years
    Busted it! Thanks a lot, it’s perfect. :)
  • Manish Singh
    Manish Singh over 10 years
    Thanks man. The idea is to use the keydown event instead of keyup.
  • CmdrMoozy
    CmdrMoozy almost 10 years
    Right - keydown is the trick. Note that returning false seems to stop the event's propagation entirely, whereas preventDefault() will let the input box ignore the event, while still allowing other listeners to handle it as it bubbles up.
  • Mario J Vargas
    Mario J Vargas almost 10 years
    @Lukas , your solution worked best for me. However, I'm calling e.preventDefault(); instead of returning false. The latter didn't achieve the freezing of the up-arrow key behavior. Thanks for posting an alternate, simpler solution.
  • darylhedley
    darylhedley over 9 years
    This is the correct answer! I had to use the keydown event to stop the cursor moving and then the keyup event to get the input value when needed
  • NotJay
    NotJay over 8 years
    Up vote for "kludge"! Worked for me, thanks for the answer.
  • Nurul Huda
    Nurul Huda over 4 years
    Using e.code === 'ArrowUp' || e.code === 'ArrowDown' will make the code is much easier to read.
  • Robert Kujawa
    Robert Kujawa almost 3 years
    Perfect solution! Saved me so much time, I'm using Vue and all I had to do is <input @keydown.up.down.prevent />.