MutationObserver error : How could I wait for the creation of an element?
MutationObserver error : How could I wait for the creation of an element?
我正在尝试制作 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 时该元素已经存在)。
注意: 我尝试使用 $(document).ready()
,但它是在我要添加按钮的元素创建之前触发的。
NB-bis:我没有post整个脚本。
不幸的是,该错误消息使用起来非常模糊,但您打错了字:
observer.observe(document.body, {
childlist: true,
subtree: true,
attributes: false,
characterData: false,
});
应该是
observer.observe(document.body, {
childList: true,
subtree: true,
attributes: false,
characterData: false,
});
例如childlist
=> childList
在这种情况下,运行 您在 Chrome 中的相同代码比 "cannot be converted to return the specified type" 提供了更有用的信息。它说
The options object must set at least one of 'attributes', 'characterData', or 'childList' to true.
实际上,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
s,请使用可以减轻很多痛苦的库。
我看到有人认为 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});
})();
我正在尝试制作 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 时该元素已经存在)。
注意: 我尝试使用 $(document).ready()
,但它是在我要添加按钮的元素创建之前触发的。
NB-bis:我没有post整个脚本。
不幸的是,该错误消息使用起来非常模糊,但您打错了字:
observer.observe(document.body, {
childlist: true,
subtree: true,
attributes: false,
characterData: false,
});
应该是
observer.observe(document.body, {
childList: true,
subtree: true,
attributes: false,
characterData: false,
});
例如childlist
=> childList
在这种情况下,运行 您在 Chrome 中的相同代码比 "cannot be converted to return the specified type" 提供了更有用的信息。它说
The options object must set at least one of 'attributes', 'characterData', or 'childList' to true.
实际上,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
s,请使用可以减轻很多痛苦的库。
我看到有人认为 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});
})();