Bug Tracker

Opened 11 years ago

Closed 11 years ago

Last modified 10 years ago

#12652 closed bug (notabug)

Links with onclick handlers that return true break when invoked through jQuery

Reported by: Stijn de Witt Owned by:
Priority: undecided Milestone: None
Component: unfiled Version: 1.8.2
Keywords: Cc:
Blocked by: Blocking:

Description

When you click a link from code using jQuery's click() method, and that link has an onclick handler that returns true, the default action of the link (navigate to the href) is not executed. This seems to me to be a bug in jQuery's event handling code.

I created a live example demonstrating the issue in JsFiddle: http://jsfiddle.net/W5xzm/9/

Change History (17)

comment:1 Changed 11 years ago by dmethvin

Resolution: notabug
Status: newclosed

Not all browsers have a DOM .click() method that navigates to the link, so for consistent cross-browser behavior jQuery does not attempt to navigate when you trigger links manually. It's easy to get the desired behavior though. See the top comment at the docs page: http://api.jquery.com/trigger/

comment:2 Changed 11 years ago by anonymous

The top comment advises binding an extra handler to navigate to the href, like so:

$('#someLink').bind('click', function() {

window.location.href = this.href; return false;

});

Isn't that actually bad practice? Seems to me any handlers bound to the onclick of #someLink after this event handler was bound would never get fired because of the return false...

In any way, this behavior really surprised me.

You say that some browsers do not navigate to the href when you call click() on them... Do you have examples on that? I ask because that's exactly what I am doing in my code right now to work around jQuery's behavior. I am getting the native DOM element and calling click() on that directly. I might need to change that if any of the browsers we target don't actually support that...

comment:3 Changed 11 years ago by dmethvin

You say that some browsers do not navigate to the href when you call click() on them

I didn't say that at all. I said "Not all browsers have a DOM .click() method". Try this on Safari for example: http://jsfiddle.net/vSZuy/

comment:4 Changed 11 years ago by dmethvin

#12847 is a duplicate of this ticket.

comment:5 Changed 11 years ago by Nao

I'm sorry, but... Why do you completely drop the event's default action (instead of trying to trigger it) if the element is seen to be an anchor and the event a click?

I understand the fact that it would fail on non-HTML5 compatible browsers such as Safari and earlier IEs, in fact I saw this by myself, but why drop it? Why not add a simple one-liner as a fallback? Something like 'if (elem.href) location = elem.href'...

It's *way* better than forcing jQuery users to actually implement that one...

