我正在创建Chrome扩展程序并尝试在gMail撰写框的SEND按钮旁边添加一个小文本。
我正在使用MutationObserver来了解撰写框窗口何时出现。我通过观察类no
的元素来做到这一点,因为撰写框元素被创建为此元素的子元素(类no
)。
当用户点击撰写按钮并出现撰写框窗口时,我会使用.after()
方法在SEND按钮旁边放置一个元素。发送按钮类名称为.gU.Up
。
这些是gMail的真正类名,也很奇怪。
以下是我正在使用的代码:
var composeObserver = new MutationObserver(function(mutations){
mutations.forEach(function(mutation){
mutation.addedNodes.forEach(function(node){
$(".gU.Up").after("<td> <div> Hi </div> </td>");
});
});
});
var composeBox = document.querySelectorAll(".no")[2];
var config = {childList: true};
composeObserver.observe(composeBox,config);
问题是我经常遇到以下错误:
Uncaught TypeError: Failed to execute 'observe' on 'MutationObserver': parameter 1 is not of type 'Node'
有人可以帮忙吗?我已经尝试了很多东西,并在这里查看了其他答案,但仍然无法摆脱这个错误。
这是我的 manifest.json 文件:
{
"manifest_version": 2,
"name": "Gmail Extension",
"version": "1.0",
"browser_action": {
"default_icon": "icon19.png",
"default_title": "Sales Analytics Sellulose"
},
"background": {
"scripts": ["eventPage.js"],
"persistent": false
},
"content_scripts": [
{
"matches": ["https://mail.google.com/*"],
"js": ["jquery-3.1.1.js", "insQ.min.js", "gmail_cs.js"]
}
],
"web_accessible_resources":[
"compose_icon.png",
"sellulosebar_icon.png"
]
}
P.S。我已经尝试过插入查询库,但它有一些缺点。它并没有让我具体说明具体要素的变化。我还没有尝试使用mutationummary库,但由于它使用MutationObserver,我认为这个问题会持续存在。
评论中添加:
确实,选择器没有给我一个节点。我检查了控制台,它给了一个对象。我还检查了控制台,并选择了我想要观察的相应元素。
但是,当我为所选元素添加console.log
时,它显示为未定义。这意味着,在节点出现之前,您可能正确执行代码。你能告诉我如何确保延迟发生吗?将&#39; setTimeout&#39;工作?如何使用MutationObserver?
答案 0 :(得分:14)
正如我在评论中提到的那样,Xan说了一个答案,错误表明document.querySelectorAll(".no")[2]
的结果不会评估为Node。
根据您在评论中提供的信息,很明显问题是您的代码执行时您想要观察的节点不存在。在该节点可用之前,有许多方法可以延迟代码的执行。一些可能性是:
使用setTimeout循环进行轮询,直到您检测到要放置MutationObserver的元素可用:
function addObserverIfDesiredNodeAvailable() {
var composeBox = document.querySelectorAll(".no")[2];
if(!composeBox) {
//The node we need does not exist yet.
//Wait 500ms and try again
window.setTimeout(addObserverIfDesiredNodeAvailable,500);
return;
}
var config = {childList: true};
composeObserver.observe(composeBox,config);
}
addObserverIfDesiredNodeAvailable();
这将在DOM中存在相对较短的节点后立即找到。此方法的可行性取决于插入目标节点后需要多长时间才能将观察者置于其上。显然,您可以根据需要调整轮询尝试之间的延迟。
答案 1 :(得分:4)
此错误表示document.querySelectorAll(".no")[2]
不是Node
。
这很可能意味着没有这样的元素; querySelectorAll
将始终返回NodeList
,即使它是空的;访问列表中不存在的成员成功没有运行时错误,但返回undefined
:从这个意义上说,NodeList
就像一个数组。
“等等,但确实如此!我在控制台中运行此代码并且它可以正常工作!”你可能会大惊小怪。那是因为当你执行它时,文档加载完成很久之后,这些元素就存在了。
所以,你需要等待添加这个根元素;很可能,另一个MutationObserver
来做这项工作。
答案 2 :(得分:3)
尝试在jQuery中使用它。
如果您正在开发Chrome扩展程序,并且从content_script中的页面或DOM中获取HTML元素(节点),则将获得Object,并且Node将作为Object的属性返回。然后,您可以从Object中获取Node并传递到observe(Node,config)
方法中。
示例
var node = $("#elementId"); //this is wrong because if you logged this in the console you will get Object
var node = $("#elementId")[0]; //This gives the first property of the Object returned, and this is correct because if you logged this in the console you will get the Node element for which you want to detect changes in the DOM.
答案 3 :(得分:0)
使用 setInterval 刷新并大约每秒检查一次节点的存在。 DOM中的Node可用后,调用观察者函数。
Rezulat brojeva 5 i 3 je 34 i 64
不是将无限刷新设置为适当的// target selector
const selector = 'div.watchlist-body';
// max time to wait (in seconds)
const maxSeconds = 10;
// time spend (in seconds)
let timer = 1;
// refresh every second
const refreshId = setInterval(() => {
// check if dom exists
if (document.querySelector(selector)) {
// clear interval
clearInterval(refreshId);
// call observer
observer();
}
// check if timeout
if (timer++ >= maxSeconds) {
clearInterval(refreshId);
console.log('Error: Max allowed seconds exceeds.');
}
}, 1000);
function observer() {
console.log('Hello, I am from observer!');
}
,而是在定义的秒数后退出刷新。在观察者中处理您的逻辑:)
答案 4 :(得分:-1)
如果您使用jQuery,请将此代码放在
中$(document).ready(function(){ // your code });