如何在Firefox 3.x中覆盖addEventListener? [英] How to overwrite addEventListener in Firefox 3.x?

查看:63
本文介绍了如何在Firefox 3.x中覆盖addEventListener?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

im制作滑脂猴子用户脚本,该脚本包含各种垫片和旧浏览器页面中的polyfills.问题在于,它们似乎都不包含任何能够使"addEventListener"的第三个参数是可选的,并且自网页以来通常忽略它,它给出一个参数不足".到处都是错误.

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 third parameter of 'addEventListener' optional, and since webpages usually omit it, it gives a "Not enough arguments." error everywhere.

我试图用这种方式覆盖它:

i tried to overwrite it this way:

Element.prototype.oldaddEventListener = Element.prototype.addEventListener;
Element.prototype.addEventListener = function(event,handler, placeholder) {
    if (!arguments[2]) {
        this.oldaddEventListener(event,handler, false);
        }
        else{
        this.oldaddEventListener(event,handler, placeholder);
        }

}

现在检查它是否替换了元素上的功能:

and now checking if it replaced the function on elements:

alert(document.querySelector("div").addEventListener)

警告原件:

function addEventListener() {
    [native code]
}

检查Element.prototype.addEventListener:

checking the Element.prototype.addEventListener:

alert(Element.prototype.addEventListener)

显示覆盖的版本.所以我尝试覆盖这些:

shows the overwritten version. so then i tried overwriting these:

HTMLElement.prototype.addEventListener,
EventTarget.prototype.addEventListener,
HTMLDivElement.prototype.addEventListener,
Object.prototype.addEventListener,
Node.prototype.addEventListener,

没有一个有效.他们每个人都显示出在以下情况下会被覆盖警告,但没有影响元素的功能.我在萤火虫DOM检查器中搜索了它的任何实例仍在展示原始图片,并覆盖其中'applicationCache','content','document','frames','parent','self'和顶部".显然这也不起作用.

NONE of this worked. every of them shows to be overwritten when alerted, but none of it affects the function of elements. i searched in the firebug DOM inspector for any instances of it that were still showing the original, and overwritten it in 'applicationCache', 'content', 'document', 'frames', 'parent', 'self' and 'top'. obviously this didnt work either.

用户脚本在文档开始"处运行,我检查了它是否在运行在任何其他脚本之前,甚至在该元素存在之前.页面加载后手动运行脚本也无济于事.我发现覆盖元素上的功能的唯一方法是直接选择该元素并覆盖每个元素一一元素.

the userscript runs at 'document-start', and i checked that it runs before any other script and before the element even exists. running the script manually after the page loaded also does nothing. the only way i found to overwrite the function on elements is to directly select that element and overwrite it on each and every element one by one.

所以我的问题是:如何覆盖在Firefox 3.x中是全局的每个元素吗?

so my question is: how to overwrite the "addEventListener" function on every element globally, in Firefox 3.x?

推荐答案

那是很糟糕的事情……幸运的是,从那时起他们将其修复了;-)

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; 

在FF 3.2中

false ...

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.

一种方法是覆盖 document.createElement 方法,但这仅适用于脚本创建的元素.要捕获标记中的内容,可以使用TreeWalker.

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.

function overwrite(target) {
  if (target._addEvent_overwritten) return; // do it only once
  // calling the Element.prototype.addEventListener throws an Error in FF3.x
  var 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.createElement
var 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 generated
document.addEventListener('DOMContentLoaded', function() {
  // catch all Elements
  var walker = document.createTreeWalker(
    document.documentElement, NodeFilter.SHOW_ELEMENT, null, false
  );
  while (walker.nextNode())
    overwrite(walker.currentNode);
});

// Tests

var 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';
  });
});

<div id="in-doc">click me (in markup)</div>

但是,在DOMContentLoaded事件触发之前,这不会捕获标记中接收事件侦听器的事件.

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

对于这些,您可能还必须覆盖所有 document.getElementById document.querySelector Element_instance.querySelector NodeList 吸气剂, HTMLCollection 吸气剂等.
那不是一件容易的事,而且我很遗憾错过了为此做所有事情的动力,因为在搜索错误时,我仅使用mozregression的FF版本,但至少您能理解.

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.

这篇关于如何在Firefox 3.x中覆盖addEventListener?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