Question

Pressing the tab key which triggers a focus change is also received by the input receiving the focus as a keyup.

a: <input type='text'/><br/>
b: <input type='text' onkeyup='alert("wtf?")'/><br/>

http://jsfiddle.net/59SnP/

As my control also uses tab (not in the example), I would want the focus related keyup event being consumed (but I want to receive other non-focus-change related tab events). I tried to research the rationale behind the current behavior but found nothing. The question: Where is this current behavior specified (event not consumed by focus change), and what would be a cross-browser workaround to force consuming it. Thx.

Était-ce utile?

La solution

You can try this. I changed your keyup event in your input :

<input type='text' onkeyup="if(!tabPressed){ alert('This is it !'); }"/>

And I added a little event handler which will raise a flag when the tab button is pressed :

var tabPressed = false;
document.addEventListener('keydown', function (e) {
    if(e.keyCode == 9) {
        tabPressed = true;   
    } else {
        tabPressed = false;
    }
}, false);

Autres conseils

Based on Nathan's insight, here is a fully working example:

// First part of Nathan's HACK (set a sentinel when a focus changing tab has happened)
var tabPressed = false;
// remove this listener to break the functionality
$(document).on("keydown", function (e) {
    if(e.keyCode == 9) {
        tabPressed = true;   
    } else {
        tabPressed = false;
    }
});

// The listener on the client input that would kill the keyup tab event upon focus change
$("#magic").on("keyup", function(e) {
    if (tabPressed && e.keyCode==9) {
        tabPressed = false; // reset the sentinel
        e.stopImmediatePropagation()
        e.preventDefault()
    }
})

And here is the second part, which is a simple skeleton of something meaningful. We disable TAB inside the input, and log it as we do with other keyups:

$("#magic").on("keydown", function(e) {
    if (e.keyCode==9) {
        e.preventDefault()
        e.stopPropagation()
    }
})

$("#magic").on("keyup", function(e) {
    $(this).val($(this).val() + " " + e.keyCode)
    e.stopPropagation()
    e.preventDefault()
})

The HTML backing the story is as simple as:

a: <input type='text'/><br/>
b: <input type='text'/><br/>
c: <input type='text' id='magic'/><br/>

If you want to play with it, here it is on jsfiddle

NOTE: This still is not the perfect solution, the sentinel is just reset inside the control, so if a tabpress moving the focus does not activate our input, the sentinel stucks, and the first event will be swallowed.. So here is an example of wrong behaviour:

  1. Click on input A
  2. Press TAB (focus moves to input B, tabPressed becomes true)
  3. Click on input C
  4. Press TAB (it is eaten up as sentinel is true)
  5. Press TAB (now it goes through)

Still it is slightly better to have to press TAB twice as to have something happening automatically, wo user control...

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top