跨域Iframe高度自适应
Published at 7 months ago
在CSS Trick上面看到了一篇讲跨域Iframe调整的文章,DEMO在这里。要做到跨域Iframe高度自适应,需要可以控制两个域内的内容,主要的技术是通window.location.hash来传递信息。 先来看看主域的内容:<iframe id="frame-one" scrolling="no" frameborder="0" src="http://digwp.com/examples/iFrameSource/source.html" onload="FrameManager.registerFrame(this)"></iframe>
放置一个需要高度自适应的Iframe,onload时会调用一个函数,这个函数在下面的这个js里面
<script type="text/javascript" src="js/FrameManager.js"></script>,这个js的内容如下:
var FrameManager = {
currentFrameId : '',
currentFrameHeight : 0,
lastFrameId : '',
lastFrameHeight : 0,
resizeTimerId : null,
init: function() {
if (FrameManager.resizeTimerId == null) {
FrameManager.resizeTimerId = window.setInterval(FrameManager.resizeFrames, 500);
}
},
resizeFrames: function() {
FrameManager.retrieveFrameIdAndHeight();
if ((FrameManager.currentFrameId != FrameManager.lastFrameId) || (FrameManager.currentFrameHeight != FrameManager.lastFrameHeight)) {
var iframe = document.getElementById(FrameManager.currentFrameId.toString());
if (iframe == null) return;
iframe.style.height = FrameManager.currentFrameHeight.toString() + "px";
FrameManager.lastFrameId = FrameManager.currentFrameId;
FrameManager.lastFrameHeight = FrameManager.currentFrameHeight;
window.location.hash = '';
}
},
retrieveFrameIdAndHeight: function() {
if (window.location.hash.length == 0) return;
var hashValue = window.location.hash.substring(1);
if ((hashValue == null) || (hashValue.length == 0)) return;
var pairs = hashValue.split('&');
if ((pairs != null) && (pairs.length > 0)) {
for(var i = 0; i < pairs.length; i++) {
var pair = pairs[i].split('=');
if ((pair != null) && (pair.length > 0)) {
if (pair[0] == 'frameId') {
if ((pair[1] != null) && (pair[1].length > 0)) {
FrameManager.currentFrameId = pair[1];
}
} else if (pair[0] == 'height') {
var height = parseInt(pair[1]);
if (!isNaN(height)) {
FrameManager.currentFrameHeight = height;
FrameManager.currentFrameHeight += 15;
}
}
}
}
}
},
registerFrame: function(frame) {
var currentLocation = location.href;
var hashIndex = currentLocation.indexOf('#');
if (hashIndex > -1) {
currentLocation = currentLocation.substring(0, hashIndex);
}
frame.contentWindow.location = frame.src + '?frameId=' + frame.id + '#' + currentLocation;
}
};
window.setTimeout(FrameManager.init, 300);
这个js里面会连续不断地执行resizeFrames这个函数,这个函数就是获得浏览器hash的值,如果有值的话就调整iframe的高度
再来看看iframe里面的内容:
<script type="text/javascript" src="frame.js"></script>
<script type="text/javascript">
window.onload = function(event) {
window.setInterval(publishHeight, 300);
}
</script>
需要引入一段js,然后每隔一定的时间调用一个publishHeight函数,这个js的内容如下:
function publishHeight() {
if (window.location.hash.length == 0) return;
var frameId = getFrameId();
if (frameId == '') return;
var actualHeight = getBodyHeight();
var currentHeight = getViewPortHeight();
if (Math.abs(actualHeight - currentHeight) > 15) {
var hostUrl = window.location.hash.substring(1);
hostUrl += "#";
hostUrl += 'frameId=' + frameId;
hostUrl += '&';
hostUrl += 'height=' + actualHeight.toString();
window.top.location = hostUrl;
}
}
function getFrameId() {
var qs = parseQueryString(window.location.href);
var frameId = qs["frameId"];
var hashIndex = frameId.indexOf('#');
if (hashIndex > -1) {
frameId = frameId.substring(0, hashIndex);
}
return frameId;
}
function getBodyHeight() {
var height,
scrollHeight,
offsetHeight;
if (document.height) {
height = document.height;
} else if (document.body) {
if (document.body.scrollHeight) {
height = scrollHeight = document.body.scrollHeight;
}
if (document.body.offsetHeight) {
height = offsetHeight = document.body.offsetHeight;
}
if (scrollHeight && offsetHeight) {
height = Math.max(scrollHeight, offsetHeight);
}
}
return height;
}
function getViewPortHeight() {
var height = 0;
if (window.innerHeight) {
height = window.innerHeight - 18;
} else if ((document.documentElement) && (document.documentElement.clientHeight)) {
height = document.documentElement.clientHeight;
} else if ((document.body) && (document.body.clientHeight)) {
height = document.body.clientHeight;
}
return height;
}
function parseQueryString(url) {
url = new String(url);
var queryStringValues = new Object(),
querystring = url.substring((url.indexOf('?') + 1), url.length),
querystringSplit = querystring.split('&');
for (i = 0; i < querystringSplit.length; i++) {
var pair = querystringSplit[i].split('='),
name = pair[0],
value = pair[1];
queryStringValues[name] = value;
}
return queryStringValues;
}
publishHeight这个函数会不但地将iframe的高度通过hash传给顶级窗口,看红色标示部分,这样父窗口就可以获得hash的值,很关键。
了解更多请看:
http://css-tricks.com/cross-domain-iframe-resizing/
http://geekswithblogs.net/rashid/archive/2007/01/13/103518.aspx
http://adamfortuna.com/2009/09/30/resize-a-crossdomain-iframe/
http://blog.johnmckerrell.com/2006/10/22/resizing-iframes-across-domains/