注意在greasemonkey 脚本中创建元素?
Posted
技术标签:
【中文标题】注意在greasemonkey 脚本中创建元素?【英文标题】:Watch for element creation in greasemonkey script? 【发布时间】:2013-07-12 00:47:10 【问题描述】:当文档加载时创建了“nav”类的元素时,我需要得到通知。谷歌搜索我找到了 MutationObservers 并认为它们会很完美,但我似乎无法让它工作。
// ==UserScript==
// @name ii-shortcuts
// @namespace https://github.com/RedHatter
// @include *
// @version 1
// @run-at document-start
// ==/UserScript==
var observer = new MutationObserver(function(mutations)
mutations.forEach(function(mutation)
if (mutation.target.getAttribute('class') == 'nav')
GM_log('nav creation');
);
);
observer.observe(document, subtree: true, attributes: true, attributeFilter: ['class']);
我也试过了。
// ==UserScript==
// @name ii-shortcuts
// @namespace https://github.com/RedHatter
// @include *
// @version 1
// @run-at document-start
// ==/UserScript==
var observer = new MutationObserver(function(mutations)
mutations.forEach(function(mutation)
if (mutation.addedNodes[0].getAttribute('class') == 'nav')
GM_log('nav creation');
);
);
observer.observe(document, subtree: true, childList: true);
但在下一种情况下是“导航创建”登录页面加载。我错过了什么?
【问题讨论】:
@CrazyTrain Not accouding to the specs "DOM 突变事件不能因为 UA 解析文档引起的变化而触发……但是,根据 DOM 规范的要求,突变观察者会触发。 " 你可以使用arrive.js,它提供了很好的简单api来监听元素的创建(内部使用MutationObserver) 嗯...看起来很不错。谢谢@UzairFarooq 【参考方案1】:几个问题(从大到小):
当文档第一次加载时,静态加载;这些事件是childList
事件,而不是attributes
事件。
例如,
$("body").append ('<p id="foo" class="bar">Hiya!</p><p>blah</p>');
生成 一个 childList
事件,而随后的
$("#foo").attr ("class", "bar2");
生成attributes
事件。
mutation.addedNodes[0]
包含类 nav
的元素的几率几乎为零。这几乎总是一个文本节点。
您需要检查整个数组,加上target
。
不要使用getAttribute('class') == 'nav'
来检查课程。这将为没有getAttribute
函数的节点抛出异常,并且它会丢失具有多个类的元素。例如:<p class="foo nav bar">...
在适当的节点类型上使用classList.contains()
。
如果您使用任何GM_
函数(如GM_log()
),请使用@grant
指令。无论如何都要使用授权,以确保沙盒保持打开状态。
避免使用// @include *
。尤其是对于计时器和观察者,这可能会使您的浏览器和您的机器陷入瘫痪。
此信息适用于 Firefox。 Chrome 在实现 Mutation 观察者的方式上存在很大差异。此类代码在页面加载前无法在 Chrome 中运行。
把它们放在一起,脚本变成:
// ==UserScript==
// @name _ii-shortcuts
// @namespace https://github.com/RedHatter
// @include http://YOUR_SERVER.COM/YOUR_PATH/*
// @run-at document-start
// @version 1
// @grant GM_log
// ==/UserScript==
/*- The @grant directive is needed to work around a design change
introduced in GM 1.0. It restores the sandbox.
*/
var MutationObserver = window.MutationObserver;
var myObserver = new MutationObserver (mutationHandler);
var obsConfig =
childList: true, attributes: true,
subtree: true, attributeFilter: ['class']
;
myObserver.observe (document, obsConfig);
function mutationHandler (mutationRecords)
mutationRecords.forEach ( function (mutation)
if ( mutation.type == "childList"
&& typeof mutation.addedNodes == "object"
&& mutation.addedNodes.length
)
for (var J = 0, L = mutation.addedNodes.length; J < L; ++J)
checkForCSS_Class (mutation.addedNodes[J], "nav");
else if (mutation.type == "attributes")
checkForCSS_Class (mutation.target, "nav");
);
function checkForCSS_Class (node, className)
//-- Only process element nodes
if (node.nodeType === 1)
if (node.classList.contains (className) )
console.log (
'New node with class "' + className + '" = ', node
);
// YOUR CODE HERE
//GM_log ('nav creation');
【讨论】:
感谢您的提示!虽然我打算在脚本完成后添加一个@grant
(否则你会得到那个烦人的弹出),我只放了@include *
,因为我不想显示我在哪个网站上使用脚本。
【参考方案2】:
调用 MutationObservers 的目的不仅仅是添加节点,包括更改属性和删除节点。
因此请注意 mutation.addedNodes
返回 null - 在这种情况下,此代码将失败。试试:
if (mutation.addedNodes && mutation.addedNodes[0].getAttribute('class') === 'nav')
...
突变对象还有一个“类型”属性,您可以使用它来获取更多信息;你读过MDN 上的API 文档吗?那里有一些很好的例子。
【讨论】:
我尝试了代码,并没有改变任何东西。问题不是脚本失败,而是具有类 nav 的元素永远不会传递给 MutationObserver。是的,我已经阅读了文档。 您是否有一个测试页面,其中包含您正在使用此代码观看的 html?以上是关于注意在greasemonkey 脚本中创建元素?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Google Chrome 的 Greasemonkey 脚本中使用 jQuery?
将 Greasemonkey/Tampermonkey 用户脚本应用到 iframe