确定元素是否由 JS 添加与原始 HTML 文档 *或* 检测脚本何时通过 InnerHtml 更新节点

Rob*_*ist 5 html javascript firefox javascript-framework mutation-observers

简而言之,我需要知道页面上的某些元素是否在页面上,因为某些脚本通过父元素上的 InnerHtml 属性插入了它们,或者它们是否是下载的原始 HTML 文档的一部分。在这个(荒谬的)应用程序中,这两种可能性意味着非常不同的事情。

实际用例:

第 3 方脚本通过设置元素的 InnerHtml 属性来更新页面上的随机节点元素。我可以完全控制浏览器(WPF / GeckoFx / XulRunner),并且能够随意注入和修改(新)JS,但没有洞察力或能力来修改严重混淆的第三方脚本。

获取我需要的数据的唯一方法是确定页面加载后,屏幕上的某些元素(如果存在)是否由第三方脚本(innerHtml)加载,或者它们是否是之前原始 Html 文档的一部分第三方脚本运行。


简单地将页面的原始 html 内容源与其最终状态进行比较是很困难的,因为原始页面上有很多内联脚本。

有人有什么想法吗?

Rob*_*ist 2

不幸的是,使用突变观察者的建议并不适用于这种情况。突变观察者不知道 dom 节点被添加到页面的原因他们只报告一个。这意味着无法确定是否添加了 DOM 片段,因为页面仍在加载,或者因为脚本已触发并动态添加内容。

然而

本文解释了如何覆盖 dom 中每个元素的 InnerHTML getter/setter 属性http://msdn.microsoft.com/en-us/library/dd229916 (v=vs.85).aspx总是由 javascript 调用,对我来说知道 dom 的某个部分是否使用此函数调用加载就变得微不足道了。

虽然这几乎肯定是矫枉过正,对于大多数应用程序来说不是一个好主意,但对于像这样的奇怪情况以及 js 框架的构建,它可能很有意义。

如果该文章在某个时候离线,我的初始代码将类似于以下内容:

var elem = isInIE() ? HTMLElement : Element;    // IE and FF have different inheritance models, behind the scenes.
var proxiedInnerHTML = Object.getOwnPropertyDescriptor(elem.prototype, "innerHTML");

Object.defineProperty(elem.prototype, "innerHTML", {
    set: function ( htmlContent )
    {
        // custom code goes here

        proxiedInnerHTML.set.call(this, htmlContent);
    }); 
Run Code Online (Sandbox Code Playgroud)

在较旧的浏览器中应该警告一下,或者如果您使用了错误的元素(HTMLElement 与 Element),则调用将在innerHTML 调用上失败,而不是在属性定义上失败。

在浏览器中处理原型:

我在 FF 和 IE 中测试了这个块,但在 Chrome 中没有测试。更重要的是,我发现帖子指出 w3c 规范中不能保证指定浏览器如何处理其元素类型的继承,因此不能保证 HtmlDivElement 将来或过去会调用 InnerHTML 的 HtmlElement 或 Element 基本方法任何给定浏览器的版本。

也就是说,使用所有保留的 html 关键字创建一个网页并测试该技术是否适用于它们是非常简单的。对于 IE 和 FF,截至 2015 年 1 月,该技术全面有效。

旧浏览器支持:

虽然我没有使用它,但在较旧的浏览器中,您可以使用

document.__defineGetter__("test", /* getter function */ );
document.__defineSetter__("test", /* setter function */ );
document.__lookupGetter__("test");
document.__lookupSetter__("test");
Run Code Online (Sandbox Code Playgroud)

感谢 RobG 让我走上这条路