`
yushine
  • 浏览: 196972 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

三谈iFrame框架自适应高度

 
阅读更多

为什么是三谈

为什么是三谈呢?一是因为这真的是一个被说烂的话题,二是因为太师傅在n年前就写过这篇再谈iframe自适应高度 。之所以再提该问题,是因为之前项目中确实遇到了这个问题的方方面面,有必要总结一下。希望对各位有帮助,有错误请指正。

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

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

  1. 如果页面内有绝对定位或者没有清浮动的元素,情况有些复杂,不同浏览器处理结果不同,甚至包括Webkit内核的浏览器,具体请看这个Demo 。所以你要么进行浏览器检测,要么用Math.max 计算一个最大值,要么你想别的方法。
  2. iframe 所包含页面可能非常大,需要很长的加载时间,为此直接计算高度的时候,很可能页面还没下载完,高度计算就会有问题。所以最好在iframe onload 事件中计算高度。这里还要注意的是,IE下必须使用微软事件模型obj.attachEvent 来绑定onload 事件。而别的浏览器直接obj.onload = function(){} 也可以。

(function(){
    var frame = document.getElementById("frame_content_parent"),
        setIframeHeight = function(){
            var frameContent = frame.contentWindow.document,
                frameHeight = Math.max(frameContent.body.scrollHeight,frameContent.documentElement.scrollHeight);

            frame.height = frameHeight;
        };
    if(frame.addEventListener){
        frame.addEventListener("load",setIframeHeight,false);
    }else{
        frame.attachEvent("onload",setIframeHeight);
    }
})();

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

原理与第一种情况一样,多一个计时器,一直检测字页面高度,当子页面高度和iframe 的高度不一致时,重新设置iframe 的高度。这边也可以加一个try 在js出错时,加一个足够的高度。


(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);
    }
})();

跨域

这里提供一个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 = "http://demo.zhouqicf.com/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 = "http://demo.zhouqicf.com/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 = "http://demo.zhouqicf.com/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 属性上增加一个随机数的参数就行了。比如http://demo.zhouqicf.com/js/2010/iframe_height/agent_iframe.html?temp=123123423712937#1563


//B页面关键脚本
agent_iframe.src = "http://demo.zhouqicf.com/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 框架自适应被嵌入页面高度

    js控制 Iframe 框架自适应被嵌入页面高度

    iframe自适应宽高

    这个库允许的高度与同跨域iframe来适应他们所包含的内容的宽度自动调整大小。它最常见的问题与使用iframes提供一系列的功能,其中包括: 高度和宽度大小的iframe内容大小。 作品以多个嵌套的iframe。 跨域iframe域...

    JAVASCRIPT让IFRAME框架的高度自适应

    JAVASCRIPT让IFRAME框架的高度自适应

    js实现iframe自动自适应高度的方法

    主要介绍了js实现iframe自动自适应高度的方法,涉及javascript操作iframe框架的技巧,非常具有实用价值,需要的朋友可以参考下

    Iframe框架高度自适应的实现.doc

    Iframe框架高度自适应的实现.doc

    .net 网页的布局框架 iframe自适应高度 js设置链接样式

    网站实现了网页的布局,左边固定,点击左边的链接,在右边显示相应信息,iframe自适应高度,用js更改链接样式。网站是本人在练习的时候弄的,页面简单,功能实现了。看了就明白了。 vs2005的

    iframe自适应高度(兼容目前所有主浏览器)

    iframe自适应高度(兼容目前所有主浏览器)

    JQuery IFrame框架高度自适应(支持嵌套–兼容IE,ff,safafi,chrome)

    NULL 博文链接:https://z-one.iteye.com/blog/1725511

    iframe框架使用(完美版)

    iframe使用 自适应高度 封装js

    JS实现iframe自适应高度的方法示例

    本文实例讲述了JS实现iframe自适应高度的方法。分享给大家供大家参考,具体如下: <iframe id="mainFrame" name="mainFrame" src="/zwgk/hsearchview" width="740" frameborder="0" scrolling="no" scrolling=...

    关于IFRAME 自适应高度的研究

    关于IFRAME 自适应高度的研究——之前自己也碰到过这个问题,为了得到答案去网上搜索,发现有不少人也遇到了这样的问题,现在就把解决方法共享一下。 重要提示:src=中你必须填写的网页地址,一定要和本页面在同一...

    自适应高度框架 —-属个人收藏内容

    main.htm: <... <head> <... charset=gb2312′ /> <... <...iframe自适应加载的页面高度</title> </head> <body> <div><iframe src=”child.htm”></i

    基于jquery的兼容各种浏览器的iframe自适应高度的脚本

    就是绑定事件必须在iframe加载完毕之前绑定,否则不会执行。 以下是jQuery,load事件的概述 在每一个匹配元素的load事件中绑定一个处理函数。 如果绑定给window对象,则会在所有内容加载后触发,包括窗口,框架,对象...

    iframe标签用法详解(属性、透明、自适应高度)

    iframe 元素会创建包含另外一个文档的内联框架(即行内框架)。 HTML 与 XHTML 之间的差异 在 HTML 4.1 Strict DTD 和 XHTML 1.0 Strict DTD 中,不支持 iframe 元素。 提示和注释: 提示:您可以把需要的文本...

    artDialog_Demo

    25、可以自适应iframe内容的大小(不跨域的前提下) 26、对超过预设面积大小的对话框拖动自动采用替身的方式,以求拖动更流畅 27、新增加一个'data'的接口,它保存了你对话框每次创建的消息对象 (操作iframe消息...

    ExtAspNet v2.2.1 (2009-4-1) 值得一看

    -修正Form不能自适应浏览器大小的改变(feedback:kaywood)(WorkItem#6309)。 -增加重载方法Alert.Show(message, title, icon)(feedback:TheBox)(WorkItem#6353)。 -为容器控件(比如Panel,Region,Tab等)增加AJAX...

    ExtAspNet_v2.3.2_dll

    -修正Form不能自适应浏览器大小的改变(feedback:kaywood)(WorkItem#6309)。 -增加重载方法Alert.Show(message, title, icon)(feedback:TheBox)(WorkItem#6353)。 -为容器控件(比如Panel,Region,Tab等)增加AJAX...

    《程序天下:JavaScript实例自学手册》光盘源码

    5.6 动态添加iframe框架 5.7 用层实现长文章分页 5.8 iframe自适应高度 5.9 类似MSN的消息提示 5.10 只打印iframe的内容 第6章 下拉列表特效 6.1 下拉框实现多选 6.2 实现两个select的同步 6.3 被选中的列表项下次不...

    程序天下:JavaScript实例自学手册

    5.6 动态添加iframe框架 5.7 用层实现长文章分页 5.8 iframe自适应高度 5.9 类似MSN的消息提示 5.10 只打印iframe的内容 第6章 下拉列表特效 6.1 下拉框实现多选 6.2 实现两个select的同步 6.3 被选中的列表项下次不...

    超实用的jQuery代码段

    1.15 实现iframe高度自适应 1.16 实现左右div自适应相同高度 1.17 获取鼠标在屏幕中的坐标 1.18 获取鼠标在窗口客户区中的坐标 1.19 获取鼠标在窗口页面中的坐标 1.20 设置Flash对象的WMode窗口模式 1.21 实现类...

Global site tag (gtag.js) - Google Analytics