1. 概述
1.1 問題描述
将報表集成至 Web 頁面中時,報表往往只是作爲頁面的某一部分嵌入在一個框架中如 iframe 中顯示出來。
由於報表每頁數據是不定的,在最後一頁可能只有幾條數據,此時 iframe 框架将留有大片的空白,造成空間的浪費也使得界面不美觀。
這個時候我們就會希望,要是 iframe 框架大小能夠根據報表頁面的内容自動調整高度或寬度,如下圖效果:
當頁面記錄數較少,此時 iframe 框架高度變小,如下圖:
1.2 實現思路
主要思路如下通過網頁加載結束事件監聽報表頁面的高度,進而設置所在 iframe 框架的高度,即可實現 iframe 框架高度根據報表内容來自适應了。
2. 操作步驟
2.1 實現翻頁功能
可參考 自定義翻頁按鈕
通過使用 contentPane 的翻頁屬性方法來實現翻頁
具體使用代碼如下:
<div id="toolbar">
<input type="button" onclick="document.getElementById('reportFrame').contentWindow.contentPane.gotoFirstPage();" value="首頁"></input>
<input type="button" onclick="document.getElementById('reportFrame').contentWindow.contentPane.gotoPreviousPage();" value="上一頁"></input>
<input type="button" onclick="document.getElementById('reportFrame').contentWindow.contentPane.gotoNextPage();" value="下一頁"></input>
<input type="button" onclick="document.getElementById('reportFrame').contentWindow.contentPane.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.contentPane;
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.contentPane.gotoFirstPage();" value="首頁"></input>
<input type="button" onclick="document.getElementById('reportFrame').contentWindow.contentPane.gotoPreviousPage();" value="上一頁"></input>
<input type="button" onclick="document.getElementById('reportFrame').contentWindow.contentPane.gotoNextPage();" value="下一頁"></input>
<input type="button" onclick="document.getElementById('reportFrame').contentWindow.contentPane.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 預覽效果
已完成示例請參照%FR_HOME%/WebReport/page_demo/auto.html
啓動設計器,輸入http://localhost:8075/webroot/help/page_demo/auto.html,效果如下圖:
3. 注意事項
此文檔中:2.1,2.2,2.3 爲功能步驟,可先行研究其功能步驟後。再對 2.4 主頁面代碼進行查看看。