背景说明:我开发了一个页面框架,里面通过Iframe嵌入第三方应用。但第三方应用有多个,页面高度不一样,而且在使用过程中还会动态变化。我外面Iframe的高度就要跟随里面的应用来变化。
这样就要求第三方应用页面高度变化时要控制外围Iframe的高度跟随变化,但直接的js控制是行不通的,因为第三方应用和我的框架在不同域,浏览器因为安全原因会禁止应用通过js控制外面框架的DOM对象。同理,外围框架也不能控制Iframe内应用的DOM对象。
要实现真正的跨域调用,必须通过一个代理页面来实现。原理如下:
存在3个页面,http://frame.com/frame.html:我的框架页面
http://app.com/app.html:第三方应用的页面
http://frame.com/agent.html:代理页面
注意,框架页面和代理页面必须是同一个域的,这样才能通过代理页面控制框架而绕过安全限制。
这样我们就可以在app.html中获取页面的高度,然后通过 agent.html#hash的机制把高度传递给agent.html页面,最后在agent.html页面中获取高度然后调整frame.html中Iframe的高度。这就有个前提,要求你可以修改app.html,或者可以要求app.html做些修改。为了方便第三方修改,我在一个agent.js中实现了这些修改,第三方应用只要引用这个js就可以了。
agent.js代码如下:
function sethash(){
var oldHash=0;
var urlC = "http://frame.com/agent.html";
var iframe=document.createElement('iframe');
iframe.id="iframeC"
iframe.name="iframeC";
iframe.width=0;
iframe.height=0;
iframe.style.display="none";
document.body.appendChild(iframe);
//document.body.innerHTML+='<iframe id="iframeC" name="iframeC" src=\'#\'" width="0" height="0" style="display:none;" ></iframe>';
setInterval(function(){
var bHeight = document.body.scrollHeight;
var dHeight = document.documentElement.scrollHeight;
var oHeight = document.body.offsetHeight;
var hashH =Math.min(oHeight,Math.min(bHeight,dHeight));
if(oldHash!=hashH){
document.getElementById("iframeC").src=urlC+"?"+Math.random()+"#"+hashH;
}
oldHash=hashH;
},200);
}
if(window.addEventListener){
window.addEventListener("load",sethash,false);
}else{
window.attachEvent("onload",sethash);
}
agent.html代码如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><title>frame agent</title></head>
<body>
<script type="text/javascript">
function pseth() {
var iObj = parent.parent.document.getElementById('frame_cont');
iObjH = window.location.hash;
//iObjH = parent.parent.frames["frame_cont"].frames["iframeC"].location.hash;
iObj.style.height = iObjH.split("#")[1]+"px";
}
pseth();
</script>
</body>
</html>
这里有几个需要注意的地方
1、agent.js中创建隐藏的iframe要使用DOM函数操作,不能用innerhtml,在IE等浏览器上用innerhtml会导致一些绑定的js事件失效。
2、在设置定时器重新调用agent.html时需要带随机数参数,不然有些浏览器由于缓存会不调用。
3、在app.html中调用agent.js,
<script type="text/javascript" src="http://frame.com/setHash.js"></script>