Tag Archives: iframe

跨域iframe自适应高度

这个可能是一个老生常谈的问题了,搜索google和百度应该也是文章大把大把的;处理方式也大同小异,今天又有哥们问这个问题,所以还是将自己的处理方式写出来。

最早遇到这个问题是07年在Yahoo的时候,当时SNS盛行,Yahoo也决定做SNS,其中就有应用是iframe模式的,但是iframe的页面在对方服务器上,使用的也是别人的域名,Yahoo也不可能给对方提供二级或三级域名;那就遇到一个问题,怎样去调整iframe的高度,让他做到自适应;大家都知道JS为了安全,是不能跨域执行的,所以只能通过其他方式实现;感谢克军同学当时给的建议。

下面具体说说怎么实现吧。

首先因为iframe是跨域的,所以不能直接用JS来控制,只能通过一个中间键,我们这里选择在iframe的页面(页面B)中再iframe一个父页面(页面A)同域的页面(页面C);这样页面C就能和页面A进行无障碍的通讯了;因为页面B iframe 页面C,所以页面B可以改写页面C的href值;到这里大家应该看明白啥意思了,来张图说明下:
iframe

A页面中的内容

A页面主要就是接收C页面传过来的内容并且去完成相应的操作。可能有人会说直接C页面来操作不就可以了?但是那样处理不太好,因为可能A页面中还有很多其他的公共方法,比如美化过的Alert等,所以如果能做一个公共的方法来接收C页面传过来的值会更加方便之后的框架调整,而且也不建议总是去修改页面C。

<iframe id="ifr" src="iframe_b.html" height="200" width="400"></iframe>
<script type="text/javascript">
var ifr_el = document.getElementById("ifr");
function getIfrData(data){
    ifr_el.style.height = data+"px";
}
</script>

B页面中的内容

B页面的主要内容当然是怎么把值传递给C页面,前面说了是将值传递到C页面的href中,所以只要修改iframe的src就可以,因为不用刷新C页面,所以可以用过hash的方式传递给C页面

<div id="box">
	<button id="btn_auto" type="button">Height Auto: off</button>
	<button id="btn_plus10" type="button">Height +10px</button>
	<button id="btn_minus10" type="button">Height -10px</button>
</div>
<iframe id="ifr" src="iframe_c.html" width="0" height="0"></iframe>
<script type="text/javascript">
var box_el = document.getElementById("box"),
    btn_auto_el = document.getElementById("btn_auto"),
    btn_plus10_el = document.getElementById("btn_plus10"),
    btn_minus10_el = document.getElementById("btn_minus10"),
    ifr_el = document.getElementById("ifr");

var isAuto = false,
    oldHeight = 0,
    ifrSrc = ifr_el.src.split("#")[0];

btn_auto_el.onclick = function(){
	if(!isAuto){
		isAuto = true;
		btn_auto_el.innerHTML = "Height Auto: on";
	}else{
		isAuto = false;
		btn_auto_el.innerHTML = "Height Auto: off";
	}
}
btn_plus10_el.onclick = function(){
	var height = box_el.offsetHeight;
	box_el.style.height = (10+height)+"px";
}
btn_minus10_el.onclick = function(){
	var height = box_el.offsetHeight;
	box_el.style.height = (height-10)+"px";
}
setInterval(function(){
	if(isAuto){
		var height = document.body.scrollHeight;
		height += 20;
		if(oldHeight != height){
			oldHeight = height;
			ifr_el.src = ifrSrc+"#"+oldHeight;
		}
	}
}, 200);
</script>

C页面中的内容

C页面的唯一功能就是接收B页面通过href传进来的值并且传递给A页面,可到B页面传来的值可以通过一个定时器不停去查看location.href是否被改变,但是这样感觉效率很低,还有个方式就是在新的浏览器中通过onhashchange事件(IE8+,Chrome5.0+,Firefox3.6+,Safari5.0+,Opera10.6+)来监听href的改变。

<script type="text/javascript">
var oldHeight = 0;

setInterval(function(){
	var height = location.href.split("#")[1];
	if(height && oldHeight != height){
		oldHeight = height;
		if(window.parent.parent.getIfrData){
			window.parent.parent.getIfrData(oldHeight);
		}
	}
}, 200);
</script>

高度应用只是iframe跨域传值中最简单也是最常见应用,其实能扩展出很多其他的需求,之前在Yahoo的项目中就将iframe中的弹出框操作也传递到了外面,以保证样式的统一和页面的全遮盖。

最后举个“栗子”,演示请看http://www.honglei.net/demo/iframe_a.html