将Greasemonkey/Tampermonkey/userscript应用于iframe?

UpI*_*pIX 16 iframe greasemonkey userscripts tampermonkey

标题几乎是一个问题:

是否可以将一个Greasemonkey脚本添加到iframed网站?

如果是这样,怎么样?

谢谢.

Bro*_*ams 17

在Greasemonkey的(而且Tampermonkey最userscript引擎),一个脚本会自动闪光的iframe,如果它符合@include,@exclude,和/或@match指令.
而且,一个流行的问题是如何阻止Greasemonkey在iframe上开火.

所以,如果您的脚本匹配如下:

@match https://fiddle.jshell.net/*
Run Code Online (Sandbox Code Playgroud)

它会触发jsFiddle"输出"页面,无论它们是否出现在iframe中.


如果您想触发JUST iframed内容:

然后你会检查window.self财产.
例如,假设您有一个目标页面,如:

<body>
    <h1>I'm some webpage, either same-domain or not.</h1>
    <iframe src="//domain_B.com/somePath/somePage.htm">
...
Run Code Online (Sandbox Code Playgroud)

然后你可以使用如下脚本:

// ==UserScript==
// @name    _Fires specially on domain_B.com iframes
// @match   *://domain_B.com/somePath/*
// ==/UserScript==

if (window.top === window.self) {
    //--- Script is on domain_B.com when/if it is the MAIN PAGE.
}
else {
    //--- Script is on domain_B.com when/if it is IN AN IFRAME.
    // DO YOUR STUFF HERE.
}
Run Code Online (Sandbox Code Playgroud)

重要:

随着Greasemonkey 4的发布,iframes处理严重瘫痪(除此之外还有许多其他因素被打破).
仍然适用于Tampermonkey,Violentmonkey和几乎所有其他用户脚本引擎.
强烈建议您(不包括Greasemonkey本身)不要使用Greasemonkey 4或更高版本.

  • 请注意,这是 GreaseMonkey 4 中的[损坏](https://github.com/greasemonkey/greasemonkey/issues/2574) (3认同)
  • Greasemonkey似乎不建议你不要使用4或更高版本。他们只是通知它破坏了向后兼容性。 (3认同)

Ada*_*atz 6

这是针对iframe没有位置可触发的情况的解决方案@include@match

这适用于 Greasemonkey 4。

我们必须等待每个帧加载完毕,然后才能对其进行操作。我这样做是通过使用waitForKeyElements.js,它等待与给定 CSS 选择器匹配的元素,就像在 中循环匹配document.querySelectorAll("selector"),然后将给定函数应用于响应:

// ==UserScript==
// @include https://blah.example.com/*
// @require https://git.io/waitForKeyElements.js
// ==/UserScript==

function main(where) {
  // do stuff here with  where  instead of  document
  // e.g. use  where.querySelector()  in place of  document.querySelector()
  // and add stylesheets with  where.head.appendChild(stylesheet)
}

main(document); // run it on the top level document (as normal)

waitForKeyElements("iframe, frame", function(elem) {
  elem.removeAttribute("wfke_found"); // cheat wfke's been_there, use our own
  for (let f=0; f < frames.length; f++) {
    if (!frames[f].document.body.getAttribute("been_there")) {

      main(frames[f].document);

      frames[f].document.body.setAttribute("been_there", 1);
    }
  }
});
Run Code Online (Sandbox Code Playgroud)

请注意,所选元素只是一个占位符,表明iframe已加载。我们从中删除了“去过那里”跟踪器,waitForKeyElements因为该框架可能会在稍后再次加载(我们不能仅仅使用它,iframe因为它的内容已加载到其他地方)。

当我们知道一个框架已加载时,我们遍历每个框架并查找我们的标记,即框架body调用中的 HTML 属性been_there(如<body been_there="1">)。如果缺少,我们可以main()在框架的文档上运行我们的函数。完成后,我们添加been_there属性,以免再次触发。


小智 5

/sf/answers/3908610051/的解决方案对我不起作用,所以我对其进行了一些更改。它适用于 Greasemonkey 4.10。

// ==UserScript==
// @include https://blah.example.com/*
// @require https://git.io/waitForKeyElements.js
// ==/UserScript==

function main(where) {
  // do stuff here with  where  instead of  document
  // e.g. use  where.querySelector()  in place of  document.querySelector()
  // and add stylesheets with  where.head.appendChild(stylesheet)
}

main(document); // run it on the top level document (as normal)

waitForKeyElements("iframe, frame", function(elem) {
  elem.addEventListener("load", function () {
    elem.removeAttribute("wfke_found");
  });
  main(elem.contentDocument);
});
Run Code Online (Sandbox Code Playgroud)

最大的变化是它现在即使在浏览 iframe 时也能工作。