同域、子頁面高度不會動態(tài)增加
這種情況最簡單,直接通過腳本獲取字頁面實際高度,修改iframe元素高度即可。但有二點必須注意:
如果頁面內(nèi)有絕對定位或者沒有清浮動的元素,情況有些復(fù)雜,不同瀏覽器處理結(jié)果不同,甚至包括Webkit內(nèi)核的瀏覽器,具體請看這個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);}); } })(); |
從上面這個Demo可以看到,除IE瀏覽器外,別的瀏覽器計算出來的都是iframe的高度,即CSS里設(shè)置的#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代理的方法,簡單地說一下原理。假設(shè)有3個頁面,分別是主頁面A.html,字頁面B.html,代理頁面C.html。其中A與B是跨域的,而A和C是同域的。它們的關(guān)系: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節(jié)點,然后設(shè)置它的src屬性,在這個地址上附加一個參數(shù),即B頁面計算出來的高度,然后C頁面就可以通過window.location獲取這個地址欄中的地址,提取出高度值,通過window.top找到A頁面,設(shè)置A頁面的Iframe的高度。基本的原理就是這樣,看代碼吧:
DEMO
//B頁面腳本 //任務(wù):計算其實際高度,然后生成一個iframe節(jié)點,將高度作為代理頁面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頁面腳本 //任務(wù):獲取請求地址中的高度值,將其賦值給A頁面的Iframe的高度 window.top.document.getElementById("frame_content_parent").height = parseInt(window.location.hash.substring(1),10); |
跨域、字頁面高度動態(tài)變化
這里結(jié)合了第2、第4兩種方法,我的想法是在B頁面通過一個計時器,不停計算B頁面的高度,一但變化,馬上修改iframe標(biāo)簽的src屬性,而C頁面也有計時器不斷監(jiān)聽src的變化,改變Aiframe標(biāo)簽的高度。需要注意的是僅僅修改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次計算高度重復(fù)的話,就會導(dǎo)致src屬性的值相同,這樣瀏覽器就很可能不重新請求該頁面了,那么C頁面中的腳本也就不運行了。要修復(fù)這個問題很簡單,只要在每次計算出來的src屬性上增加一個隨機數(shù)的參數(shù)就行了。比如http://demo.zhouqicf.com/js/2010/iframe_height/agent_iframe.html?temp=123123423712937#1563
//B頁面關(guān)鍵腳本 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); |