javascript - 从iframe的父pag调用JavaScript代码

  显示原文与译文双语对照的内容

基本上,我在一个页面中嵌入了一个 iframe,并且iframe有一些 JavaScript 例程我需要从父页面调用它。

现在相反,因为你只需要调用 parent.functionName(),但不幸的是,我需要的正好相反。

请注意,我的问题不是改变iframe的源 URL,而是调用在iframe中定义的函数。

时间:

假设你的iframe的标识是"targetFrame",你想要调用的函数是 targetFunction():


document.getElementById('targetFrame').contentWindow.targetFunction();

你也可以使用 window.frames 而不是 document.getElementById 访问框架。


window.frames[0].frameElement.contentWindow.targetFunction();

这里有一些奇怪的地方需要注意。

  1. HTMLIFrameElement.contentWindow 可能是更简单的方法,但它不是一个标准的属性,有些浏览器不支持它,大多数都是旧的。 这是因为DOM级别 1的HTML标准没有关于 window 对象的内容。

  2. 你也可以尝试 HTMLIFrameElement.contentDocument.defaultView 这两个老浏览器允许但 IE 不允许。 即使如此,标准也没有明确地说你得到 window 对象,因为与( 1 ) 相同,但是如果你愿意,你可以在这里选择一些额外的浏览器版本。

  3. window.frames['name'] 返回窗口是最古老的,因此最可靠的接口。 但是,你必须使用 name="..." 属性才能按名称获取框架,这有点难看 已经废弃 /过渡。( id="..." 会更好,但 IE 不喜欢这样。)

  4. window.frames[number] 也非常可靠,但是知道正确的索引是窍门。 你可以摆脱这一点。 如果你知道页面上只有一个 iframe 。

  5. 完全可能的是,子iframe还没有加载,或者发生了其他错误使它无法访问。 你可能会发现,反转通信流程更容易: 也就是说,让子iframe在完成加载后通知它的window.parent 脚本,并准备回调用它。 通过传递自己的对象( 例如。 父脚本的回调函数,父脚本可以直接与iframe中的脚本通信,而不必担心与之关联的HTMLIFrameElement 。

iframe 调用一个父JS函数是可行的,但只有当 iframe 中加载的页面来自同一个域 换句话说,abc.com, 时,两者都使用相同的协议 换句话说,两者都在 http:// 或者 https:// 上。

在以下情况下调用将失败:

  1. 父页面和iframe页面来自不同的域。
  2. 他们正在使用不同的协议,一个在 http://上,另一个在 https://. 上

对此限制的任何解决办法都是非常不安全的。

例如假设我注册了域 superwinningcontest.com 并发送了指向用户电子邮件的链接。 当他们加载主页时,我可以隐藏一些 iframe,并阅读他们的Facebook提要,查看最近的亚马逊或者贝宝交易,or--if,他们使用了没有实现足够security--transfer货币的服务。 这就是为什么JavaScript仅限于same-domain和 same-protocol 。

在IFRAME中,将你的函数公开到窗口对象:


window.myFunction = function(args) {
 doStuff();
}

要从父页面访问,请使用以下命令:


var iframe = document.getElementById("iframeId");
iframe.contentWindow.myFunction(args);

只是为了记录,我今天遇到了同样的问题,但是这次页面嵌入了一个对象,而不是一个 iframe ( 因为它是一个 XHTML 1.1文档) 。 下面是对象的工作原理:


document
. getElementById('targetFrame')
. contentDocument
. defaultView
. targetFunction();

( 不好意思的是,丑陋的换行符,不适合一行)

如果iFrame和包含文档位于不同的域中,这些方法可能不起作用,但有一个解决方案:

例如,如果文档包含一个iframe元素包含文档,在文档和脚本的窗口对象上调用 postMessage() 文档b,然后将触发消息事件对象,标记为来自文件的窗口。 文档A 中的脚本可能类似于:


var o = document.getElementsByTagName('iframe')[0];
o.contentWindow.postMessage('Hello world', 'http://b.example.org/');

要为传入事件注册事件处理程序,脚本将使用 addEventListener() ( 或者类似的机制) 。 例如文档B 中的脚本可能类似于:


window.addEventListener('message', receiver, false);
function receiver(e) {
 if (e.origin == 'http://example.com') {
 if (e.data == 'Hello world') {
 e.source.postMessage('Hello', e.origin);
 } else {
 alert(e.data);
 }
 }
}

This script first checks domain is expected domain,and then looks at",which it either displays to user,or responds to by sending a"back to document which sent"infirst音译。

通过 http://dev.w3.org/html5/postmsg/#web-messaging 编辑器

继续使用 的joelanair回答:

要获得更多的健壮性,请使用如下:


var el = document.getElementById('targetFrame');

if(el.contentWindow)
{
 el.contentWindow.targetFunction();
}
else if(el.contentDocument)
{
 el.contentDocument.targetFunction();
}

Workd喜欢魅力:)

同样的事情,但稍微简单一点的方法将是如何在iframe中刷新父页面。 调用页面的父函数调用javascript函数重新加载页面:


window.location.reload();

或者直接从iframe中的页面执行这里操作:


window.parent.location.reload();

两个作品。

关注 Nitin bansal的回答

更多的健壮性:


function getIframeWindow(iframe_object) {
 var doc;

 if (iframe_object.contentWindow) {
 return iframe_object.contentWindow;
 }

 if (iframe_object.window) {
 return iframe_object.window;
 } 

 if (!doc && iframe_object.contentDocument) {
 doc = iframe_object.contentDocument;
 } 

 if (!doc && iframe_object.document) {
 doc = iframe_object.document;
 }

 if (doc && doc.defaultView) {
 return doc.defaultView;
 }

 if (doc && doc.parentWindow) {
 return doc.parentWindow;
 }

 return undefined;
}


...
var el = document.getElementById('targetFrame');

getIframeWindow(el).targetFunction();
...

...