彈出層就是相對文檔或視窗定位的一個層,一般用來顯示提示資訊、廣告等内容,還可以配合覆寫層來鎖定頁面。
在[url=http://www.cnblogs.com/cloudgamer/archive/2008/09/15/1290954.html]仿Lightbox效果[/url]中,已經基本實作了這個效果,這次主要改進了ie6在fixed時的抖動問題。
此外,還增加了一個用來相容ie6的fixed的方法,覆寫層也重新“包裝”,程式也改成元件的結構。
相容:ie6/7/8, firefox 3.6.8, opera 10.6, safari 5.0.1, chrome 5.0
[img]http://dl.iteye.com/upload/attachment/329659/6525993e-dc7f-3fb9-90c0-0245020b291a.jpg[/img]
[url=http://www.cnblogs.com/cloudgamer/archive/2010/10/11/AlertBox.html][b]前台效果預覽[/b][/url]
[url=http://dl.iteye.com/topics/download/5ef49027-39c2-348c-b2d5-fa2488e2277c][b]完整執行個體下載下傳[/b][/url]
[b]程式說明[/b]
[b]【實作原理】[/b]
彈出層的基本原理在[url=http://www.cnblogs.com/cloudgamer/archive/2008/09/15/1290954.html]仿Lightbox效果[/url]中已經說的差不多了。
關鍵的地方就是定位,一般相對文檔的定位用absolute就行了。
要随屏移動,即相對視窗定位,就用fixed定位。
這些實作起來都很簡單,除了不支援fixed的ie6。
[b]【相容ie6的fixed】[/b]
由于ie6本身不支援fixed定位,隻能模拟或取巧來間接實作。
最原始的方法是在window的scroll事件中不斷修正彈出層的位置,像[url=http://www.cnblogs.com/cloudgamer/archive/2008/09/15/1290954.html]仿Lightbox效果[/url]那樣。
後來有人發現還可以[url=http://bbs.blueidea.com/thread-2938030-1-1.html]通過reflow“離奇”地實作[/url]。
但以上方法都有一個缺陷,滾動時彈出層會“發抖”,很不舒服(可以用緩動等來改善)。
想要不發抖,可以通過html和css的巧妙應用來實作,具體參考[url=http://bbs.blueidea.com/thread-2930592-1-1.html]14px的介紹[/url]。
原理是用一個容器代替body,然後對不會動的body絕對定位。
看來很完美,但有一個緻命的問題,這個方法需要修改html結構,會影響到相關的一些東西,例如window的scroll事件等。
程式中用了另一個方法,通過body的背景和expression來實作,下面是一個相容的fixed效果:
[code]<!DOCTYPE html>
<html>
<head>
<style>
body {
_background: url(about:blank) fixed;
}
.fixable {
position:fixed;
top:100px;
_position:absolute;
_top:expression((document).documentElement.scrollTop+100);
}
</style>
</head>
<body style="height:1500px;">
<div class="fixable">fixable</div>
</body>
</html>[/code]
以上代碼能相容ie6實作fixed,比較關鍵的是:
body的background-attachment必須是fixed;
把要fixed的元素設定絕對定位,并且用expression不斷修正top/left。
具體原理我也不清楚,可能是body背景在fixed之後,會優先重繪expression的結果。
ps:expression裡面必須用eval或加括号,才能不斷觸發運算(具體原因不明)。
關于這個方法的介紹可以看[url=http://www.gunlaug.no/contents/wd_additions_15.html]position: fixed in IE/win[/url]和[url=http://www.qianduan.net/fix-ie6-dont-support-position-fixed-bug.html]修正IE6不支援position:fixed的bug[/url]等。
相比前面的方法,這個是比較完美的了,但也有一些問題,例如body的背景隻能用fixed,使用expression資源消耗相對較大。
更大的問題是不能實作用百分比值或right/bottom來定位。
為了解決這個問題,程式使用了一個定位層,這個層用上面的方法實作fixed定位,尺寸跟視窗大小一樣,并且位置重合,那麼隻要用一般的定位方法相對這個層定位,就能達到相對視窗定位的效果了。
相容程式主要在RepairFixed對象中,首先設定body背景:
[code]if (body.currentStyle.backgroundAttachment !== "fixed") {
if (body.currentStyle.backgroundImage === "none") {
body.runtimeStyle.backgroundRepeat = "no-repeat";
body.runtimeStyle.backgroundImage = "url(about:blank)";
}
body.runtimeStyle.backgroundAttachment = "fixed";
}[/code]
參考自DE的[url=http://code.google.com/p/ie7-js/]IE7.js[/url],用"url(about:blank)"就不需要另外加圖檔。
再建立定位層:
[code]layer = document.createElement("<div style='position:absolute;border:0;padding:0;margin:0;overflow:hidden;background:transparent;top:expression((document).documentElement.scrollTop);left:expression((document).documentElement.scrollLeft);width:expression((document).documentElement.clientWidth);height:expression((document).documentElement.clientHeight);display:block;'>");[/code]
由于視窗大小可能會改變,除了top/left外,width/height也需要用expression修正。
定位層還要設定"overflow:hidden",好處是不會因彈出層在document原來的範圍外而自動擴大document。
ie6測試以下代碼,document會随着下滾而不斷擴大:
[code]<!DOCTYPE html>
<html>
<head>
<style>
body {
_background: url(about:blank) fixed;
}
.fixable {
position:absolute;
top:expression((document).documentElement.scrollTop+(document).documentElement.clientHeight);
}
</style>
</head>
<body>
<div class="fixable">fixable</div>
</body>
</html>[/code]
加上"overflow:hidden"就可以防止這種情況。
然後彈出層通過append方法修改為"absolute"定位,并插入到這個定位層,這樣就能實作fixed效果了。
由于這個定位層比較耗資源,是以在有元素插入時才會插到body中。
在不需要fixed的時候,要用remove方法從定位層中移除,當定位層内沒有需要定位元素就會自動從body移除。
ps:隐藏的話expression還會繼續執行,要移出文檔才行。
[b]【居中效果】[/b]
加入居中擴充程式,并且設定center為true,就會自動相對視窗居中。
居中的原理跟仿Lightbox效果是一樣的,通過設定負的元素尺寸一半的margin和"50%"的top/left來居中。
要注意的是不是使用fixed定位時,計算需要加上scrollTop/scrollLeft。
[b]【覆寫層】[/b]
在仿Lightbox效果中,ie6的覆寫層是通過建立一個覆寫整個頁面的層來做的。
使用新的相容fixed方法後,就不用另外做相容,按照fixed的效果做就行了。
覆寫層是由AlertBox擴充而來,它其實就是一個大小跟視窗一樣,并且跟視窗重合的彈出層。
由于覆寫層一般隻需要定義一個就行了,這裡把它做成一個OverLay對象,使用時直接調用它的show和close方法。
[b]【遮蓋select】[/b]
在仿Lightbox效果中介紹過兩種遮蓋select的方法:隐藏和iframe。
程式是通過iframe來遮蓋的,放在ie6的相容擴充程式中。
在iframe定位時要注意,要定位到彈出層的負的clientTop/clientLeft,這樣才能保證邊框不會被遮住。
[b]使用技巧[/b]
[b]【定位】[/b]
除了居中,程式會按照彈出層本身的定位樣式來顯示。
不是fixed定位時要注意,在ie6是相對目前視窗來定位的,其他都是相對第一屏視窗來定位的。
還要注意,必須聲明DOCTYPE,才能正确定位。
程式為了盡量通用,降低了效率(用了4個expression),是以最好還是根據實際情況自己來調整。
ps:需要像[url=http://www.cnblogs.com/cloudgamer/archive/2009/07/07/FixedTips.html]定位提示效果[/url]那樣預設定位的話,可以自行擴充。
[b]【鎖定鍵盤】[/b]
使用覆寫層時,為了防止使用者通過鍵盤操作頁面,可以在document的keydown中執行preventDefault來禁用。
如果彈出層需要正常操作,隻要在彈出層的keydown中執行stopPropagation就行了。
[b]【拖動彈窗】[/b]
這裡隻是簡單的加上拖動功能,要注意的是fixed定位時,計算拖動的參考對象是不同的。
更詳細的拖動介紹可以看看這個[url=http://www.cnblogs.com/cloudgamer/archive/2008/11/17/Drag.html]拖動效果[/url]。
[b]使用說明[/b]
執行個體化時,必須有彈出層作為參數:
[code]new AlertBox("idBox");[/code]
可選參數用來設定程式的預設屬性,包括:
屬性: 預設值//說明
fixed: false,//是否固定定位
zIndex: 1000,//層疊數
onShow: $$.emptyFunction,//顯示時執行
onClose: $$.emptyFunction//關閉時執行
還提供了以下方法:
show:顯示彈出層;
close:隐藏彈出層;
dispose:銷毀程式。
加入相容ie6擴充程式後,會自動修正ie6的fixed問題,可根據fixSelect屬性設定是否修正select遮蓋bug,預設是。
加入居中擴充程式後,可根據center屬性設定是否居中,預設否。
RepairFixed修正fixed對象,可獨立使用,有append和remove方法添加和移除需要fixed的元素,隻能在ie6使用。
OverLay覆寫層對象,有如下屬性:
屬性: 預設值//說明
"color": "#fff",//背景色
"opacity": .5,//透明度(0-1)
"zIndex": 100,//層疊值
還有show和close方法顯示和隐藏覆寫層。