基本上,我将iframe
嵌入到页面中,并且iframe
具有一些我需要从父页面调用的JavaScript例程。
现在相反非常简单,因为您只需要调用parent.functionName()
,但是不幸的是,我需要恰好相反。
请注意,我的问题不是更改iframe
的源URL ,而是调用iframe
定义的函数。
#1楼
仅作记录,我今天遇到了同一问题,但是这次页面被嵌入对象而不是iframe中(因为它是XHTML 1.1文档)。 这是如何与对象一起使用的:
document
.getElementById('targetFrame')
.contentDocument
.defaultView
.targetFunction();
(很抱歉换行太丑,没有一行)
#2楼
跟随尼丁·班萨尔(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');
var frame_win = getIframeWindow(el);
if (frame_win) {
frame_win.targetFunction();
...
}
...
#3楼
我找到了一个很好的解决方案。
如您所说,执行位于父文档中的代码非常容易。 这就是我的代码的基础,反之亦然。
加载iframe时,我会调用位于父文档上的函数,并将对iframe文档中本地函数的引用作为参数传递。 现在,通过此引用,父文档可以直接访问iframe的功能。
例:
在父项上:
function tunnel(fn) {
fn();
}
在iframe上:
var myFunction = function() {
alert("This work!");
}
parent.tunnel(myFunction);
加载iframe时,它将调用parent.tunnel(YourFunctionReference),它将执行参数中接收的功能。
如此简单,而不必处理各种浏览器中的所有非标准方法。
#4楼
使用以下命令来调用父页面中框架的功能
parent.document.getElementById('frameid').contentWindow.somefunction()
#5楼
由于该页面现在已损坏,并且只能通过archive.org进行访问,因此在此处进行了复制:
内嵌框架
在此页面上,我将简要概述如何从它们所在的页面访问iframe。 毫不奇怪,有一些浏览器注意事项。
iframe是一个内联框架,该框架虽然包含一个完全独立的页面及其自己的URL,但仍放置在另一个HTML页面中。 这在网页设计中提供了非常好的可能性。 问题是要访问iframe,例如将新页面加载到其中。 此页面说明了操作方法。
框架还是物体?
基本问题是将iframe视为框架还是对象。
- 如框架简介页中所述,如果您使用框架,则浏览器会为您创建框架层次结构(
top.frames[1].frames[2]
等)。 iframe是否适合此框架层次结构? - 还是浏览器将iframe视为另一个对象,而该对象恰好具有src属性? 在这种情况下,我们必须使用标准的DOM调用 (如
document.getElementById('theiframe'))
进行访问。 通常,浏览器允许在“真实”(硬编码)iframe上同时使用两种视图,但是生成的iframe无法作为框架访问。
NAME属性
最重要的规则是,即使您也使用id
,也要为创建的所有iframe提供一个name
属性。
<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'; frame ['iframe_name']。location.href ='newpage.html'; 框架语法稍微更可取,因为Opera 6支持它,但对象语法不支持。
访问iframe
因此,要获得完整的跨浏览器体验,您应该给iframe命名并使用
frames['testiframe'].location.href
句法。 据我所知,这始终有效。
存取文件
只要使用name
属性,在iframe中访问文档就非常简单。 要计算iframe中文档中的链接数,请执行frames['testiframe'].document.links.length
。
生成的iframe
但是,当您通过W3C DOM生成iframe时,iframe不会立即输入到frames
数组中,并且frames['testiframe'].location.href
语法将无法立即使用。 浏览器需要一些时间才能在阵列中打开iframe,在这段时间内没有脚本可以运行。
document.getElementById('testiframe').src
语法在所有情况下都可以正常工作。
链接的target
属性对生成的iframe都不起作用,除了Opera中,即使我给生成的iframe都指定了name
和id
。
缺乏target
支持意味着您必须使用JavaScript来更改生成的iframe的内容,但是由于您首先还是需要JavaScript才能生成它,所以我认为这并不是什么大问题。
iframe中的文字大小
一个好奇的Explorer 6仅bug:
通过“视图”菜单更改文字大小时,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();
#7楼
IFRAME应该在frames[]
集合中。 使用类似
frames['iframeid'].method();
#8楼
在IFRAME中,将函数公开给window对象:
window.myFunction = function(args) {
doStuff();
}
要从父页面进行访问,请使用以下命令:
var iframe = document.getElementById("iframeId");
iframe.contentWindow.myFunction(args);
#9楼
这里有一些怪癖要注意。
HTMLIFrameElement.contentWindow
可能是更简单的方法,但是它不是一个标准的属性,某些浏览器不支持它,大多数是较旧的浏览器。 这是因为DOM Level 1 HTML标准对window
对象没有什么可说的。您也可以尝试
HTMLIFrameElement.contentDocument.defaultView
,这是一些较旧的浏览器允许的,但IE不允许。 即使这样,该标准也没有明确指出要返回window
对象,原因与(1)相同,但是如果您愿意,可以在此处选择一些其他的浏览器版本。返回窗口的
window.frames['name']
是最早的接口,因此也是最可靠的接口。 但是您必须使用name="..."
属性才能按名称获取框架,该框架有点难看/不推荐使用/过渡。 (id="..."
会更好,但IE不喜欢那样。)window.frames[number]
也非常可靠,但是知道正确的索引是诀窍。 你可以摆脱这个例如。 如果您知道页面上只有一个iframe。子iframe完全有可能尚未加载,或者有其他问题导致无法访问。 您可能会发现逆向通信流程更容易:也就是说,让子iframe在完成加载并准备好被调用时通知它的
window.parent
脚本。 通过将其自己的对象之一(例如回调函数)传递给父脚本,该父对象可以直接与iframe中的脚本进行通信,而不必担心与之关联的HTMLIFrameElement。
#10楼
可以从iframe
调用父级JS函数,但是仅当父级和iframe
中加载的页面都来自同一域(即abc.com),并且两者都使用相同的协议(即,两者都位于http://
或https://
。
在以下情况下,呼叫将失败:
- 父页面和iframe页面来自不同的域。
- 他们使用的协议不同,一个协议位于http://,另一个协议位于https://。
解决此限制的任何方法都将非常不安全。
例如,假设我注册了域名superwinningcontest.com,并发送了指向人们电子邮件的链接。 当他们加载主页时,我可以在其中隐藏一些iframe
并阅读他们的Facebook提要,检查最近的Amazon或PayPal交易,或者-如果他们使用的服务没有实现足够的安全性,则可以从中转移资金他们的帐户。 这就是JavaScript仅限于相同域和相同协议的原因。
#11楼
$("#myframe").load(function() {
alert("loaded");
});
#12楼
其中一些答案无法解决CORS问题,或者无法在放置代码段的地方使交流变得显而易见。
这是一个具体的例子。 假设我想点击父页面上的按钮,然后在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中单击按钮以在iframe外部调用方法),只需切换代码段的运行位置,然后进行以下更改:
document.getElementById('my_iframe').contentWindow.postMessage('foo','*');
对此:
window.parent.postMessage('foo','*')
#13楼
同样的事情,但是更简单的方法是如何从iframe中的页面刷新父页面 。 只需调用父页面的函数即可调用javascript函数来重新加载页面:
window.location.reload();
或直接在iframe中的页面上执行此操作:
window.parent.location.reload();
两者都可以。
#14楼
继续JoelAnair的回答:
为了提高鲁棒性,请使用以下方法:
var el = document.getElementById('targetFrame');
if(el.contentWindow)
{
el.contentWindow.targetFunction();
}
else if(el.contentDocument)
{
el.contentDocument.targetFunction();
}
像魅力一样工作:)
#15楼
如果iFrame和包含文档位于不同的域中,则先前发布的方法可能不起作用,但是有一个解决方案:
例如,如果文档A包含包含文档B的iframe元素,并且文档A中的脚本在文档B的Window对象上调用postMessage(),则将在该对象上触发消息事件,标记为源自Windows的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);
}
}
}
该脚本首先检查域是否为预期的域,然后查看消息,该消息要么显示给用户,要么通过将消息发回给发送消息的文档来响应。
通过http://dev.w3.org/html5/postmsg/#web-messaging
#16楼
如果要从其他函数(例如,shadowbox或lightbox)生成的iframe上调用Parent上的JavaScript函数。
您应该尝试利用window
对象并调用父函数:
window.parent.targetFunction();
#17楼
尝试尝试parent.myfunction()