3

I am building a chat application and I am trying to make sure that any time a user presses a key, the key they press ends up getting entered into a specific element (an editable HTML document ui.rte1Content in an iframe ui.rteIFrame, to be exact). This should happen no matter which element on the page currently has focus. I only care about supporting Firefox and Chrome.

So far, I've registered a handler on the window.onkeydown event:

function captureKeyDown(e) {
    console.log("Capturing: " + e.keyCode);

    // We ignore certain keys such as page up, as well as keys pressed with
    // alt or ctrl, except for a few select combos like ctrl+b
    if(!ignoreKeys.contains(e.keyCode) && !e.altKey && 
      (!e.ctrlKey || (e.ctrlKey && validCtrlKeys.contains(e.keyCode)))) {
        ui.rte1Content.focus(); // Chrome prefers this.
        if(!rteHasFocus) {
            ui.rteIFrame.focus(); // Firefox prefers this
        }
        //alert("A commented out alert");
    }
}

This works perfectly in Firefox: rteIFrame gets focus, the key that's been pressed shows up, and we carry on. However, in Chrome (23.0.1271.95), while rte1Content correctly gets focus in time for the NEXT letter to show up, the initial letter that first triggered the event disappears into the ether.

For what it's worth, if I uncomment out the alert statement, the letter shows up just fine in Chrome. I have no idea why this is.

Does anyone have any suggestions about how I can get this to work?

Swiftheart
  • 443
  • 1
  • 5
  • 17

1 Answers1

0

For the "alert() thing", it's simply because in Chrome the focus is lost when an alert() occurs. To test that, try to open the JavaScript console (CTRL+SHIFT+J in Chrome, CTRL+SHIFT+K in Firefox), select something or focus on something on any page then type in the console alert("test");, you gonna see that the focus is lost. Then try in Firefox, the focus is kept.

Also I feel like you are doing stuff the complicated way ahah! Why not just using a <textarea> tag to store keyboard input ? Also, if you plan on making a chat application by passing data trough an iframe with the COMET technique or maybe some long pooling, etc.. I would really suggest that you google WebSockets as you gonna be able to make a more modern and optimized chat with this. It would be perfect also in your case because you seams to focus only on Firefox and Chrome, two browsers that correctly support WebSockets. :)

WiMantis
  • 376
  • 3
  • 11
  • I'm not using a textarea mostly as a side effect of using this rich text editor library, http://www.kevinroth.com/rte/demo.htm which uses an editable iframe. And yeah, I know that the focus is lost when an alert occurs, but I'm not sure why that would make the typed character appear in the right place. I also don't know how to simulate that positive effect without the alert() (I already tried randomly setting the focus to something else and then setting it back). – Swiftheart Dec 09 '12 at 09:43
  • Ohh sorry I rode that it wasn't working when the alert was uncommented... I definitely need some sleep. A way around you could explore : [here](http://stackoverflow.com/questions/961532/firing-a-keyboard-event-in-javascript), consisting of manually firing keyboard events instead of "moving it to the right place".. or you could try to add tons of eventsListeners to keep focus on the editor on every mouseClicks, mouseMoves, etc.. and hope that every pressed characters will go in the editor, but that would definitively be a dusty last resort solution. – WiMantis Dec 09 '12 at 10:09
  • I actually tried manually firing the keyboard event. It correctly triggered my onkeydown handler, but the character never appeared (even when I made sure the focus was already in the right place to eliminate any problems related to that). I did some googling and found [this](http://stackoverflow.com/questions/4158847/is-there-a-way-to-simulate-key-presses-or-a-click-with-javascript) which says that, "in Chrome [manual events] only fire the event handlers and don't perform any of the default actions." I don't know if that's trustworthy or not, but it squares with my experience. – Swiftheart Dec 09 '12 at 10:23
  • (For the record, I also tried just manually adding the character to the innerHTML of the text area, but that opens a whole new pandora's box related to problems with cursor positioning in a non-textarea and meta keys and so on and so forth.) As a hack in the meantime, yeah, I basically keep calling focus() every time the user clicks outside the editor, but this is far from ideal. Ideally, I'd like the focus to be able to stay in certain other fields and only revert back on a keypress. – Swiftheart Dec 09 '12 at 10:25
  • So I've discovered that, in Chrome, the keypress event never seems to fire on any particular element, which I guess is why the default action (the letter appearing) never occurs. Is it possible that the keypress event fires while the focus is "in between" elements?? As an annoying workaround, I am currently using [jquery-simulate-ext](http://j-ulrich.github.com/jquery-simulate-ext/) to simulate key presses directly on rte1Content. This kind of works, but it still fails for a lot of cases (up and down arrows, ctrl+v, etc.). I would still love to find a simple fix to the original question. – Swiftheart Dec 11 '12 at 15:20