iframe 很多网站都在用,虽然方便开发与维护(可能同时有几个页面调用同一个 iframe ),不过却存在安全问题。嵌入 iframe 的页面,父页面与子页面均可以很轻松的在同域或跨子域的情况下进行读写操作;在完全不同域的情况下,也可以通过更改 hash 的方式进行通信。下面我在九个不同(版本的)浏览器中对此进行数据传输与更改的兼容性测试。
同域或跨子域读写操作 iframe 里的内容
父页面读写操作子页面:
代码如下 |
复制代码 |
<iframe id="test-iframe" name="test-iframe" src="child.html" scrolling="no" frameborder="0"></iframe>
<script>
window.onload = function () {
/*
* 下面两种获取节点内容的方式都可以。
* 由于 IE6, IE7 不支持 contentDocument 属性,所以此处用了通用的
* window.frames["iframe Name"] or window.frames[index]
*/
var d = window.frames["test-iframe"].document;
d.getElementsByTagName('h1')[0].innerHTML = 'pp';
alert(d.getElementsByTagName('h1')[0].firstChild.data);
}
</script>
|
注:在请务必通过 window.onload 方法访问 iframe 中的节点,否则浏览器会提示错误-拒绝访问。在 IE8, Firefox3.6, Opera11 下在 DOMReady 时也可以访问 iframe 中的节点。
子页面读写操作父页面:
代码如下 |
复制代码 |
<script>
parent.document.getElementsByTagName('h1')[0].innerHTML = 'pp';
alert(parent.document.getElementsByTagName('h1')[0].firstChild.data);
</script>
|
小结:
•1 测试通过 IE6, IE7, IE8, Firefox2.0, Firefox3.0, Firefox3.6, Chrome8, Opera11, Safari5.
•2 查阅资料得出 document.getElementById(‘id name’).contentDocument 全等于 window.frames["iframe Name"].document.
•3 跨子域时,需要在父页面和子页面 JS 中分别加上 document.domain = 'xxx.com';
跨域操作 iframe 里内容
当两个网页所在域不同时,要实现数据的互相调用,只能通过 JS 改变 location 对象的 hash 属性的值来做到互相通信。
父页面:
代码如下 |
复制代码 |
<iframe id="test-iframe" src="http://www.yyy.com/child.html" scrolling="no" frameborder="0"></iframe>
<input type="button" value="send" onclick="sendRequest()" />
<script>
function sendRequest() {
document.getElementById('test-iframe').src += '#a';
}
var interval = window.setInterval(function(){
if(location.hash) {
alert(location.hash);
window.clearInterval(interval);
}
},1000);
</script>
|
子页面:
代码如下 |
复制代码 |
<h1>RRRRRR</h1>
<script>
var url = 'http://www.xxx.com/father.html';
oldHash = self.location.hash,
newHash,
interval = window.setInterval(function(){
newHash = self.location.hash;
if(oldHash != self.location.hash) {
document.getElementsByTagName('h1')[0].innerHTML = 'pp';
//alert(parent.location.href); //去掉这个注释,浏览器会提示无权限
parent.location.href = url + '#b';
window.clearInterval(interval);
}
},500);
</script>
|
小结:
•1 经测试 IE6, IE7, IE8, Firefox2.0, Firefox3.0, Firefox3.6, Chrome8, Opera11, Safari5, 除 IE6, IE7 外只要改变 hash 就会记录在浏览器 history 中。
•2 我有试图在子页面用 parent.location.replace 的方法来避免父页面向服务器发送请求而进行跳转,这样理论上浏览器就不会记录历史,但未能奏效。
•2 子页面无权读取父页面的 url, 但可以对父页面的 url 进行写操作,所以跨域操作时,要提前得知父页面的url
iframe自适应,跨域,JS的document.domain
判断子页面的域是否与父页面的域相同:
代码如下 |
复制代码 |
document.domain == parent.document.domain
|
关于iframe的自适应,跨域可以参考下面步骤:
1.在父窗口加上document.domain(也就是调用IFRAME的那个窗口)
1 //如“www.a.com”中的"a.com"
代码如下 |
复制代码 |
document.domain = "a.com";
|
2.在子窗口加上下边代码(也就是IFRAME本身里边)
代码如下 |
复制代码 |
function iframeAutoFit()
{
try
{
if(window!=parent)
{
var a = parent.document.getElementsByTagName("iframe");
for(var i=0; i<a.length; i++)
{
if(a[i].contentWindow==window)
{
var h1=0, h2=0, d=document, ddd=d.documentElement;
a[i].parentNode.style.height = a[i].offsetHeight +"px";
a[i].style.height = "10px";
if(dd && dd.scrollHeight) h1=dd.scrollHeight;
if(d.body) h2=d.body.scrollHeight;
var h=Math.max(h1, h2);
if(document.all){h += 4;}
if(window.opera){h += 1;}
a[i].style.height = a[i].parentNode.style.height = h +"px";
}
}
}
}
catch (ex){}
}
if(window.attachEvent)
{
window.attachEvent("onload", iframeAutoFit);
}else if(window.addEventListener)
{
window.addEventListener('load', iframeAutoFit, false);
}
|
3.细节问题 IFRAME外边加个DIV,否则火狐下有问题,宽度设置好 否则它们都有问题
代码如下 |
复制代码 |
<div style="width:100%;margin:0 0 10px 0;">
<iframe align='middle' src='http://comments.cnmo.com/iframe_comment.php?kindid=9&articleid=<?=$pic_id?>&tw=620&style=11&font_num=180&pagesize=3' frameborder='0' marginwidth='0' marginheight='0' width='100%' scrolling='no' height='450px' style='margin-top:15px;'></iframe>
</div>
|
OK 了。
frame/iframe 架构的网站中js弹出浮层记录
核心:取得DOM最底层的对象,然后再往下去对象[想要弹出浮层的那个frame/iframe],再往后的操作就跟非框架的一样了。
HTML代码:
代码如下 |
复制代码 |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>frame/iframe架构中js弹出浮层</title>
</head>
<body>
<frameset rows="64,*,64" frameborder="no" border="0" framespacing="0">
<noframes>
<body>你的浏览器不支持框架,所以无法使用本系统,建议你升级浏览器版本或者使用其它浏览器。</body>
</noframes>
<frame src="header.html" name="headerFrame" noresize="noresize" frameborder="no" scrolling="no" marginwidth="0" marginheight="0" target="main" />
<frameset cols="200,*" id="frame">
<frame src="left.html" name="leftFrame" noresize="noresize" marginwidth="0" marginheight="0" frameborder="0" scrolling="no" target="main" />
<frame src="right.html" name="main" marginwidth="0" marginheight="0" frameborder="0" scrolling="auto" target="_self" />
</frameset>
<frame src="footer.html" name="footerFrame" noresize="noresize" frameborder="no" scrolling="no" marginwidth="0" marginheight="0" target="main" />
</frameset>
</body>
</html> |
如上边的页面布局,我们要在id为main的frame里弹出一个浮层以展示相关信息。
弹出浮层JS代码:
代码如下 |
复制代码 |
function popShow() {
var mainFrame = window.top.main.document;
var bkg = mainFrame.getElementById("pop_bkg"); // 取得浮层那个透明背景对象
if(bkg==null) { //不存在则新建
bkg = mainFrame.createElement("div");
bkg.className = "pop_bkg";
bkg.id = "pop_bkg";
mainFrame.body.appendChild(bkg);
}
var pop_div = mainFrame.getElementById("pop_addr_div"); // 取得显示信息的那个Div对象
if(pop_div == null){//不存在则新建
pop_div = mainFrame.createElement("pop_addr_div");
pop_div.id = "pop_addr_div";
mainFrame.body.appendChild(pop_div);
}
bkg.style.display = "block";
pop_div.style.display = "block";
}
|
这样就可以正常的弹出个浮层了。 |