上下div高度動態自適應--另類處理方案,div自適應
這段時間在工作中遇到一個看似較為棘手的問題。問題描述:查詢報表頁面分為上下兩部分,上部分為條件輸入地區,下部分為報表展示地區。客戶要求做到預設滿屏(但要動態適應不同的表單大小,也就是瀏覽器表單使用者會手動改變其大小),但上部分條件輸入地區有動態變化高度的現象。
在遇到上述問題,您是否第一反應就是利用window的onresize事件,做尺寸的動態調整。但是條件輸入地區某個按鈕動態改變了上部分的高度時,我們又應該如何呢。是否有統一的處理方案呢。今兒本人就把我自己的想法和測試提供出來,供大家參考,有疑問或建議歡迎交流和溝通。
一、上代碼
閑話少說,上代碼。首先本人為了處理與IE的相容性,對現代瀏覽器,IE瀏覽器做了區別對待。然後提供了一個工廠類以供使用。
1.1、 現代瀏覽器的實現
/** * 現代瀏覽器處理方案 */ function RptAutoHeightForModernBrower(context){ this.context = context; this.$object = null; } var mPt = RptAutoHeightForModernBrower.prototype; mPt.init = function(){ var object = document.createElement('iframe'), self = this; //object在ie11上onload方法不能執行 //區元素,絕對位置(父級必須是相對定位,否則參考到body了),四個為0,width、height為100%讓其寬、高與父級相同,pointer-events:none(不接受滑鼠事件)z-index:層級最低。 object.onload = function(){ var context = this; this.contentDocument.defaultView.addEventListener('resize', function(){ self.context.onResize(context.clientHeight); }); } object.setAttribute('style', 'display:block; position:absolute; border:0px; visibility: hidden; left:0px; right: 0px; top: 0px; bottom: 0px; pointer-events: none; z-index: -1; overflow:hidden; width: 100%; height: 100%; opacity:0;'); //object.type = "text/html"; object.src = "about:blank"; this.context.$header.appendChild(object); this.$object = object; //先觸發一次 this.context.onResize(this.context.$header.clientHeight); //window.resize事件 window.onresize = function(){ self.context.onResize(self.context.$header.clientHeight); } } mPt.dispose = function(){ this.$object.contentDocument.defaultView.removeEventListener('resize'); this.context.$header.removeChild(this.$object); }
在此處,為了做到相容IE11(因為Ie11不支援attacheEvent方法,所以也會被判斷為現代瀏覽器),本人建立的DOM,不是使用的object而是使用的iframe,因為在IE下object的onload事件不能觸發,而iframe的可能有;並且iframe的邊框一定要去掉,否則影響判斷。
1.2、ie瀏覽器的實現
/** * ie的處理方案 */ function RptAutoHeightForIE(context){ this.context = context; } var iePt = RptAutoHeightForIE.prototype; iePt.init = function(){ var self = this; this.context.$header.attachEvent('onresize', function(){ self.context.onResize(window.event.srcElement.clientHeight); }); this.context.onResize(this.context.$header.clientHeight); //window.resize事件 window.onresize = function(){ self.context.onResize(self.context.$header.clientHeight); } } iePt.dispose = function(){ this.context.$header.detachEvent('onresize'); }
IE瀏覽器的實現相對簡單,因為IE環境下的div天身支援onresize事件。
1.3、工廠類
//處理高度自適應的Factory function RptAutoHeightFactory(opts){ this.opts = opts || {}; this.$wrap = this.opts.wrap || document.getElementsByClassName('rpt-wrap')[0]; this.$header = this.opts.header || this.$wrap.getElementsByClassName('rpt-header')[0]; this.$cont = this.opts.cont || this.$wrap.getElementsByClassName('rpt-cont')[0]; var cxt = { $header: this.$header, onResize: this.resize() }; this.diffVal = 0; this.realize = document.attachEvent ? new RptAutoHeightForIE(cxt) : new RptAutoHeightForModernBrower(cxt); } var pt = RptAutoHeightFactory.prototype; pt.init = function(){ var bTop = this.getStyle(this.$header, "border-top-width"); var bBottom = this.getStyle(this.$header, "border-bottom-width"); bTop = parseInt(bTop.replace('px', ''), 10); bBottom = parseInt(bBottom.replace('px', ''), 10); this.diffVal += bTop + bBottom; var bTop = this.getStyle(this.$cont, "border-top-width"); var bBottom = this.getStyle(this.$cont, "border-bottom-width"); bTop = parseInt(bTop.replace('px', ''), 10); bBottom = parseInt(bBottom.replace('px', ''), 10); this.diffVal += bTop + bBottom; this.realize.init(); } pt.resize = function(){ var $cont = this.$cont, self = this; return function(headerHeight){ var dist = self.getMaxHeight() - headerHeight - self.diffVal; if(dist > 1 ){ $cont.style.height = dist +'px'; //加單位,是為了相容ie } } } pt.getHeight = function(dom){ var height = dom.clientHeight; return height; } pt.getStyle = function(dom, key){ if(dom.currentStyle){ return dom.currentStyle[key]; }else if(window.getComputedStyle){ return window.getComputedStyle(dom, null)[key]; } } pt.getMaxHeight = function(){ return document.documentElement.clientHeight || document.body.clientHeight; }
此處本人在擷取style的屬性值,使用了getComputedStyle和currentStyle實現的,這民是標準的方法。
1.4、這樣使用
js代碼:
var irow = 2; function addRow(){ var parent = document.getElementsByClassName('rpt-header')[0]; var p = document.createElement('p'); p.innerHTML = "<p>添加第" + irow++ + "行記錄</p>"; parent.appendChild(p); } var autoHeightFactory = new RptAutoHeightFactory(); autoHeightFactory.init();
html代碼:
<div class="rpt-wrap"> <div class="rpt-header"> <button type="button" onclick="addRow()">添加</button> <p>第一行內容</p> </div> <div class="rpt-cont"> </div> </div>
css代碼:
html, body{ margin: 0px; padding: 0px; height: 100%; } .rpt-wrap{ height: inherit; overflow: hidden; } .rpt-header{ border: 1px solid gray; position: relative; } .rpt-cont{ border: 1px solid red; }