从父页面调用 iframe 中的 JavaScript 代码

IT技术 javascript html iframe
2021-01-26 02:05:08

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

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

请注意,我的问题是不会改变的源URLiframe,但是调用在定义的函数iframe

6个回答

假设您的 iFrame 的 id 是“targetFrame”,您要调用的函数是targetFunction()

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

您还可以使用window.frames代替访问框架document.getElementById

// this option does not work in most of latest versions of chrome and Firefox
window.frames[0].frameElement.contentWindow.targetFunction(); 
此解决方案不适用于我的小工具,这是我的代码document.getElementById('remote_iframe_0').contentWindow.my.create_element_gadg‌​et('verify_user');"remote_iframe_0 由 apache shindig 服务器以编程方式创建但window.parent.document.getElementById('remote_iframe_0').contentWindow.my.create_element_gadg‌​et('verify_user');"有效
2021-03-14 02:05:08
@Dirty Henry 你所说的“jQuery 函数”是什么意思?jQuery 是一个 JavaScript 库。
2021-03-20 02:05:08
我添加了一个关于如何使用提到的 window.frames 方法的示例。
2021-03-26 02:05:08
适用于 FF 7、Chrome 12、IE 8/9 和 Safari(不确定此版本)
2021-04-06 02:05:08
@JellicleCat 那是因为父页面和 iframe 具有不同的主机,使其成为跨域框架,正如消息告诉您的那样。只要父页面和 iframe 的协议、域和端口匹配,一切都会正常工作。
2021-04-07 02:05:08

这里有一些怪癖需要注意。

  1. HTMLIFrameElement.contentWindow可能是更简单的方法,但它不是一个标准属性,有些浏览器不支持它,主要是较旧的浏览器。这是因为 DOM Level 1 HTML 标准对window对象没有任何说明

  2. 您也可以尝试HTMLIFrameElement.contentDocument.defaultView,这是一些较旧的浏览器允许但 IE 不允许的。即便如此,标准并没有明确说明您取回window对象,原因与 (1) 相同,但如果您愿意,可以在此处选择一些额外的浏览器版本。

  3. window.frames['name']返回窗口是最古老的,因此也是最可靠的接口。但是您必须使用一个name="..."属性才能按名称获取框架,这有点丑陋/不推荐使用/过渡。id="..."会更好,但 IE 不喜欢那样。)

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

  5. 完全有可能子 iframe 尚未加载,或者其他问题使其无法访问。您可能会发现反转通信流更容易:也就是说,让子 iframewindow.parent在完成加载并准备好被回调时通知它的脚本。通过将它自己的一个对象(例如回调函数)传递给父脚本,该父脚本可以直接与 iframe 中的脚本通信,而不必担心它与什么 HTMLIFrameElement 相关联。

另请注意,由于现代浏览器(已测试 FF29 和 Chrome34)中的安全限制,您放置函数调用的位置很重要。仅从脚本标签或 $(document).ready() 调用该函数是行不通的。而是将调用放在 body 的 onload 标记中,或者按照建议的 elswhere 将调用放在 <a href="javascript:doit();">do it</a> 锚点中(请参阅stackoverflow.com/questions/921387/...)。将函数调用作为回调传递给脚本通常也有效。
2021-03-14 02:05:08
好东西!尤其是你的建议 5. 已经证明是非常有value的。在 Chrome 中尝试从父级访问 iFrame 函数时,它解决了我很多头痛的问题。将函数对象从 iFrame 中传递出去,使它在 Chrome、FF 甚至 IE 中从 9 到 7 运行起来都很有魅力,而且还可以很容易地检查函数是否已经加载。谢谢!
2021-03-17 02:05:08
@chovy:不,请参阅 Vivek 对此的回答中的说明。
2021-03-24 02:05:08
第 3 条有效,但如果你像 @le dorfier 所说的那样做,效果会更好。注意methode()部分。
2021-04-02 02:05:08

调用父 JS 函数iframe是可能的,但前提是父级和加载的页面iframe来自同一个域,即 abc.com,并且都使用相同的协议,即两者都在http://https://.

在以下提到的情况下,调用将失败:

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

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

例如,假设我注册了域 superspiringcontest.com 并发送了指向人们电子邮件的链接。当他们加载主页时,我可以iframe在那里隐藏一些s 并阅读他们的 Facebook 提要,检查最近的亚马逊或paypal交易,或者——如果他们使用的服务没有实现足够的安全性——从他们的账户中转账帐户。这就是为什么 JavaScript 仅限于同域和同协议。

请注意,对于不同的端口号,它也会失败。即 abc.com:80 != abc.com:8080
2021-03-26 02:05:08
解决方法是使用美丽而危险的en.wikipedia.org/wiki/Cross-document_messaging
2021-04-04 02:05:08
有谁知道不同的子域是否会导致此失败?我在调试一个我认为与此相关的问题时遇到了困难 - iframe 正在调用父窗口函数,但调用没有发生。
2021-04-04 02:05:08

在 IFRAME 中,将您的函数公开给 window 对象:

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

要从父页面访问,请使用:

var iframe = document.getElementById("iframeId");
iframe.contentWindow.myFunction(args);
不幸的是,这行不通。也许我应该开始一个新问题并记录我的代码?无论哪种方式,父页面内容也会打印。document.getElementById('myFrame').contentWindow.print();' and the pubic function window.print()这种方式调用的 printContent()`(不是 oncick 事件处理程序)document.getElementById('myFrame').contentWindow.printContent();
2021-03-20 02:05:08
我在这里报告的似乎是一个 IE 问题(在 IE8 中测试)。在当前版本的 Chrome 中没有问题。然而,还没有测试其他浏览器。对于那些感兴趣的人,请参阅这个jsFiddle(我认为这是动态 iframe 加载和从父级调用公共函数的一个很好的例子。)
2021-03-26 02:05:08
很好的答案。不确定这里的约定。我有一个后续问题。如果我应该开始一个新问题,我会的。我有一个问题。我的页面的 iframe 是动态填充的。它包含一个按钮,其onclick()事件只是调用window.print(). 这将输出内容iframe完美。但是当 iframe 的页面的公共函数调用时window.print(),如果父页面调用公共函数,则打印父页面的内容。我应该如何对此进行编码,以便window.print()在公共函数中调用的行为与onclick事件中的行为相同
2021-04-02 02:05:08
@Karl 你不想打电话onclick你想打电话iframe.contentWindow.print()
2021-04-03 02:05:08
@Karl - 是的,那么最好开始一个新问题。除非父窗口与 iframe 位于不同的域中。那么你尝试的任何事情都不会奏效
2021-04-06 02:05:08

如果 iFrame 的目标和包含文档在不同的域中,之前发布的方法可能不起作用,但有一个解决方案:

例如,如果文档 A 包含一个包含文档 B 的 iframe 元素,并且文档 A 中的脚本在文档 B 的 Window 对象上调用 postMessage(),那么将在该对象上触发消息事件,标记为源自文档 A。文档 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);
    }
  }
}

该脚本首先检查域是否为预期域,然后查看消息,它要么向用户显示该消息,要么通过将消息发送回最初发送消息的文档来响应。

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

太好了...在尝试上述答案后,我终于得到了您的答案,谢谢!
2021-03-13 02:05:08
easyXDM为旧浏览器提供了对 PostMessage 的抽象(包括顽固恐龙的 Flash (LocalConnection) 后备)。
2021-03-18 02:05:08