1. 概述
1.1 問題描述
將報表整合至 Web 頁面中時,報表往往只是作為頁面的某一部分嵌入在一個框架中如 iframe 中顯示出來。
由於報表每頁資料是不定的,在最後一頁可能只有幾筆資料,此時 iframe 框架將留有大片的空白,造成空間的浪費也使得介面不美觀。
這個時候我們就會希望,要是 iframe 框架大小能夠根據報表頁面的內容自動調整高度或寬度,如下圖效果:
當頁面記錄數較少,此時 iframe 框架高度變小,如下圖:
1.2 實現思路
主要思路如下透過網頁載入結束事件監聽報表頁面的高度,進而設定所在 iframe 框架的高度,即可實現 iframe 框架高度根據報表內容來自適應了。
2. 操作步驟
2.1 實現翻頁功能
可參考 自定义翻页按钮
具體使用程式碼如下:
<div id="toolbar">
<input type="button" onclick="document.getElementById('reportFrame').contentWindow._g().gotoFirstPage();" value="首頁"></input>
<input type="button" onclick="document.getElementById('reportFrame').contentWindow._g().gotoPreviousPage();" value="上一頁"></input>
<input type="button" onclick="document.getElementById('reportFrame').contentWindow._g().gotoNextPage();" value="下一頁"></input>
<input type="button" onclick="document.getElementById('reportFrame').contentWindow._g().gotoLastPage();" value="末頁"></input>
</div>
2.2 新增監聽
我們需要獲取伺服器傳回給瀏覽器的頁面,因此需要新增一個監聽看瀏覽器是否已經將結果載入完畢。新增監聽的方法為contentPane.on("afterload",function(){});
注:若存在跨域呼叫 iframe 的時候,會被瀏覽器禁止,需要進行中轉,具體操作方法請參照 不同埠號下跨域呼叫 JS
2.3 設定 iframe 框架高度
一旦發現瀏覽器已經將結果載入完畢,我們便可以獲取結果如最後一頁資料有多少行,遍歷每行獲得高度並進行累計,將最終需要的高度(像素 px 為單位)賦給框架。
for(var i = 0;i<tr.length;i++){
//由於報表頁面載入完成之後,可能會將儲存格也在載入成一個 tr,會導致重複計算,這裏透過條件判斷來獲取行的 tr
if(tr[i].id.substring(0,1)=="r"){
height = height + tr[i].offsetHeight;
}
}
reportFrame.height = height;
注:由於報表在計算解析成 HTML 的時候,可能會將儲存格也解析成為一個 tr,所以需要遍歷所有 tr 判斷一下儲存格是否被解析為一個 tr。
實現如上效果,請看下面完整的頁面程式碼。
2.4 頁面 auto.html 完整程式碼
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Demo</title>
</head>
<script type="text/javascript">
// 由於gotoNextPage()等方法呼叫後,後台伺服器傳回結果需要一定的時間,而我們需要獲得傳回結果中的行
// 因此新增監聽,contentPane.on("afterload",function(){}):當選擇頁載入完畢後呼叫 setframeHeight 方法獲取行數及高度進而調整框架大小
window.onload=function(){
var contentPane = document.getElementById('reportFrame').contentWindow._g();
contentPane.on("afterload",function(){
setframeHeight();
});
}
function setframeHeight(){
var reportFrame = document.getElementById('reportFrame');
// 獲得頁面中的所有行
var tr = reportFrame.contentWindow.document.getElementsByTagName("tr");
//為了避免報表載入結束後出現捲軸現象,這裏將報表容器的 overflow 屬性設定為 hidden
//由於在報表容器屬性的設定只能在報表計算之後,所以用 setTimeout 來設定延遲執行時間,如果資料過多,請按照具體情況修改延遲時間
setTimeout(function(){document.getElementById('reportFrame').contentWindow.document.getElementById("content-container").style.overflow="hidden";},10)
// 由於報表頁面還存在頁邊距,因此框架高度是大於所有行累計的高度的,這裏賦一個初始值以表示邊距的大小
var height = 30;
for(var i = 0;i<tr.length;i++){
//由於報表頁面載入完成之後,可能會將儲存格也在載入成一個 tr,會導致重複計算,這裏透過條件判斷來獲取行的 tr
if(tr[i].id.substring(0,1)=="r"){
height = height + tr[i].offsetHeight;
}
}
reportFrame.height = height;
}
</script>
<body >
<div id="toolbar">
<input type="button" onclick="document.getElementById('reportFrame').contentWindow._g().gotoFirstPage();" value="首頁"></input>
<input type="button" onclick="document.getElementById('reportFrame').contentWindow._g().gotoPreviousPage();" value="上一頁"></input>
<input type="button" onclick="document.getElementById('reportFrame').contentWindow._g().gotoNextPage();" value="下一頁"></input>
<input type="button" onclick="document.getElementById('reportFrame').contentWindow._g().gotoLastPage();" value="末頁"></input>
</div>
<iframe id="reportFrame" src="../../decision/view/report?viewlet=/doc/Primary/DetailReport/Details.cpt&__showtoolbar__=false" width = 100% height = 80% frameborder="0" ></iframe>
<p>頁面其他部分</p>
</body>
<html>
2.5 window.onload 無法獲取 contentPane
在實際開發中,發現 contentPane.on(event, function(){});事件無法執行,原因在於以上程式碼執行程式中 contenPane 這個物件是 undefined,這裏我提供兩種思路供大家參考。
修改頁面程式碼:
<script type="text/javascript">
window.onload=function(){
//實現思路就是讓這個頁面載入完畢包括資料都顯示的時候,再執行核心程式碼
//此處的延時2s根據實際情況進行修改,頁面會有些卡頓
setTimeout(function(){
var reportFrame = document.getElementById('reportFrame');
// 獲得頁面中的所有行
var tr = reportFrame.contentWindow.document.getElementsByTagName("tr");
//為了避免報表載入結束後出現捲軸現象,這裏將報表容器的 overflow 屬性設定為 hidden
//這裏直接設定報表容器屬性
document.getElementById('reportFrame').contentWindow.document.getElementById("content-container").style.overflow="hidden";
// 由於報表頁面還存在頁邊距,因此框架高度是大於所有行累計的高度的,這裏賦一個初始值以表示邊距的大小
var height = 30;
for(var i = 0;i<tr.length;i++){
//由於報表頁面載入完成之後,可能會將儲存格也在載入成一個 tr,會導致重複計算,這裏透過條件判斷來獲取行的 tr
if(tr[i].id.substring(0,1)=="r"){
height = height + tr[i].offsetHeight;
}
}
reportFrame.height = height;
}, 2000);
}
</script>
注:在報表的“載入結束”中獲取報表的高度,然後將報表高度傳給父頁面在頁面初始化程式中調整 firame 的高度,頁面載入會比較流暢。
2.6 預覽效果
啟動工程,輸入http://localhost:8075/webroot/help/page_demo/auto.html,效果如下圖:
3. 注意事項
此文檔中:2.1,2.2,2.3 為功能步驟,可先行研究其功能步驟後。再對 2.4 主頁面程式碼進行查看看。