Exi*_*las 3 javascript iframe synchronization cross-domain userscripts
请参考具有相同的JavaScript以便在网页和iframe中运行的技术,如此答案所述:
例如,假设您在domain_A.com上具有此页面:
<html>
<body>
<iframe src="http://domain_B.com/SomePage.htm"></iframe>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
如果您像这样设置@match指令:
// @match http://domain_A.com/*
// @match http://domain_B.com/*
Run Code Online (Sandbox Code Playgroud)
然后您的脚本将运行两次-一次在主页上,一次在iframe上,就好像它是一个独立页面一样。
使脚本的两个实例相互通信的选项有哪些?
这将是同步实例所必需的。例如,只有在网页脚本实例完成后才让iframe脚本实例执行其任务,反之亦然。
这两个脚本实例可以使用相互通信postMessage()。关于:
这将需要同步实例,例如,使iframe仅在一个网页完成后才能执行其任务,反之亦然。
这就是其他答案中显示的内容。
但是 Chrome在向扩展程序呈现框架/ iframe
方面存在一些错误,因此,要解决这些错误,您必须注入调用的代码postMessage()。
以下脚本显示了如何。它:
安装此脚本(由于多年以来在目标站点中的更改,因此更新了感谢SomePerformance):
// ==UserScript==
// @name _Cross iframe, cross-domain, interscript communication
// @include http://fiddle.jshell.net/2nmfk5qs/*
// @include http://puppylinux.com/
// @grant none
// ==/UserScript==
/* eslint-disable no-multi-spaces */
if (window.top === window.self) return;
console.log ("Script start...");
if (window.location.href.includes('fiddle')) {
console.log ("Userscript is in the MAIN page.");
//--- Setup to process messages from the GM instance running on the iFrame:
window.addEventListener ("message", receiveMessageFromFrame, false);
console.log ("Waiting for Message 1, from iframe...");
}
else {
console.log ("Userscript is in the FRAMED page.");
//--- Double-check that this iframe is on the expected domain:
if (/puppylinux\.com/i.test (location.host) ) {
window.addEventListener ("message", receiveMessageFromContainer, false);
//--- Send the first message to the containing page.
sendMessageFromAnIframe (
"***Message 1, from iframe***", "http://fiddle.jshell.net"
);
console.log ("Waiting for Message 2, from containing page...");
}
}
function receiveMessageFromFrame (event) {
if (event.origin != "http://puppylinux.com") return;
console.log ('The container page received the message, "' + event.data + '".');
//--- Send message 2, back to the iframe.
sendMessageToAnIframe (
"#testIframe",
"***Message 2, from the container page***",
"http://puppylinux.com"
);
}
function receiveMessageFromContainer (event) {
if (event.origin != "http://fiddle.jshell.net") return;
console.log ('The iframe received the message, "' + event.data + '".');
}
/*--- Because of bugs in how Chrome presents frames to extensions, we must inject
the messaging code. See bug 20773 and others.
frames, top, self.parent, contentWindow, etc. are all improperly undefined
when we need them. See Firefox and other browsers for the correct behavior.
*/
function sendMessageFromAnIframe (message, targetDomain) {
var scriptNode = document.createElement ('script');
scriptNode.textContent = 'parent.postMessage ("' + message
+ '", "' + targetDomain + '");'
;
document.body.appendChild (scriptNode);
}
function sendMessageToAnIframe (cssSelector, message, targetDomain) {
function findIframeAndMessageIt (cssSelector, message, targetDomain) {
var targetIframe = document.querySelector (cssSelector)
if (targetIframe) {
targetIframe.contentWindow.postMessage (message, targetDomain);
}
}
var scriptNode = document.createElement ('script');
scriptNode.textContent = findIframeAndMessageIt.toString ()
+ 'findIframeAndMessageIt ("' + cssSelector
+ '", "' + message
+ '", "' + targetDomain + '");'
;
document.body.appendChild (scriptNode);
}
console.log ("Script end");
Run Code Online (Sandbox Code Playgroud)
然后访问jsFiddle的此测试页。
您将在javascript控制台中看到以下内容:
脚本开始... 用户脚本位于主页面中。 正在等待来自iframe的消息1,... 脚本结束 脚本开始... 用户脚本位于“框架”页面中。 正在等待消息2,包含页面... 脚本结束 容器页面收到消息“ ***来自iframe的消息1”。 iframe收到消息“ ***来自容器页面的消息2,***”。