我正在尝试在 Chrome 中为我在工作中一直使用的网站编写 Tampermonkey 脚本。我希望脚本删除某个类或标题的按钮上的禁用属性。在我看来,这似乎是一个相当简单的任务,但由于该网站大量使用 Ajax,我遇到了困难。
当我第一次加载网站时,有一个标题、一个左侧边栏,并且占据屏幕其余部分的主应用程序窗口是空白的。
用户将单击标题或侧栏中的可用选项之一,然后通过 ajax 将内容加载到主应用程序窗口中。主应用程序窗口有一个标题,其中包含出现新选项卡的选项卡,我可以在打开的选项卡和关闭的选项卡之间切换。主应用程序窗口主体是所有内容显示的地方,并且根据我正在处理的内容有许多不同的格式。
我已经能够成功执行标题和侧边栏中出现的按钮的选择器并禁用/启用它们。
编辑:今天我玩了一下,意识到 HTML 中的几个地方包含
#shadow-root (open)
,所以我开始看看这是什么。直到今天做了一些研究,我才意识到影子 DOM 树是与主文档 DOM 树分开渲染的。这解释了为什么它没有触发我的功能。我做了一些进一步的测试,并且能够在第一次出现 #shadow-root (open)
之前在主应用程序窗口中的 ajax 内容上触发我的函数。
这是我到目前为止的 Tampermonkey 脚本,它需要 JQuery 和 waitForKeyElements(),这是我通过有关 ajax 内容的堆栈溢出的其他问题发现的:
// ==Userscript==
// @name Enable buttons
// @match my.website.url.org
// @require https://code.jquery.com/jquery-3.6.4.min.js
// @require https://gist.github.com/raw/2625891/waitForKeyElements.js
// @grant GM_addStyle
// @version 0.1
// ==/Userscript==
(function() {
waitForKeyElements ('button.btn.ripple.primary', modifyButtons, false);
function modifyButtons(jNode) {
console.log ("~~~~~~~~ Button has been encountered ~~~~~~~~");
var buttons = document.querySelectorAll('button.btn.ripple.primary');
for (var i=0; i<buttons.length; i++) {
buttons[i].disabled = false;
console.log(i + " buttons touched and enabled.");
}
}
})();
这是我尝试修改的按钮的 HTML:
#shadow-root (open)
<!---->
<button type="button" title="Create" class="btn ripple primary" disabled>
<span>Create</span>
</button>
<!---->
我也尝试过:
waitForKeyElements ('button[title="Create"]', modifyButtons, false);
即使我通过右键单击菜单进入正确的页面后手动运行脚本,这些都不会触发修改按钮功能。
标题和侧栏中有一些按钮,我已成功触发了modifyButtons 函数来测试我的脚本。以下是侧边栏按钮之一的 HTML:
<button title="Search" class="pull-right blue__btn sat-stroked-button">
<span class="sat-button-wrapper">
Search
</span>
</button>
侧边栏中有六个带有这些类的按钮,我可以使用以下命令在所有六个按钮上触发“modifyButtons”功能:
waitForKeyElements ('button.pull-right.blue__btn.sat-stroked-button', modifyButtons, false);
我能够通过以下方式在侧边栏中的一个特定按钮上触发修改按钮功能:
waitForKeyElements ('button[title="Search"]', modifyButtons, false);
过去,我已经搞乱了
buttons[i].disabled = false;
和buttons[i].disabled = true;
,当我让它在侧边栏中的按钮上触发时,它完成了我需要的事情。我只需要它在这个阶段实际查看并触发主应用程序窗口中的按钮。
#shadow-root (open)
元素?您应该尝试创建一个突变观察器,寻找适当影子根的选择器,然后观察这些根的动态更新。 以本存储库中的示例为例: github.com/jcsteh/axSGrease
MutationObserver(function (mutations) {
for (let mutation of mutations) {
try {
if (mutation.type === "childList") {
for (let node of mutation.addedNodes) {
if (node.nodeType != Node.ELEMENT_NODE) {
continue;
}
applyTweaks(node, DYNAMIC_TWEAKS, true);
}
} else if (mutation.type === "attributes") {
applyTweaks(mutation.target, DYNAMIC_TWEAKS, true, true);
}
} catch (e) {
// Catch exceptions for individual mutations so other mutations are still handled.
console.log("Exception while handling mutation: " + e);
}
}
});
您可以使用特定选择器来观察影子根并将其调出,并在该特定元素的 element.shadowRoot 上调用observer.observe。然后,直接在该阴影上应用一次调整。