With the help of How to trigger an event after using event.preventDefault() and How to clone or re-dispatch DOM events? I came up with the following solution:
<script>
var anchor = document.getElementById('anchor');
anchor.addEventListener('click', function(e){
if(e.eventHandled) return;
e.preventDefault();
window.alert('Javascripts');
var clonedEvent = new e.constructor(e.type, e);
clonedEvent.initEvent(e.type, true, false);
clonedEvent.eventHandled = true;
anchor.dispatchEvent(clonedEvent);
});
</script>
<a href="http://www.google.com/" id="anchor">Google</a>
Now when command+clicking the link you first receive the alert, and afterwards are sent to a new tab.
Jsfiddle: http://jsfiddle.net/8NRJY/1/ (Note that jsfiddle wont change urls if you do a normal click, but this works fine outside of jsfiddle)
Now all there's left is making this cross browser compatible, and inserting the google tracking of course (the dispatchEvent would be inside the callback).
Edit: Here is the cross-browser (IE8+ at least) compatible version.
The first functions should be part of your library if you're working in native javascript.
<script>
var addEventListener = function(elem, eventName, handler, useCapture) {
if (elem!=null) {
if (elem.addEventListener) {
if (useCapture===true||useCapture===false) {
elem.addEventListener(eventName, handler, useCapture);
}
else {
elem.addEventListener(eventName, handler);
}
} else {
elem.attachEvent('on' + eventName, function(evt) {
evt = evt || window.event;
evt.target = evt.target || evt.srcElement;
handler(evt);
});
}
}
};
var onReady = function (fn) {
if (document.addEventListener) {
document.addEventListener('DOMContentLoaded', fn);
} else {
document.attachEvent('onreadystatechange', function() {
if (document.readyState === 'interactive' || document.readyState === 'complete'){
fn();
}
});
}
};
var fireEvent = function(el, event){
if(document.createEvent){
var clonedEvent = new event.constructor(event.type, event);
clonedEvent.initEvent(event.type, true, false);
el.dispatchEvent(clonedEvent);
}else if(document.createEventObject){
var clonedEvent = document.createEventObject();
el.fireEvent('on'+event.type, clonedEvent);
}
};
onReady(function(){
var anchor = document.getElementById('anchor');
addEventListener(anchor, 'click', function(e){
if(!anchor.eventDispatched){
e.preventDefault ? e.preventDefault() : e.returnValue = false;
anchor.eventDispatched = true;
fireEvent(anchor, e);
}else{
anchor.eventDispatched = false;
e.returnValue = true;
}
});
});
</script>
<a id="anchor" href="http://www.google.com">Test</a>
Edit 2: Fixing this to work with Google Analytics is proving to be a much tougher task than I thought.
In modern browsers, it works great right off the bat. In IE8 there's only a single event at a time (stored in window.event
), which means that Google's callback overrides that, which means I can't re-fire the original event. I'm trying various methods of cloning the event to make it work, but so far no success.
I hate you IE8.
Edit 3: I've given up on trying to make this work in IE8.
Edit 4: As it turns out, Chrome blocks the new window as a popup, because the event is triggered after a callback (even though its the original user click event).