在父页面的iframe中调用JavaScript代码
基本上,我有一个embedded在页面中的iframe,iframe有一些我需要从父页面调用的JavaScript例程。
现在相反是很简单的,因为你只需要调用parent.functionName() ,但不幸的是我需要完全相反的。 
请注意,我的问题不是更改iframe的源URL ,而是调用iframe中定义的函数。
 假设你的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(); 
有一些怪癖在这里知道。
- 
HTMLIFrameElement.contentWindow可能是更简单的方法,但它不是一个标准的属性,一些浏览器不支持它,大多数是旧的。 这是因为DOM级别1的HTML标准对window对象没有什么可说的。
- 
你也可以尝试 HTMLIFrameElement.contentDocument.defaultView,这是几个较旧的浏览器允许,但IE不。 即便如此,标准并没有明确地说你得到window对象,出于与(1)相同的原因,但是如果你关心的话,你可以在这里select一些额外的浏览器版本。
- 
window.frames['name']返回窗口是最老的,因此也是最可靠的接口。 但是,你必须使用name="..."属性来获得一个名字,这是一个丑陋/不赞成/过渡的框架。 (id="..."会更好,但IE不喜欢。)
- 
window.frames[number]也是非常可靠的,但知道正确的索引是诀窍。 你可以摆脱这个例如。 如果你知道你只有一个页面上的iframe。
- 
孩子iframe还没有加载完全可能,或者是其他的错误使得它无法访问。 您可能会发现,更改通信stream程更容易:也就是说,当子结点加载完成并准备好callback时,让子结点的iframe通知其 window.parent脚本。 通过将自己的一个对象(例如callback函数)传递给父脚本,该父母就可以直接与iframe中的脚本进行通信,而不必担心与其关联的HTMLIFrameElement。
 从iframe调用一个父JS函数是可能的,但只有当父母和加载在iframe中的页面来自同一个域,即abc.com,并且都使用相同的协议,即都在http://或https:// 。 
在下面提到的情况下,呼叫将失败:
- 父页面和iframe页面来自不同的域。
- 他们使用不同的协议,一个是http://,另一个是https://。
任何解决这个限制的方法都是非常不安全的。
 例如,假设我注册了域名superwinningcontest.com并发送了链接到人们的电子邮件。 当他们加载主页时,我可以在那里隐藏一些iframe ,阅读他们的Facebook feed,查看最近的亚马逊或PayPal交易,或者如果他们使用的服务没有实现足够的安全性,他们的账户。 这就是为什么JavaScript限于同域和同协议。 
在IFRAME中,将你的函数公开给窗口对象:
 window.myFunction = function(args) { doStuff(); } 
要从父页面访问,请使用以下命令:
 var iframe = document.getElementById("iframeId"); iframe.contentWindow.myFunction(args); 
如果iFrame和包含的文档位于不同的域中,以前发布的方法可能不起作用,但有一个解决scheme:
例如,如果文档A包含一个包含文档B的iframe元素,并且文档A中的脚本调用了文档B的Window对象上的postMessage(),则会在该对象上触发一个消息事件,标记为源自Window文档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); } } } 
这个脚本首先检查域是预期的域,然后查看它向用户显示的消息,或者通过将消息发回到首先发送消息的文档来响应。
为了logging,我今天遇到了同样的问题,但是这次页面被embedded到一个对象中,而不是一个iframe(因为它是一个XHTML 1.1文档)。 以下是它如何与对象一起工作的:
 document .getElementById('targetFrame') .contentDocument .defaultView .targetFunction(); 
(对于难看的换行符,不适合在一行中)
  IFRAME应该在frames[]集合中。 使用类似的东西 
 frames['iframeid'].method(); 
我发现相当优雅的解决scheme。
如您所说,执行位于父文档上的代码相当容易。 这就是我的代码的基础,做相反的事情。
当我的iframe加载时,我调用位于父文档上的函数,将作为参数的引用传递给位于iframe文档中的本地函数。 父文档现在可以通过这个引用直接访问iframe的函数。
例:
对于父母:
 function tunnel(fn) { fn(); } 
在iframe上:
 var myFunction = function() { alert("This work!"); } parent.tunnel(myFunction); 
