网站地图    收藏   

主页 > 前端 > javascript >

iframe自动适应高度几个实例(支持:跨域)

来源:自学PHP网    时间:2014-09-19 14:47 作者: 阅读:

[导读] iframe自动适应高度是我们开发中会碰到的一些问题,但做起来兼容性问题是iframe自动适应高度几个难题了,特别是跨域自动适应高度时,几乎没有更好的解决办法了,下面小编来给大家...

同域、子页面高度不会动态增加

这种情况最简单,直接通过脚本获取字页面实际高度,修改iframe元素高度即可。但有二点必须注意:

如果页面内有绝对定位或者没有清浮动的元素,情况有些复杂,不同浏览器处理结果不同,甚至包括Webkit内核的浏览器,具体请看这个Demo。所以你要么进行浏览器检测,要么用Math.max计算一个最大值,要么你想别的方法。

iframe所包含页面可能非常大,需要很长的加载时间,为此直接计算高度的时候,很可能页面还没下载完,高度计算就会有问题。所以最好在iframe的onload事件中计算高度。这里还要注意的是,IE下必须使用微软事件模型obj.attachEvent来绑定onload事件。而别的浏览器直接obj.onload = function(){}也可以。

 代码如下 复制代码

(function(){
    var _reSetIframe = function(){
        var frame = document.getElementById("frame_content_parent")
        try {
            var frameContent = frame.contentWindow.document,
                bodyHeight = Math.max
(frameContent.body.scrollHeight,
frameContent.documentElement.scrollHeight);
            if (bodyHeight != frame.height){
                frame.height = bodyHeight;
            }
        }
        catch(ex) {
            frame.height = 1800;
        }
    }
    if(frame.addEventListener){
        frame.addEventListener
("load",function(){setInterval(_reSetIframe,200);},false);
    }else{
        frame.attachEvent("onload",function(){setInterval(_reSetIframe,200);});
    }
})();

同域、子页面高度会动态增加、脚本可能完全失效

第二个例子中,考虑到了脚本出错的情况,但是万一脚本根本不执行了呢,那iframe中的内容就会因为iframe的高度不够而显示不了。为此我们通常事先设置一个足够的高度,为了前端控制方便,我觉得写在CSS文件中比较合适,需要修改时只改CSS就行了。这里我设置了selector{ height:1800px; }。需要注意的是,写在样式表里的样式,不能直接用node.style[property]来取,对于微软模型,要用node.currentStyle[property](题外话:悲剧的IE模型不支持CSS伪类),对于W3C模型,要用window.getComputedStyle(node,null)[property]来取。我这里图方便直接用了YUI。

这里又有一个问题,设置iframe的高度大于其包含页面的高度时,各个浏览器的处理不一样。例如在Firefox下,必须计算body元素的高度,而html元素的高度等于iframe的高度,然而当恰巧这个页面又有绝对定位、未清浮动元素时,又不能通过body元素来取,显然第一种方法缺点更小一些。具体请看这个Demo。

从上面这个Demo可以看到,除IE浏览器外,别的浏览器计算出来的都是iframe的高度,即CSS里设置的#frame_content_parent{ height:1800px; }。而IE计算出来的是iframe所引用页面的实际高度。

 代码如下 复制代码

#frame_content_parent{ height:1800px; }
(function(){
    var $ = YAHOO.util.Dom,
        frame = $.get("frame_content_parent");
    function reSetIframe(){
        var frameContent = frame.contentWindow.document,
            bodyHeight = Math.max
(frameContent.documentElement.scrollHeight,
frameContent.body.scrollHeight);
        if (bodyHeight != $.getStyle(frame, "height")){
            $.setStyle(frame, "height", bodyHeight + "px");
        }
    }
    if(frame){
        $.setStyle(frame,"height","auto");
        setInterval(reSetIframe,300);
    }
})();

再看一个实例

 代码如下 复制代码

