我试图制作一个Greasemonkey脚本来在Facebook页面中添加一个按钮。
但是我需要等待创建一个元素来添加按钮
我尝试使用MutationObserver
(As suggested here)来执行此操作,但是出现错误。
function init() {
console.log('Launched : ' + launched);
if (!launched) {
launched = true;
main();
}
}
console.log('barfoo');
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
if (!mutation.addedNodes) return;
console.log(mutation.addedNodes.type());
for (var i = 0; i < mutation.addedNodes.length; i++) {
if (mutation.addedNodes[i].matches('div[class="pam _5shk uiBoxWhite bottomborder"]')) {
console.log('init');
init();
}
}
})
});
console.log('bar');
try {
observer.observe(document.body, {
childlist: true,
subtree: true,
attributes: false,
characterData: false,
});
} catch (error) {
console.log(error);
}
console.log('foobar');
但是我得到了以下日志:
barfoo
bar
DOMException [TypeError: "The expression cannot be converted to return the specified type."
code: 0
nsresult: 0x805b0034
location: file:///home/vmonteco/.mozilla/firefox/f3xgmo8e.default/gm_scripts/Facebook_cleaner/Facebook_cleaner.user.js:230] Facebook_cleaner.user.js:239:3
foobar
此错误的原因是什么? 我怎么能解决这个问题?
如果在执行我的脚本之前创建了元素,MutationObserver
是否仍会被触发? (IE,如果在创建MutationObserver时元素已经存在)。
NB:我尝试使用$(document).ready()
,但在创建要添加按钮的元素之前触发了它。
NB-bis :我没有发布整个剧本。
答案 0 :(得分:6)
遗憾的是,该错误信息完全含糊不清,但您有一个错字:
observer.observe(document.body, {
childlist: true,
subtree: true,
attributes: false,
characterData: false,
});
应该是
observer.observe(document.body, {
childList: true,
subtree: true,
attributes: false,
characterData: false,
});
e.g。 childlist
=&gt; childList
在这种情况下,在Chrome中运行相同的代码会提供比#34更有用的消息;无法转换为返回指定的类型&#34;。它说
选项对象必须至少设置一个属性&#39;,&#39; characterData&#39;或&#39; childList&#39;为真。
答案 1 :(得分:1)
实际上,MutationObserver
是不这样做的最好方法(正如你正在努力学习的那样。它很快变得复杂和脆弱。它可能真的陷入网页,并且它在各个平台之间并不一致。)
此外,如果在脚本触发之前元素存在,MutationObserver将无法捕获它。
使用Run Greasemonkey script on the same page, multiple times?中显示的方法。
这样,您的整个脚本就变为:
// ==UserScript==
// @name _Wait for specific divs
// @include http://YOUR_SERVER.COM/YOUR_PATH/*
// @require http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js
// @require https://gist.github.com/raw/2625891/waitForKeyElements.js
// @grant GM_addStyle
// ==/UserScript==
/*- The @grant directive is needed to work around a design change
introduced in GM 1.0. It restores the sandbox.
*/
waitForKeyElements (
'div.pam _5shk.uiBoxWhite.bottomborder', processDiv
);
function processDiv (jNode) {
// YOUR CODE HERE.
// For example:
jNode.css ("background", "pink");
}
看看这有多容易! :)
使用waitForKeyElements()
您可以根据需要使用任何复杂的jQuery选择器。
如果你真的坚持MutationObserver
,请使用一个可以消除很多痛苦的库。
This answer shows how to use MutationObserver in a Greasemonkey/Tampermonkey script.
答案 2 :(得分:-1)
我认为 MutationObserver 并非实现此目的的方法,但实际上是这样。细微之处在于,如果您要处理从一开始就立即加载的页面节点,那么为了不丢失任何内容,您必须使用// @run-at document-start
条件运行Monkey脚本,然后附加观察者,例如到document.documentElement
以捕获绝对的所有内容(或者,如果您确定以后页面中的所有内容都不会改变而将其中断,则返回到以后出现的元素):
(function()
{
new MutationObserver((mutationsList, observer) => {
for (let mutation of mutationsList)
{
if (mutation.type != 'childList' || !mutation.addedNodes.length)
{
continue;
}
Array.from(mutation.addedNodes).forEach(function(e) // or forSome if you only want to catch one object such as a button
{
if (!(e instanceof Element))
{
return;
}
// do stuff
});
}
}).observe(document.documentElement, {childList: true, subtree: true});
})();