Iframe跨域 自适应高度

一:背景:  

现在有在www.a.com域下的main.html,要在其内引入www.b.com下的b.html页面

二:思路:

         现有主界面main在域a下,被嵌套页面b在域b下,被嵌套页面b又嵌套一个在域a下的中介页面c。当用户打开浏览器访问mail.html的时候载入b,触发b的onload事件获取其自身高度,然后b载入c并将高度值作为参数赋值给c的location对象。这样c就可以通过location.hash获得b的高度,然后将获取到的b的高度传给main,然后修改b的高度。

三:实现:

  1. 在b通过脚本随机插入文本,模拟一个高度不断变化的页面。
  2. 在main中嵌入b:
    <iframe src="B.html" name="iframeb" id="iframeb" width="500" scrolling="no" frameborder="0" style="border:1px solid #F00;">
  3. 在b页面插入隐藏的与main同域的中间页c,并获取自身高度作为参数赋值给location对象。
    <script type="text/javascript">
    var Midname = "iframec";
    function sethash(){
       hashH = document.body.scrollHeight+16; //获取自身高度
       urlC = "c.html"; //设置iframec的src
        	document.getElementById("iframec").src=urlC+"#"+hashH+"px"; //将高度作为参数传递
    }
    window.onload = function () {
        setTimeout(function(){
            setInterval(function () { 
                 sethash();
            }, 300);
        },0);
    document.write('<iframe name="' + Midname + '" id="' + Midname + '" src="" style="display:none;"></iframe>');
    }(window.onload); 
    </script>
    

    注意:1. 这里获取b自身高度用的是document.body.scrollHeight而不是用的document.documentElement.scrollHeight,是因为在设置iframe的scrolling=”no”的前提下,当改变b内容的高度,当高度增加的时候,它们获取的高度相等,但是当b内容的高度减少的时候,后者获取的高度不会减少,这样会出现当b内容减少时,main页面的高度无法自适应减少。

               如果设置scrolling=”yes”,这样通过document.documentElement.scrollHeight会减小,但是会慢慢减少,这样当b页面内容减少的时候,在main页面会看到iframeb的高度慢慢减少,达不到预期的效果。

         2. 当页面载入的时候用了setTimeout(sethash(),0)来调用sethash。

    四:问题

             分析 document.bodydocument.doucmentElement的区别

    1. document.body是DOM中Document对象里的body节点, document.documentElement是文档对象根节点(html)的引用。
    2. IE在怪异模型(quick mode)下document.documentElement无法正确取到clietHeight scrollHeight等值,比如clietHeight=0。(暂不讨论)
    3. document.body.scrollHeight是body元素的滚动高 度,document.documentElement.scrollHeight为页面的滚动高度,且 document.documentElement.scrollHeight在IE和Firefox下还有点小差异。
      IE : document.documentElement.scrollHeight = document.body.scrollHeight + marginTop bottom高度 + 上下border宽度
      firefox : document.documentElement.scrollHeight = document.body.scrollHeight + marginTop bottom高度
    4. 一个是DOMDocument对象里的body子节点,一个是整个节点树的根节点root。

    使用setTimeout(sethash(),0)的作用:

     

    1、实现javascript的异步;
               正常情况下javascript都是按照顺序执行的。但是我们可能让该语句后面的语句执行完再执行本身,这时就可以用到setTimeout延时0ms来实现了。
    如:
               alert(1);
               setTimeout("alert(2)", 0);
               alert(3);
               虽然延时了0ms,但是执行顺序为:1,3,2
               这样就保证setTimeout里面的语句在某一代码段中最后执行。 

     

             在上面的例子中:document.write('<iframe name="' + Midname + '" id="' + Midname + '" src="" style="display:none;"></iframe>')插入隐藏的c写在了调用sethash后面,以JavaScript 引擎的单线程处理方式,会先调用sethash函数,这时用document.getElementById("iframec")去获取c就会出错。

             2. 在事件中,setTimeout 会在其完成当前任何延宕事件的事件处理器的执行,以及完成文档当前状态更新后,告诉浏览器去启用 setTimeout 内注册的函数。比如:现有一个事件在页面上添加一个input框,并给它赋值(文档更新完成前),然后聚焦到文本框,并选中。这时因为现有的 JavaScript 引擎是单线程处理任务的。它把任务放到队列中,不会同步去执行,必须在完成一个任务后才开始另外一个任务。当事件触发时,由于没有多线程的同步执行,不可能同时去处理刚创建的元素的聚焦和选中,所以这两个不在队列中的任务将被丢弃。使用setTimeout,可以将这两个任务抽离出来形成新的队列,从而达到预期的效果。

     

posted @ 2013-01-14 15:20  ~小章鱼~  阅读(456)  评论(0编辑  收藏  举报