In this code, Firefox sees 'this' as the element that was clicked and passes the href attribute through the right way.
IE seems to think that 'this' as [object window] instead. How would I get this to work the same way in both browsers?
Note: jQuery would be lovely, but is not an option for this project
var printElem = getElementsByClassName('print', 'a');
for(i in printElem){
ObserveEvent(printElem[i], 'click', function(e){
window.open(this.href, '', 'location=0,menubar=1,resizable=1,scrollbars=1,width='+810+',height='+700);
cancelEvent(e);
});
}
I'm adding my two cents here as I think you can use it.
There was a contest 4 years ago to see who could write the best addEvent
implementation. One of the main problems it tried to address was retaining this
inside the event handler.
Here is one contest entry written by the creator of jQuery:
function addEvent( obj, type, fn ) {
if ( obj.attachEvent ) {
obj['e'+type+fn] = fn;
obj[type+fn] = function(){obj['e'+type+fn]( window.event );}
obj.attachEvent( 'on'+type, obj[type+fn] );
} else
obj.addEventListener( type, fn, false );
}
(And of course to be symmetrical):
function removeEvent( obj, type, fn ) {
if ( obj.detachEvent ) {
obj.detachEvent( 'on'+type, obj[type+fn] );
obj[type+fn] = null;
} else
obj.removeEventListener( type, fn, false );
}
Rename it to "ObserveEvent" if you wish.
There you have it, an 8 line implementation you can drop into your codebase - No libraries, no frameworks. And your this
reference inside your handler works just fine.
You can use the event target, like this:
ObserveEvent(printElem[i], 'click', function(e){
var target = e.target || e.srcElement;
window.open(target.href, '', 'location=0,menubar=1,resizable=1,scrollbars=1,width='+810+',height='+700);
cancelEvent(e);
});
The problem almost certainly stems from the ObserveEvent
function using IE's attachEvent
method, which (unlike addEventListener
in other browsers) doesn't set this
to the object being observed in the event handler.
Another option: Create a closure to scope the element for the handler for each element:
var printElem = getElementsByClassName('print', 'a');
for(var i in printElem){
(function(elem) { // elem === printElem[i] at time of execution later
ObserveEvent(elem, 'click', function(e){
window.open(elem.href, '', 'location=0,menubar=1,resizable=1,scrollbars=1,width='+810+',height='+700);
cancelEvent(e);
});
})(printElem[i]); // immediately call the temp function with our element
}