<script type="text/javascript">
//** iframe自动适应页面 **//
//输入你希望根据页面高度自动调整高度的iframe的名称的列表
//用逗号把每个iframe的ID分隔. 例如: ["myframe1", "myframe2"],可以只有一个窗体,则不用逗号。
//定义iframe的ID
var iframeids=["test"]
//如果用户的浏览器不支持iframe是否将iframe隐藏 yes 表示隐藏,no表示不隐藏
var iframehide="yes"
function dyniframesize()
{
var dyniframe=new Array()
for (i=0; i<iframeids.length; i++)
{
if (document.getElementById)
{
//自动调整iframe高度
dyniframe[dyniframe.length] = document.getElementById(iframeids);
if (dyniframe && !window.opera)
{
dyniframe.style.display="block"
if (dyniframe.contentDocument && dyniframe.contentDocument.body.offsetHeight) //如果用户的浏览器是NetScape
dyniframe.height = dyniframe.contentDocument.body.offsetHeight;
else if (dyniframe.Document && dyniframe.Document.body.scrollHeight) //如果用户的浏览器是IE
dyniframe.height = dyniframe.Document.body.scrollHeight;
}
}
//根据设定的参数来处理不支持iframe的浏览器的显示问题
if ((document.all || document.getElementById) && iframehide=="no")
{
var tempobj=document.all? document.all[iframeids] : document.getElementById(iframeids)
tempobj.style.display="block"
}
}
}
if (window.addEventListener)
window.addEventListener("load", dyniframesize, false)
else if (window.attachEvent)
window.attachEvent("onload", dyniframesize)
else
window.onload=dyniframesize
</script>

iframe自动适应高度跨域

这里提供一个Iframe代理的方法,简单地说一下原理。假设有3个页面,分别是主页面A.html,字页面B.html,代理页面C.html。其中A与B是跨域的,而A和C是同域的。它们的关系:A包含B,B包含C。很显然A和B,以及B和C,因为跨域不能相互通信,而A和C同域,可以相互通信。为此我们就想到让C页面告诉A页面,B页面到底有多少高。因为B和C也是跨域的不能相互通信,所以想在C页面中,直接window.parent.document.body.scrollHeight这样是行不通的,所以我们只能让B页面自己计算自身的高度,然后通过某种方法告诉C页面,再由C页面告诉A页面。这里的一个方法就是在B页面生成一个Iframe节点,然后设置它的src属性,在这个地址上附加一个参数,即B页面计算出来的高度,然后C页面就可以通过window.location获取这个地址栏中的地址,提取出高度值,通过window.top找到A页面,设置A页面的Iframe的高度。基本的原理就是这样,看代码吧:

DEMO

 代码如下 复制代码

//B页面脚本
//任务:计算其实际高度,然后生成一个iframe节点,将高度作为代理页面C的地址的一部分赋值给Src属性
(function(){
    var agent_iframe = document.createElement("iframe"),
        b_height = Math.max(document.documentElement.scrollHeight,document.body.scrollHeight);
    agent_iframe.src = "/js/2010/iframe_height/agent_iframe_once.html#" + b_height;
    document.body.appendChild(agent_iframe);
    agent_iframe.style.display = "none";
})();

//C页面脚本
//任务:获取请求地址中的高度值,将其赋值给A页面的Iframe的高度
window.top.document.getElementById("frame_content_parent").height = parseInt(window.location.hash.substring(1),10);

跨域、字页面高度动态变化

