views:

428

answers:

4

I am fighting with a very strange javascript behavior on a jQuery UI widget I'm trying to fix. IE7 (win XP), jQuery 1.2.6 (yes, it's an old version).

The widget is a combo-box, which captures keyboard events and has special behaviors for the arrow keys.

When I try to type the "&" character into the flexbox input field, I get strange behavior.

The flexbox has some code like:

//initialization
$myInputElement.keypress($.flexbox.process_key);
$.flexbox.process_key = function process_key(e) {
    $.flexbox.flexboxFromInput(this).processKey(e);
    return true;
};

//on the flexbox object's prototype:
...
    processKey: function processKey(e) {
        var mod = 0;
            if (typeof (e.ctrlKey) !== 'undefined') {
                if (e.ctrlKey) mod |= 1;
                if (e.shiftKey) mod |= 2;
            } else {
                if (e.modifiers & Event.CONTROL_MASK) mod |= 1;
                if (e.modifiers & Event.SHIFT_MASK) mod |= 2;
            }
            ...
            switch (e.keyCode) {
                   case 38: // up
                       this.prevResult();
                       break;
                   case 40: // down
                       if (this.getCtr().is(':visible')) this.nextResult();
                       else this.flexboxDelay(true);
                       break;
               ...etc.
           }
    }
...

When I introduce a logging statement, what I find is that pressing "&" (shift+7) produces three keypress events:

INFO: Flexbox> processKey, keyCode=16, ctrl=false, shift=true
INFO: Flexbox> processKey, keyCode=55, ctrl=false, shift=true
INFO: Flexbox> processKey, keyCode=38, ctrl=false, shift=true

Apparently, keyCode 38 is both the up arrow key and the ASCII code for ampersand??

As I was writing this, it occurred to me that I can detect the keypress as "shift+7" (keyCode 55) to treat it as the ampersand key, then set some kind of flag to ignore the next keypress (which is the 38). This seems like a horrible hack.

Does anybody have a better way to differentiate between special characters such as "&" and the arrow keys in IE?

+1  A: 

I think keydown might give you more reliable data than keypress.

Tobias Cohen
Thanks for the reply! I'm not sure though if this is a viable option in my case. I need to capture the event whenever the user makes changes to the input (regardless whether or not it's an arrow key). If the user holds down a letter key, I think the keydown event will only be triggered once, for the first letter entered, and not for each change?
RMorrisey
+1  A: 

This is what I ended up doing:

    /*
     * Hack around a wierd behavior in IE where "&%'(" have the same keyCodes
     * as the arrow keys.
     */
    if (/55$|53$|57$/.test(e.keyCode) && (mod & 2) && !(mod & 1)) {
        this.ignoreNextArrowKey = true;
    }
    else if (/222$/.test(e.keyCode) && !(mod & 2) && !(mod & 1)) {
        this.ignoreNextArrowKey = true;
    }
    else if (/38$|37$|39$|40$/.test(e.keyCode) && this.ignoreNextArrowKey) {
        this.ignoreNextArrowKey = false;
        return;
    }

Hope this helps somebody. If you are reusing this code, you may have to adjust your usage of keyword 'this', depending on what object it refers to (here, it's a javascript object associated with the flexbox widget).

I'm still hoping for an alternative solution that's a bit less hackish =)

RMorrisey
A: 

key up or down returns a keyCode of 55 for '&' and 38 for 'Arrow Up'

kennebec
See my comment to Tobias' answer
RMorrisey
A: 

I recommend using this jquery library to write custom handlers for keypresses: http://code.google.com/p/js-hotkeys/

Trying to discern keycodes logically is a nightmare.

Neil McKeown