This report should be re-opened. (Couldn't find any more recent report with the same bug in it.)

comment:6 Changed 11 years ago by dmethvin

This behavior has been consistent for 5 years. Changing it to execute the default action on just some browsers would break code expecting the old behavior.

comment:7 Changed 11 years ago by Nao

Then perhaps it shouldn't be closed as "notabug", but as a "wontfix"...

And, more importantly, this behavior should be documented. I can't count the number of support questions I saw on Stackoverflow etc. regarding this issue.

BTW, can't read comments for the .trigger page (mentioned in the first comment here), because they seem to be disabled in the new jQuery API website... :-/

comment:8 Changed 11 years ago by Nao

I forgot to point out a couple more arguments.

$('element')[0].click() works in all HTML5-compliant browsers.

$('element').click() should work on all browsers -- I think it was jQuery's mission to transparently provide the same experience across all browsers. It shouldn't *drop* a feature for newer browsers just for consistency with older browsers whose bugs jQuery doesn't want to fix.. (?)

Since jQuery 1.9 makes it pretty obvious (with their -currently broken- upgrade guide) that developers will HAVE to refactor some of their code to account for many deprecated or dropped features, perhaps this 'feature' should be moved to the migration plugin somehow, and fixed in the final version.

We're in 2013. What else can I say. Happy new year, happy new HTML ;)

comment:9 Changed 11 years ago by dmethvin

$('element').click() should work on all browsers

It does not. Did you try the example http://jsfiddle.net/vSZuy/ on Safari 5.1, which is one of our supported browsers?

comment:10 Changed 11 years ago by Nao

Of course it does not. When I said "should work", I meant that jQuery has always aimed to make JavaScript cross-browser without hassle. Heck, that's the reason most of us started using it... So there's no reason they would consciously break this particular setup of $('a').click(...), while even something like $('div').click() is accepted.

So, it's literally "should", not "will probably".

comment:11 Changed 11 years ago by dmethvin

Sorry, what I meant was to make this statement and I wasn't clear:

The native DOM click method, $('element')[0].click(), does not work on all browsers. In particular, Safari does not support the DOM .click() method on link elements, making it impossible for jQuery to trigger a native click behavior if a developer says $('element').click() and the default is not prevented. This is why that special case existed in the first place.

This behavior has been the case throughout jQuery's existence, so at this point there is no doubt a lot of code that has come to expect it. Is there a course of action you can recommend that won't break existing code?

comment:12 Changed 11 years ago by Nao

Safari does not support the DOM .click() method on link elements

I never said it did. I said all HTML5-compliant browsers did. Please re-read comment #5 where I think I covered it all. Safari 5 (and perhaps later) obviously do not support HTML5 entirely.

But, and again as I said before: if jQuery goes all the way to skipping the entire code block if (1) the element is an <a> tag AND (2) the event type is click (it seems to be pretty specific to me! And why not drop div clicks since they're not HTML4-compliant either?), then I don't see why the jQuery team can't simply add, AFTER that code block, a simple:

else if (elem.href)

location = elem.href;

The additional 'if' is just there in case href isn't defined, but since it's an anchor, I'm guessing it's always set. Anyway... Could also do 'else if (elem.href && elem.href != "#")' to avoid jumping to pseudo-links that aren't supposed to be followed. But to me it's a waste of extra bytes (and I'm obsessive about saving bytes.)

I can not find any 'real life' situation where a developer would actually expect jQuery to drop their call to $('a').click() when they do it. They would in fact expect it to work, wouldn't they...?

I'm just trying to be logical. If you also have a logical explanation for why jQuery shouldn't do this, then I'm all ears. Thanks for listening. Or reading, or whatever.

comment:13 Changed 11 years ago by dmethvin

why not drop div clicks since they're not HTML4-compliant either

That's not a problem case. There is no DOM .click() method on a div.

I don't see why the jQuery team can't simply add, AFTER that code block, a simple: else if (elem.href) location = elem.href;

Certainly it *seems* like it should be that easy, I'd though about that myself. However, I've also learned that developers tend to get used to the current behavior and changing things can cause lots of problems.

Since 1.9/2.0 is on the verge of shipping this is not going into those releases. We have the luxury of leaving this ticket here and we can let others register their pro/con.

comment:14 in reply to:  12 Changed 11 years ago by scottgonzalez

Replying to Nao:

else if (elem.href)

location = elem.href;

What if the link specifies a target? Also, how do various devices handle various protocols (mailto, tel, etc.)? I have a feeling the logic for the default action of a click is more complicated than you think.

comment:15 Changed 11 years ago by Nao

I don't really see a valid use case where someone would have such a specific link type, and still have a script specifically do a .click() on them.

Anyway. I see there's no real interest from the jQuery team in fixing this. Fine. I fixed it on my side when I reported, I just thought it'd make more sense to have it fixed in jQuery.

Good luck for the upcoming versions.

comment:16 Changed 10 years ago by gibson042

https://github.com/jquery/jquery/pull/1223 doesn't fully solve your problem, but it does expose enough to do so with a small plugin.

comment:17 Changed 10 years ago by Richard Gibson

Ref #12652: Allow overriding native .click() suppression (cherry picked from commit 14b09ef98eb11aae04c028a3b3d7af116c7d2c20)

Changeset: a120bbbfae81daccf801fcf8deb0bc77d865e27f

Note: See TracTickets for help on using tickets.