views:

437

answers:

5

I have a key listener assigned to the arrow keys to navigate a slideshow. But I want to disable the key listener, temporarily, while a user is typing inside an input field. How can I do that? My current code looks like this:

//Listen to the keys
    function checkKey(e) {
    switch (e.keyCode) {
    case 37:
        changeImage('prev');
        break;
    case 39:
        changeImage('next');;
        break;
        }
    }
    if (jQuery.browser.mozilla) {
            jQuery(document).keypress (checkKey);
    } else {
            jQuery(document).keydown (checkKey);
    }

Thank you.

+2  A: 

A bit ugly, but should work:

var moz = jQuery.browser.mozilla;
if (moz) {
    jQuery(document).keypress(checkKey);
} else {
    jQuery(document).keydown(checkKey);
}
jQuery("#myInput").focus(function() {
    if (moz) {
        jQuery(document).unbind("keypress");
    } else {
        jQuery(document).unbind("keydown");
    }
}).blur(function() {
    if (moz) {
        jQuery(document).keypress(checkKey);
    } else {
        jQuery(document).keydown(checkKey);
    }
});
karim79
+1 too fast for me ..
Gaby
Thanks. Would there be any reason for me not to apply this globally to all input on the page, e.g., jQuery("input")?Also, is there a way to apply this to "input" and "textarea" in one shot ? Thanks so much.
ensnare
You could use my example and simply add input to the possible focused elements.
Anthony
@ensnare - you can bind to multiple selectors by space-separating them: e.g.: `jQuery("input, textarea").keypress(...`
karim79
This is working perfectly on "textarea" but i cannot get it to respond to "input"
ensnare
A: 

Add onfocus and onblur event to the input field and set a global variable value. Check for that global variable in the begining of your checkKey event handler.

<input type="textbox" onfocus="window.inTextBox = true;" onblur="window.inTextBox = false;" />

function checkKey(e) {
 if (!window.inTextBox)
 {
  ...
 }
}
Ilya Volodin
A: 

I really like the simplicity of Ilya Volodin's suggestion, but I would set the event handler in the script and not embed it into the html:

  var textFocus = false; 

  $("textbox").focus(function() {
      textFocus = true;
   });

  $("textbox").blur(function() {
      textFocus = false;
   });

  function navKeys() {
       if (textFocus) {
            return false;
       } else {
       ......
       }
   }

This would be even simpler if jquery had :focus as a selector.

      function navKeys() {
       if ($("textbox:focus") {
            return false;
       } else {
       ......
       }
   }

But that is just hypothetical code at this point.

Anthony
I agree it would be a simpler way of doing it for a small page. But I do JavaScript optimization for a living, and it's a habit of the trade. Wiring up event handlers inside JavaScript code is much less preferment then doing simple onfocus/onblur inside HTML. There're, however, cases when you have to do it from the code. Like if you need to wire event to every textbox on the page.That's also why I don't like Karim79's solution. Wiring and unwiring events all the time is very costly.
Ilya Volodin
A: 

If the focus is on an input element then that element will be the target for key events.

So you could just do a check on event.target.tagName.

e.g.

function checkKey(e) {  
  switch (e.target.tagName) {  
    case "INPUT": case "SELECT": case "TEXTAREA": return;  
  }  
  // rest of your handler goes here ...  
}  
Sean Hogan
+1  A: 

First, there's no need for the browser check. For checking arrow keys, just use the keydown event for all keys.

Second, I suggest (as Sean Hogan did) checking the target of the event before doing the slideshow stuff. The following will work on all mainstream desktop browsers:

document.body.onkeydown = function(evt) {
    evt = evt || window.event;
    var target = evt.target || evt.srcElement;
    var targetTagName = (target.nodeType == 1) ? target.nodeName.toUpperCase() : "";
    if ( !/INPUT|SELECT|TEXTAREA/.test(targetTagName) ) { 
        switch (e.keyCode) {
            case 37:
                changeImage('prev');
                break;
            case 39:
                changeImage('next');;
                break;
        }
    }
}
Tim Down
Would this work well inside jQuery?I tried this function but it did not work.
ensnare
In what way did it not work? How do you mean "inside jQuery"? You could certainly adapt it to use jQuery's event handling.
Tim Down