Don't Tab Me Bro… (or jQuery's preventDefault vs. browser tabs)
Those of you in the audience who haven’t dozed off may have already
picked up on the problem:
document.location = a_href; = inability to open said link in a new
tab/window – unless you do a context-menu dance.
We need to
preventDefault()because if we don’t, the browser heads off to the link, possibly aborting our attempt to track the click.
We need to pass the callback to
mpq()because of #1, so that the browser eventually goes to the link.
The browser is sent to the original
hrefprogrammatically by the callback – after Mixpanel does it’s thing. This action is only indirectly in response to the original click, the native event that triggered this whole process has been discarded.
If the user originally ⌘-clicked (ctrl-click for the non-Mac people) to open the link in the new tab, they lose. The link opens in the current window/tab. The user gets annoyed.
Ironically I’ve seen similar behaviour on other sites, and just thought the developers were incompetent, or perhaps slightly malicious. Now I’ve become what I hate…
Try to open the following link in a new tab:
An annoying link
What happens is, as described earlier, the browser’s default response
to the link is suppressed via
preventDefault(). Then, after our
hypothetical asynchronous logging method has completed, the callback
is, er, called back, setting the browser’s location:
Well, that just won’t do, so we need to come up with a workaround. How
about just retriggering the event? The first time I tried this, I just
writing I tried
dispatchEvent() which actually retriggers the jQuery
But since we called
preventDefault() the first time round, the
retriggered event also skips the browser’s default action. But,
we’re on the right track, and when you try something, and it doesn’t
work, then the next step is always do the same thing with a copy of
Trigger a copy
Cool! It works. Wrapping it up in a proper little function is left as an exercise to the reader. Another method to try would be triggering the callback via plain old jQuery:
Plain old jQuery trigger
It doesn’t work, and from reading the documentation:
.trigger()simulates an event activation, complete with a synthesized event object, it does not perfectly replicate a naturally-occurring event.
To trigger handlers bound via jQuery without also triggering the native event, use
(Emphasis mine) I’m not really sure if should work or not. The first paragraph would indicate maybe, the second implies yes. I’m probably doing something wrong.