Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save codinronan/979394e1652570da24d30e592ae4ce53 to your computer and use it in GitHub Desktop.
Save codinronan/979394e1652570da24d30e592ae4ce53 to your computer and use it in GitHub Desktop.
// These are cross-browser implementations of addEvent and removeEvent that account for differences
// in how addEventListener and attachEvent are supported across W3C standards browsers, and IE < IE9 standards mode.
// (IE9 compatibility mode uses attachEvent, standards mode uses addEventListener).
// The approach here attempts to solve several problems:
// 1. IE's attachEvent obliterates 'this' and the 'this' in the callback becomes 'window'
// 2. The fix, which is to call the function as a method on the object, requires that
// each instance of the function be tagged individually (the guid) so that multiple listeners can be applied
// to the same object
// 3. Avoid the memory leaks associated with adding a property to the object that it did not already have
// The simpler approach is to simply use the approach here:
// http://stackoverflow.com/questions/6927637/addeventlistener-in-internet-explorer
// However it has the drawback of not resolving the meaning of 'this' that IE breaks.
// Use these more complex versions only if testing shows they are needed.
function addEvent(obj, type, fn) {
if(obj.addEventListener) {
obj.addEventListener(type, fn, false);
}
else if(obj.attachEvent) {
if (!fn.$$guid) {
fn.$$guid = addEvent.guid++;
}
// The purpose of this craziness is to retain the meaning of 'this'
// in the called function. IE obliterates 'this' and replaces it with 'window'
const eProp = type + fn.$$guid;
obj['e'+eProp] = fn;
obj[eProp] = function() { obj['e'+eProp](window.event); };
obj.attachEvent('on'+type, obj[eProp]);
}
else {
obj['on'+type] = fn;
}
}
addEvent.guid = 1;
function removeEvent(obj, type, fn) {
if(obj.removeEventListener) {
obj.removeEventListener(type, fn, false);
}
else if(obj.detachEvent) {
var eProp = type + fn.$$guid;
obj.detachEvent('on'+type, obj[eProp]);
delete obj['e'+eProp];
delete obj[eProp];
}
else {
delete obj['on'+type];
}
}
@codinronan
Copy link
Author

Or slightly simpler (but potentially buggy) implementations:

function addEvent(elem, evnt, func) {
  /* istanbul ignore else: non-chrome events can't be tested via Karma */
  if(elem.addEventListener)  // W3C DOM
    elem.addEventListener(evnt,func,false);
  else if(elem.attachEvent) { // IE DOM
    elem.attachEvent('on'+evnt, func);
  }
  else {
    elem['on'+evnt] = func;
  }
}

function removeEvent(elem, evnt, func) {
  /* istanbul ignore else: non-chrome events can't be tested via Karma */
  if(elem.removeEventListener)  // W3C DOM
    elem.removeEventListener(evnt,func,false);
  else if(elem.detachEvent) { // IE DOM
    elem.detachEvent('on'+evnt, func);
  }
  else { // No much to do
    delete elem['on'+evnt];
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment