views:

2990

answers:

4

I've noticed a strange behaviour of the live() function in jQuery:

<a href="#" id="normal">normal</a>
<a href="#" id="live">live</a>

$('#normal').click(clickHandler);
$('#live').live('click', clickHandler);

function clickHandler() {
    alert("Clicked");
    return false;
}

That's fine and dandy until you right-click on the "live" link and it fires the handler, and then doesn't show the context menu. The event handler doesn't fire at all (as expected) on the "normal" link.

I've been able to work around it by changing the handler to this:

function clickHandler(e) {
    if (e.button != 0) return true;
    // normal handler code here
    return false;
}

But that's really annoying to have to add that to all the event handlers. Is there any better way to have the event handlers only fire like regular click handlers?

+6  A: 

It's a known issue:

It seems like Firefox does not fire a click event for the element on a right-click, although it fires a mousedown and mouseup. However, it does fire a click event on document! Since .live catches events at the document level, it sees the click event for the element even though the element itself does not. If you use an event like mouseup, both the p element and the document will see the event.

Your workaround is the best you can do for now. It appears to only affect Firefox (I believe it's actually a bug in Firefox, not jQuery per se).

See also this question asked yesterday.

Crescent Fresh
A: 

This is an unfortunate consequence of how live is implemented. It's actually uses event bubbling so you're not binding to the anchor element's click event, you're binding to the document's click event.

Ken Browning
Nope, there's a flaw in the way Firefox bubbles right-click. See http://unixpapa.com/js/mouse.html
Crescent Fresh
@crescentfresh: I'm not sure how much faith to place in an article that says "Macintosh versions of Safari, of course, are immune to these problems, because Macintoshes only have one mouse button" - the last time I used a Mac with a single--button mouse was sometime before TBL invented the Web ;-)
NickFitz
@NickFitz: touché.
Crescent Fresh
+2  A: 

I've found a solution - "fix" the the live() code itself.

In the unminified source of jQuery 1.3.2 around line 2989 there is a function called liveHandler(). Modify the code to add one line:

2989:    function liveHandler(event) {
2990:        if (event.type == 'click' && event.button != 0) return true;

This will stop the click events from firing on anything but the left-mouse button. If you particularly wanted, you could quite easy modify the code to allow for "rightclick" events too, but this works for me so it's staying at that.

nickf
A: 

You can actually rewrite it as:

function reattachEvents(){
    $(element).unbind('click').click(function(){
        //do something
    });
}

and call it when you add a new dom element, it should have the expected result (no firing on the right click event).

SeanJA
yeah, but that defeats the purpose of `live()` doesn't it?
nickf
true, but live(click) acts differently than normal click() which can be fixed if you detect which button was pressed, but then you need to know exactly which browser was used (IE acts differently in earlier versions than newer versions and all other browsers act the 'correct' way). This is a much more elegant solution for the time being.
SeanJA