1

I found this excellent question about binding the arrow keys with jQuery: Binding arrow keys in JS/jQuery with a great solution from Sygmoral:

$(document).keydown(function(e) {
    switch(e.which) {
        case 37: // left
        break;

        case 38: // up
        break;

        case 39: // right
        break;

        case 40: // down
        break;

        default: return; // exit this handler for other keys
    }
    e.preventDefault(); // prevent the default action (scroll / move caret)
});

EXCEPT: This prevents the arrow keys from working the way they would usually work when the focus is in a text input field.

How would I modify this solution to allow the arrow keys to function normally when the current focus is in an input, text area, or another content editable area?

Stephen Ostermiller
  • 23,933
  • 14
  • 88
  • 109

3 Answers3

8

Put this in a condition:

$(document).keydown(function(e) {
    if(!$(e.target).is(':input, [contenteditable]')){
        switch(e.which){
           // the cases as is
        }
        e.preventDefault(); // prevent the default action (scroll / move caret)
    }
});
Jai
  • 74,255
  • 12
  • 74
  • 103
  • 1
    Just to check -- `.is(':input')` covers textareas as well? – Stephen Ostermiller Jul 26 '16 at 07:47
  • Absolutely! `:input` covers all the input elements including textarea, select, button etc. – Jai Jul 26 '16 at 07:48
  • 1
    I think the test could be simpler: `if(!$(e.currentTarget).is(':input,[contenteditable]')){` because `.is()` takes a selector that can have `OR` conditions separated by commas. Correct? – Stephen Ostermiller Jul 26 '16 at 07:52
  • Yes! That is way shorter. For the readability i just used such way. Can be done. – Jai Jul 26 '16 at 07:53
  • 1
    I think it should be `e.target` instead of `e.currentTarget `. The `currentTarget` will always be `document` since that is the element the listener was set to. – Titus Jul 26 '16 at 07:53
  • @Titus any issues with `currentTarget`? – Jai Jul 26 '16 at 07:54
  • @Titus `currentTarget` has little advantage in such case if you [read the doc here about `currentTarget`](https://developer.mozilla.org/en-US/docs/Web/API/Event/currentTarget) – Jai Jul 26 '16 at 07:56
  • 2
    Yes I've read that and it says `It always refers to the element the event handler has been attached to as opposed to event.target which identifies the element on which the event occurred.` which means that in this case, `currentTarget` will always be the `document`. – Titus Jul 26 '16 at 07:58
  • hmm...! This is where i agreed with you. nice catch. – Jai Jul 26 '16 at 08:01
0

You can use event.target to get the target element of event, so you can check

var $target = $(e.target);
if($target.is("input") || $target.is("textarea")) {
    //
}
Arun Ghosh
  • 7,634
  • 1
  • 26
  • 38
-2

Your editable element may have some common class

$('.input').keypress(function(event) {

    var charCode = (evt.which) ? evt.which : event.keyCode

    switch(charCode) {
        case 37: // left
        break;

        case 38: // up
        break;

        case 39: // right
        break;

        case 40: // down
        break;

        default: return; // exit this handler for other keys
    }
    e.preventDefault();  
});
Happy Coding
  • 2,517
  • 1
  • 13
  • 24
  • That would do the opposite of what I want. I want to bind the keys to previous and next functionality unless the focus is in an input (where the arrow keys are used for moving the cursor). – Stephen Ostermiller Jul 26 '16 at 07:54