Skip to content Skip to sidebar Skip to footer

How To Overwrite Addeventlistener In Firefox 3.x?

im making a greasemonkey userscript which puts all kinds of shims and polyfills in the page for old browsers. the problem is that none of them seems to include anything to make the

Solution 1:

That's quite bad what they did there... Luckily they fixed it since then ;-)

var el1 = document.createElement('div');
var el2 = document.createElement('div');

el1.addEventListener === el2.addEventListener; 

is false in FF 3.2...

This means that they were setting for every element its own version of the function (probably a bound version).

Given this, your only way is to catch all the elements and append to them your own version one by one.

One way is to overwrite the document.createElement method, but this will work only on elements that are created by scripts. To catch the ones that in the markup, you could use a TreeWalker.

functionoverwrite(target) {
  if (target._addEvent_overwritten) return; // do it only once// calling the Element.prototype.addEventListener throws an Error in FF3.xvar prevAddEventListener = target.addEventListener;
  target.addEventListener = function(type, handler, options) {
    prevAddEventListener.call(this, type, handler, !!options);
  };
  target._addEvent_overwritten = true;
}
// catch in document.createElement  // FF 3.x doesn't set the Document.prototype.createElementvar prevCreateElem = HTMLDocument.prototype.createElement;
HTMLDocument.prototype.createElement = function(type) {
  var elem = prevCreateElem.call(this, type);
  overwrite(elem);
  return elem;
};

// not only Elements do have this method...overwrite(window);
overwrite(document);

// catch after Document has been generateddocument.addEventListener('DOMContentLoaded', function() {
  // catch all Elementsvar walker = document.createTreeWalker(
    document.documentElement, NodeFilter.SHOW_ELEMENT, null, false
  );
  while (walker.nextNode())
    overwrite(walker.currentNode);
});

// Testsvar elem = document.createElement('div');
elem.addEventListener('click', function(evt) {
  this.textContent = 'clicked'
});
elem.textContent = 'click me (dynamic)';
document.body.appendChild(elem);

window.addEventListener('load', function() {
  document.getElementById('in-doc').addEventListener('click', function() {
    this.textContent = 'clicked';
  });
});
<divid="in-doc">click me (in markup)</div>

However this won't catch the ones in markup that receive event listeners before the DOMContentLoaded event fired.

For these, you will probably have to also overwrite all of document.getElementById, document.querySelector, Element_instance.querySelector, NodeList getters, HTMLCollection getters etc. That's not a trivial task, and I unfortunately miss the incentives to do it all for this answer, since I only use this FF version from mozregression when searching about a bug, but at least you get the idea.

Solution 2:

addEventListener is inherited from the EventTarget prototype, not Element.

var placeToReplace;
if (window.EventTarget && EventTarget.prototype.addEventListener) {
  placeToReplace = EventTarget;
} else {
  placeToReplace = Element;
}

placeToReplace.prototype.oldaddEventListener = placeToReplace.prototype.addEventListener;
placeToReplace.prototype.addEventListener = function(event, handler, placeholder) {
  console.log("calling substitute");
  if (arguments.length < 3) {
    this.oldaddEventListener(event, handler, false);
  } else {
    this.oldaddEventListener(event, handler, placeholder);
  }
}
document.querySelector("div").addEventListener("click", function() {
  console.log("foo");
});
<div>Click me</div>

Post a Comment for "How To Overwrite Addeventlistener In Firefox 3.x?"