当iframe加载时,它会调用parent.tunnel(YourFunctionReference),它将执行参数中收到的函数。
这很简单,而不必处理来自各种浏览器的所有非标准方法。
Quirksmode就此发表了一篇文章 。
由于这个页面现在已经被破坏了,只能通过archive.org访问,我在这里转载了它:
的IFrame
在这个页面上,我简单介绍一下从他们正在访问的页面访问iframe。 毫不奇怪,有一些浏览器的考虑。
一个iframe是一个内联框架,一个框架虽然包含一个完全独立的页面,并且拥有自己的URL,但却被放置在另一个HTML页面中。 这在网页devise中提供了非常好的可能性。 问题是访问iframe,例如加载一个新的页面。 这个页面解释了如何做到这一点。
框架或对象?
根本的问题是iframe是被看作是一个框架还是一个对象。
-  正如“ 框架介绍”页面所述,如果使用框架,浏览器会为您创build一个框架层次结构( top.frames[1].frames[2]等)。 iframe是否适合这个框架层次结构?
-  还是浏览器看到一个iframe作为另一个对象,恰好有一个src属性的对象? 在这种情况下,我们必须使用标准的DOM调用 (如document.getElementById('theiframe'))来访问它。 通常,浏览器允许在“真实”(硬编码)iframe上的两个视图,但是生成的iframe不能作为帧来访问。
NAME属性
 最重要的规则是给你的任何iframe创build一个name属性,即使你也使用了一个id 。 
 <iframe src="iframe_page1.html" id="testiframe" name="testiframe"></iframe> 
 大多数浏览器需要name属性才能使iframe成为框架层次结构的一部分。 一些浏览器(特别是Mozilla)需要这个id来使iframe可以作为一个对象来访问。 通过将这两个属性分配给iframe,您可以保持打开选项。 但name比id更重要。 
访问
 要么作为对象访问iframe并更改其src要么作为框架访问iframe并更改其location.href 。 
document.getElementById('iframe_id')。src ='newpage.html'; frames ['iframe_name']。location.href ='newpage.html'; 帧语法稍微好一点,因为Opera 6支持它,但不支持对象语法。
访问iframe
因此,为了获得完整的跨浏览器体验,您应该给iframe一个名称并使用它
 frames['testiframe'].location.href 
句法。 据我所知,这总是有效的。
访问文档
 访问iframe中的文档非常简单,只要使用name属性即可。 要计算iframe中文档中链接的数量,请执行frames['testiframe'].document.links.length 。 
生成iframe
 当您通过W3C DOM生成iframe时,iframe不会立即进入frames数组,而frames['testiframe'].location.href语法将不会立即生效。 浏览器需要一点时间才能在数组中显示iframe,在这段时间内没有脚本可以运行。 
  document.getElementById('testiframe').src语法在任何情况下都可以正常工作。 
 除了在Opera中,链接的target属性不能和生成的iframe一起工作,即使我给了我生成的iframe两个name和一个id 。 
 缺lesstarget支持意味着您必须使用JavaScript来更改生成的iframe的内容,但是由于您首先需要使用JavaScript来生成它,所以我不认为这是一个问题。 
在iframe中的文本大小
一个好奇的Explorer 6唯一的bug:
当您通过“查看”菜单更改文字大小时,iframe中的文字大小会正确更改。 但是,此浏览器不会更改原始文本中的换行符,以便部分文本可能会变得不可见,或者行可能会出现换行符,而该行仍可能包含另一个词。
继续JoelAnair的回答:
为了更健壮,使用如下:
 var el = document.getElementById('targetFrame'); if(el.contentWindow) { el.contentWindow.targetFunction(); } else if(el.contentDocument) { el.contentDocument.targetFunction(); } 
像魅力:)
Folinging 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(); ... 
  $("#myframe").load(function() { alert("loaded"); }); 
同样的事情,但更简单的方法将是如何刷新iframe中的页面的父页面 。 只要调用父页面的函数来调用JavaScript函数来重新加载页面:
 window.location.reload(); 
或者直接从iframe中的页面执行此操作:
 window.parent.location.reload(); 
两者都有效。
如果我们要从编码生成的iframe中调用父页面的javascript函数。 前阴影盒或灯箱
window.parent.targetFunction();
这些答案中的一些没有解决CORS问题,或者在放置代码片段的地方使其不太明显。
这是一个具体的例子。 假设我想单击父页面上的一个button,并在iframe中执行某些操作。 这是我该怎么做的。
parent_frame.html
 <button id='parent_page_button' onclick='call_button_inside_frame()'></button> function call_button_inside_frame() { document.getElementById('my_iframe').contentWindow.postMessage('foo','*'); } 
iframe_page.html
 window.addEventListener("message", receiveMessage, false); function receiveMessage(event) { if(event) { click_button_inside_frame(); } } function click_button_inside_frame() { document.getElementById('frame_button').click(); } 
去另一个方向(单击iframe内部的button来调用iframe之外的方法),只需切换代码片段所在的位置,然后更改:
 document.getElementById('my_iframe').contentWindow.postMessage('foo','*'); 
对此:
 window.parent.postMessage('foo','*') 
 试试parent.myfunction() 
使用以下命令在父页面调用一个框架的function
 parent.document.getElementById('frameid').contentWindow.somefunction()