这里结合了第2、第4两种方法,我的想法是在B页面通过一个计时器,不停计算B页面的高度,一但变化,马上修改iframe标签的src属性,而C页面也有计时器不断监听src的变化,改变Aiframe标签的高度。需要注意的是仅仅修改src属性后面的锚点值(如“#1234”),页面并不会刷新,不会重新请求,这也是在C页面增加计时器的原因。

DEMO

 代码如下 复制代码

//B页面脚本
(function(){
    var getHeight = function(){
        return Math.max(document.documentElement.scrollHeight,document.body.scrollHeight);
    };
    var preHeight = getHeight(),
        agent_iframe;
    var createIframe = function(height){
        agent_iframe = document.createElement("iframe");
        agent_iframe.style.height = "0";
        agent_iframe.style.width = "0";
        agent_iframe.style.border = "none";
        agent_iframe.src = "/js/2010/iframe_height/agent_iframe.html#" + height;
        document.body.appendChild(agent_iframe);
    }
    createIframe(preHeight);
    var checkHeight = function(){
        var currentHeight = getHeight();
        if(currentHeight != preHeight){
            agent_iframe.src = "/js/2010/iframe_height/agent_iframe.html#" + currentHeight;
            preHeight = currentHeight;
        }
        setTimeout(checkHeight,500);
    }
    setTimeout(checkHeight,500);
})();

//C页面脚本
(function(){
    var preHeight = parseInt(window.location.hash.substring(1),10),
        ifrmae = window.top.document.getElementById("frame_content_parent");
    ifrmae.height = preHeight;
    setInterval(function(){
        var newHeight = parseInt(window.location.hash.substring(1),10);
        if (newHeight !== preHeight){
            ifrmae.height = newHeight;
            preHeight = newHeight;
        }
    },500);
})();

这里还有另一种方案,就是让iframe每一次都重新请求,这样C页面就不需要计时器了,但是如果2次计算高度重复的话,就会导致src属性的值相同,这样浏览器就很可能不重新请求该页面了,那么C页面中的脚本也就不运行了。要修复这个问题很简单,只要在每次计算出来的src属性上增加一个随机数的参数就行了。比如/js/2010/iframe_height/agent_iframe.html?temp=123123423712937#1563

 代码如下 复制代码

//B页面关键脚本
agent_iframe.src = "/js/2010/iframe_height/agent_iframe.html?a=" + Math.random() + "#" + currentHeight;

//C页面脚本
window.top.document.getElementById("frame_content_parent").height = parseInt(window.location.hash.substring(1),10);


上面都是网上整理的,下面把自己的一个批量自适应高度给各位拿出来

批量iframe自适应:

工作中遇到iframe随所含内容自适应高度的问题,以前在网上看到过类似问题的解决方法,于是搜索一下,找到了一个比较完整的能够兼容浏览器的解决方法,省得自己写了。
虽然不用自己写,思路还是要明白,基本上就是取得iframe属性src所指定的包含文档中内容的高度,然后用来设置iframe自身的高度,在iframe所在页面载入时对页面中的所有需要自适应高度的iframe进行自动设置,省时省力,如果确定页面中全部iframe都需要自适应高度,直接取得iframe数组给代码,就连ID都不用自己写了,完成程序搞定。(代码贴上来:)

 代码如下 复制代码
<script language="javascript">
//输入你希望根据页面高度自动调整高度的iframe的名称的列表
//用逗号把每个iframe的ID分隔. 例如: ["myframe1", "myframe2"],可以只有一个窗体,则不用逗号。
//定义iframe的ID
var iframeids=["test"];
//如果用户的浏览器不支持iframe是否将iframe隐藏 yes 表示隐藏,no表示不隐藏
var iframehide="yes";
function dyniframesize()
{
var dyniframe=new Array()
for (i=0; i<iframeids.length; i++)
{
if (document.getElementById)
{
//自动调整iframe高度
dyniframe[dyniframe.length] = document.getElementById(iframeids[i]);
if (dyniframe[i] && !window.opera)
{
dyniframe[i].style.display="block";
if (dyniframe[i].contentDocument && dyniframe[i].contentDocument.body.offsetHeight) //如果用户的浏览器是NetScape
dyniframe[i].height = dyniframe[i].contentDocument.body.offsetHeight;
else if (dyniframe[i].Document && dyniframe[i].Document.body.scrollHeight) //如果用户的浏览器是IE
dyniframe[i].height = dyniframe[i].Document.body.scrollHeight;
}
}
//根据设定的参数来处理不支持iframe的浏览器的显示问题
if ((document.all || document.getElementById) && iframehide=="no")
{
var tempobj=document.all? document.all[iframeids[i]] : document.getElementById(iframeids[i]);
tempobj.style.display="block";
}
}
}
if (window.addEventListener)
window.addEventListener("load", dyniframesize, false);
else if (window.attachEvent)
window.attachEvent("onload", dyniframesize);
else
window.onload=dyniframesize;
</script>


网上有人改进了方法,解决了当iframe所包含文档内容高度动态变化时自动调整iframe高度的问题,原理是在iframe所在页面不断扫描iframe包含文档的内容高度并改变iframe自身高度,这种方法貌似解决了问题,但是对页面速度和系统资源占用是否有影响还很难说,感觉方法有些偏执,应该有更好的解决方法。

自学PHP网专注网站建设学习,PHP程序学习,平面设计学习,以及操作系统学习

京ICP备14009008号-1@版权所有www.zixuephp.com

网站声明:本站所有视频,教程都由网友上传,站长收集和分享给大家学习使用,如由牵扯版权问题请联系站长邮箱904561283@qq.com

添加评论