Tam*_*ege 595 html javascript iframe
基本上,我有一个iframe
嵌入在页面中,并iframe
有一些我需要从父页面调用的JavaScript例程.
现在相反的情况非常简单,因为你只需要打电话parent.functionName()
,但不幸的是,我需要完全相反.
请注意,我的问题是不会改变的源URL的iframe
,但是调用在定义的函数iframe
.
Joe*_*air 534
假设您的iFrame的id是"targetFrame",您要调用的函数是targetFunction()
:
document.getElementById('targetFrame').contentWindow.targetFunction();
Run Code Online (Sandbox Code Playgroud)
您也可以使用window.frames
而不是访问框架document.getElementById
.
// this option does not work in most of latest versions of chrome and Firefox
window.frames[0].frameElement.contentWindow.targetFunction();
Run Code Online (Sandbox Code Playgroud)
bob*_*nce 143
这里有一些需要注意的怪癖.
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.
Viv*_*HAN 64
可以调用父JS函数iframe
,但只有当父iframe
元素和加载的页面都来自同一个域,即abc.com时,两者都使用相同的协议,即两者都是on http://
或者https://
.
在下面提到的情况下,呼叫将失败:
这种限制的任何解决方法都是非常不安全的.
例如,假设我注册了域名superwinningcontest.com并发送了人们电子邮件的链接.当他们加载主页时,我可以iframe
在那里隐藏几个并阅读他们的Facebook提要,查看最近的亚马逊或PayPal交易,或者 - 如果他们使用的服务没有实现足够的安全性 - 将资金从他们的账户.这就是为什么JavaScript仅限于同域和同一协议.
Tom*_*lak 30
在IFRAME中,将您的函数公开给window对象:
window.myFunction = function(args) {
doStuff();
}
Run Code Online (Sandbox Code Playgroud)
要从父页面进行访问,请使用以下命令:
var iframe = document.getElementById("iframeId");
iframe.contentWindow.myFunction(args);
Run Code Online (Sandbox Code Playgroud)
19g*_*g96 17
如果iFrame和包含文档位于不同的域上,则先前发布的方法可能不起作用,但有一个解决方案:
例如,如果文档A包含包含文档B的iframe元素,并且文档A中的脚本在文档B的Window对象上调用postMessage(),则将在该对象上触发消息事件,标记为源自Window of Window文档A.文档A中的脚本可能如下所示:
var o = document.getElementsByTagName('iframe')[0];
o.contentWindow.postMessage('Hello world', 'http://b.example.org/');
Run Code Online (Sandbox Code Playgroud)
要为传入事件注册事件处理程序,脚本将使用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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
此脚本首先检查域是否是预期的域,然后查看它显示给用户的消息,或者通过向首先发送消息的文档发送消息来响应.
通过http://dev.w3.org/html5/postmsg/#web-messaging
仅仅是为了记录,我今天遇到了同样的问题,但这次页面嵌入了一个对象,而不是iframe(因为它是一个XHTML 1.1文档).以下是它如何与对象一起使用:
document
.getElementById('targetFrame')
.contentDocument
.defaultView
.targetFunction();
Run Code Online (Sandbox Code Playgroud)
(抱歉丑陋的换行符,不适合单行)
Quirksmode有一个帖子.
由于页面现在已经破了,只能通过archive.org访问,我在这里复制了它:
的IFrame
在这个页面上,我简要概述了从他们所在的页面访问iframe.毫不奇怪,有一些浏览器考虑因素.
iframe是一个内联框架,一个框架虽然包含一个完全独立的页面,但有一个自己的URL,但仍然放在另一个HTML页面中.这为网页设计提供了非常好的可能性.问题是访问iframe,例如将新页面加载到其中.本页介绍了如何操作.
框架还是物体?
根本问题是iframe是被视为一个框架还是一个对象.
top.frames[1].frames[2]
等等).iframe是否适合此框架层次结构?document.getElementById('theiframe'))
访问它.一般来说,浏览器允许在'真实'(硬编码)iframe上的两个视图,但生成的iframe不能作为帧访问.NAME属性
最重要的规则是给你创建name
属性的任何iframe ,即使你也使用了id
.
<iframe src="iframe_page1.html"
id="testiframe"
name="testiframe"></iframe>
Run Code Online (Sandbox Code Playgroud)
大多数浏览器需要该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
Run Code Online (Sandbox Code Playgroud)
句法.据我所知,这总是有效的.
访问文档
只要您使用该name
属性,访问iframe内的文档非常简单.要计算iframe中文档中的链接数,请执行此操作
frames['testiframe'].document.links.length
.
生成的iframe
当您通过W3C DOM生成iframe时,iframe不会立即进入frames
数组,并且frames['testiframe'].location.href
语法将无法立即生效.浏览器需要一点时间才能在数组中出现iframe,在此期间不会运行任何脚本.
该document.getElementById('testiframe').src
语法在所有情况下正常工作.
target
除了Opera之外,链接的属性对生成的iframe都不起作用,即使我将生成的iframe都给了a name
和a id
.
缺乏target
支持意味着您必须使用JavaScript来更改生成的iframe的内容,但是因为您首先需要JavaScript来生成它,所以我不认为这是一个很大的问题.
iframe中的文字大小
一个好奇的Explorer 6唯一的bug:
通过"视图"菜单更改文本大小时,iframe中的文本大小会正确更改.但是,此浏览器不会更改原始文本中的换行符,因此文本的一部分可能会变为不可见,或者当行仍然可以保留另一个单词时可能会出现换行符.
我找到了一个很优雅的解决方案
正如您所说,执行位于父文档上的代码相当容易.这是我的代码的基础,恰恰相反.
当我的iframe加载时,我调用位于父文档上的函数,作为参数传递对位于iframe文档中的本地函数的引用.现在,父文档可以通过此引用直接访问iframe的功能.
例:
在父母身上:
function tunnel(fn) {
fn();
}
Run Code Online (Sandbox Code Playgroud)
关于iframe:
var myFunction = function() {
alert("This work!");
}
parent.tunnel(myFunction);
Run Code Online (Sandbox Code Playgroud)
当iframe加载时,它将调用parent.tunnel(YourFunctionReference),它将执行参数中接收的函数.
这很简单,无需处理来自各种浏览器的所有非标准方法.
其中一些答案无法解决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','*');
}
Run Code Online (Sandbox Code Playgroud)
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();
}
Run Code Online (Sandbox Code Playgroud)
要朝另一个方向移动(在iframe中单击按钮以在iframe外部调用方法),只需切换代码段的运行位置,然后进行以下更改:
document.getElementById('my_iframe').contentWindow.postMessage('foo','*');
Run Code Online (Sandbox Code Playgroud)
对此:
window.parent.postMessage('foo','*')
Run Code Online (Sandbox Code Playgroud)