将Greasemonkey / Tampermonkey / userscript应用于iframe?

时间:2016-06-03 14:19:25

标签: iframe greasemonkey userscripts tampermonkey

标题几乎就是问题:

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

若然,怎么样?

谢谢。

4 个答案:

答案 0 :(得分:16)

在Greasemonkey(以及Tampermonkey和大多数用户脚本引擎)中,脚本会自动触发iframe ,如果它符合@include@exclude和/或{{3指令。
而且,一个受欢迎的问题是@match

因此,如果您的脚本匹配如下:

@match https://fiddle.jshell.net/*

无论是否出现在iframe中,它都会触发jsFiddle“输出”页面。

如果您想触发JUST iframed内容:

然后你会查看window.self属性 例如,假设您有一个目标页面,如:

<body>
    <h1>I'm some webpage, either same-domain or not.</h1>
    <iframe src="//domain_B.com/somePath/somePage.htm">
...

然后你可以使用像:

这样的脚本
// ==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.
}

重要:

随着how to stop Greasemonkey from firing on iframes的发布(除此之外还有许多其他事情被打破) 仍可与Tampermonkey,Violentmonkey和一起使用,几乎与其他所有用户脚本引擎一样。
强烈建议您(Greasemonkey 4, iframes handling is severely crippled)不要使用Greasemonkey 4或更高版本。

答案 1 :(得分:1)

这是针对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);
    }
  }
});

请注意,所选元素只是一个占位符,指示已加载iframe。我们从waitForKeyElements中删除了“在那儿”跟踪器,因为该框架以后可能会再次加载(我们不能仅使用iframe,因为其内容已在其他位置加载了。)

当我们知道一个框架已加载时,我们遍历每个框架并寻找我们的标记,该标记是该框架的body中的HTML属性,称为been_there(例如<body been_there="1">)。如果缺少它,我们可以在框架的文档上运行main()函数。完成后,我们添加了been_there属性,因此我们不会再次被触发。

答案 2 :(得分:0)

请注意,如果您为自己的用户制作了Chrome扩展程序,则还需要在清单中添加"all_frames": true,否则您的扩展程序将无法使用iframe。

示例:

"content_scripts": [
    {
      "matches": ["*://*/*"],
      "all_frames": true,
      "js":["dont.js"],
      "run_at":"document_start"
    }
  ]

答案 3 :(得分:0)

https://stackoverflow.com/a/55837286/12469007的解决方案不适用于我,因此我对其进行了一些更改。它适用于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);
});

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