近来要做一个LightBox的效果(也有的叫Windows关机效果),不过不用那么复杂,能显示一个内容框就行了。
“定位效果”的意思是屏幕滚动也能固定位置。
首先要先说说这个东西position:fixed,它的作用是跨浏览器的固定定位。
摘自详解定位与定位应用 :
程序中很多地方利用了这个css,ie7、ff都支持这个css,但ie6不支持,程序中只能是在ie6模拟这个效果。 【覆盖层】 
覆盖层的作用是把焦点限制在高亮层上,原理是通过一个绝对定位的层(通常使用div),设置它的宽度和高度以致能覆盖整个屏幕(包括缩放和滚动浏览器的情况下),再给它设置一个比较高的zIndex来层叠在原有内容之上(但要比高亮层小),这样用户就只能点到这个层之上的内容了。
this .Lay  =  $( this .options.Lay)  ||  document.body.insertBefore(document.createElement( " div " ), document.body.childNodes[ 0 ]); 
document.body.appendChild()导致IE已终止操作 bug,所以用了insertBefore。。
【覆盖屏幕】 
覆盖层的关键就是如何做到覆盖整个屏幕(锁定整个页面),支持position:fixed的话很简单:
with ( this .Lay.style){ display  =   " none " ; zIndex  =   this .zIndex; left  =  top  =   0 ; position  =   " fixed " ; width  =  height  =   " 100% " ; } 
用这个方法只要把position设为absolute,并使用一个_resize方法来设置width和height即可:
this .Lay.style.position  =   " absolute " ; this ._resize  =  Bind( this ,  function (){ this .Lay.style.width  =  Math.max(document.documentElement.scrollWidth, document.documentElement.clientWidth)  +   " px " ; this .Lay.style.height  =  Math.max(document.documentElement.scrollHeight, document.documentElement.clientHeight)  +   " px " ; object .object  including padding, but not including margin, border, or scroll bar.object  relative to the layout or coordinate parent, as specified by the offsetParent property.
我的理解是:
举个例子吧,先说说clientHeight和offsetHeight的区别(在ie7中测试):
测的是外面的div,offsetHeight和clientHeight相差17(分别是83和100),这个相差的就是那个滚动条本身的高度。
再看看clientHeight和scrollHeight的区别(下面是模拟在ie中的情况):
可以看到clientHeight不受内容影响,都是83,即内容有没有超过对象高度都不受影响,但scrollHeight会受内容高度影响,而且从测试可以意识到:
当有滚动条时,覆盖层的高度应该取scrollHeight(内容高度);当没有滚动条时,覆盖层的高度应该取clientHeight(视框高度)。
而恰好两个情况都是取两者中比较大的值,所以就有了以下程序: 
Math.max(document.documentElement.scrollHeight, document.documentElement.clientHeight)  +   " px " ; 
上面可以看到我用的是documentElement而不是body,手册上是这样说的:
要注意的是在window的onresize事件中scrollWidth和clientWidth的值会产生变化,程序中在onresize中使用_resize方法重新设置宽度高度:
if (isIE6){  this ._resize(); window.attachEvent( " onresize " ,  this ._resize); } 
【覆盖select】 
自定义的层给select遮挡住是一个老问题了,不过可喜的是ie7和ff都已经支持select的zIndex,只要给层设定高的zIndex就能覆盖select了,可惜对于ie6这个问题还是需要解决。
覆盖select据我所知有两个比较好的方法:
方法1应该都明白,方法2就是利用iframe可以覆盖select的特性,只要把一个iframe作为层的底部就可以覆盖下面的select了,程序中是这样使用的:
this .Lay.innerHTML  =   ' <iframe style="position:absolute;top:0;left:0;width:100%;height:100%;filter:alpha(opacity=0);"></iframe> ' 
个人觉得使用方法2比较好,但始终是改变了页面结构,有时会比较难控制,至于方法1就比较容易方便。
【高亮层】 拖放效果 和渐变效果 ,做出更好的效果。
【固定定位】 
这里“固定定位”的意思是当滚动滚动条时,高亮层依然保持在浏览器对应的位置上,把Fixed设为true就会开启这个效果。
同样对于支持fixed的浏览器很简单,只要把position设为fixed就行了,这个样式本来就是这样使用的,但可怜的ie6只能模拟了。
ie6模拟的原理是在onscroll事件中,不断根据滚动的距离修正top和left。
this .Fixed  &&  window.attachEvent( " onscroll " ,  this ._fixed); 
定位函数_fixed是这样的:
this ._fixed  =  Bind( this ,  function (){  this .Center  ?   this .SetCenter() :  this .SetFixed(); }); 
this .Box.style.top  =  document.documentElement.scrollTop  -   this ._top  +   this .Box.offsetTop  +   " px " ; this .Box.style.left  =  document.documentElement.scrollLeft  -   this ._left  +   this .Box.offsetLeft  +   " px " ; this ._top  =  document.documentElement.scrollTop;  this ._left  =  document.documentElement.scrollLeft; 【居中显示】 
“居中显示”的意思是高亮层位于视框左右上下居中的位置。
方法1相对方法2需要多一个视框宽度,而且方法2在缩放浏览器时也能保持居中,明显方法2是更好,不过用margin会影响到left和top的计算,必须注意(例如SetFix修正的地方)。这里我选择了方法2,还要注意offsetWidth和offsetHeight需要在高亮层显示之后才能获取,所以定位程序需要放到高亮层显示之后:
this .Box.style.top  =   this .Box.style.left  =   " 50% " ; if ( this .Fixed){ this .Box.style.marginTop  =   -   this .Box.offsetHeight  /   2   +   " px " ; this .Box.style.marginLeft  =   -   this .Box.offsetWidth  /   2   +   " px " ; else { this .SetCenter(); 其中如果不是固定定位,需要用SetCenter程序来修正滚屏参数,SetCenter程序是这样的:
this .Box.style.marginTop  =  document.documentElement.scrollTop  -   this .Box.offsetHeight  /   2   +   " px " ; this .Box.style.marginLeft  =  document.documentElement.scrollLeft  -   this .Box.offsetWidth  /   2   +   " px " ; 【比较文档位置】 
在ie6当不显示覆盖层时需要另外隐藏select,这里使用了“覆盖select”的方法1,值得留意的是这里加了个select是否在高亮层的判断:
this ._select.length  =   0 ; " select " ), Bind( this ,  function (o){ if ( ! Contains( this .Box, o)){ o.style.visibility  =   " hidden " ;  this ._select.push(o); } 其中Contains程序是这样的:
var  Contains  =   function (a, b){ return  a.contains  ?  a  !=  b  &&  a.contains(b) :  !! (a.compareDocumentPosition(b)  &   16 ); 
参考Comparing Document Position 看下表:
Bits Number Meaning 000000 0 Elements are identical. 000001 1 The nodes are in different documents (or one is outside of a document). 000010 2 Node B precedes Node A. 000100 4 Node A precedes Node B. 001000 8 Node B contains Node A. 010000 16 Node A contains Node B. 100000 32 For private use by the browser. 
从这里可以看出NodeA.compareDocumentPosition(NodeB) & 16的意思是当第5位数是“1”时才返回16,也就是只有NodeA包含NodeB时返回16(&是位与运算)。
ps:为什么不直接a.compareDocumentPosition(b) 
==   16,我也不清楚。 程序代码: 
var  isIE  =  (document.all)  ?   true  :  false ; var  isIE6  =  isIE  &&  ([ / MSIE (\d)\.0 / i.exec(navigator.userAgent)][ 0 ][ 1 ]  ==   6 ); var  $  =   function  (id) { return   " string "   ==   typeof  id  ?  document.getElementById(id) : id; var  Class  =  { function () { return   function () {  this .initialize.apply( this , arguments); } var  Extend  =   function (destination, source) { for  ( var  property  in  source) { =  source[property]; var  Bind  =   function (object, fun) { return   function () { return  fun.apply(object, arguments); var  Each  =   function (list, fun){ for  ( var  i  =   0 , len  =  list.length; i  <  len; i ++ ) { fun(list[i], i); } var  Contains  =   function (a, b){ return  a.contains  ?  a  !=  b  &&  a.contains(b) :  !! (a.compareDocumentPosition(b)  &   16 ); var  OverLay  =  Class.create(); =  { function (options) { this .SetOptions(options); this .Lay  =  $( this .options.Lay)  ||  document.body.insertBefore(document.createElement( " div " ), document.body.childNodes[ 0 ]); this .Color  =   this .options.Color; this .Opacity  =  parseInt( this .options.Opacity); this .zIndex  =  parseInt( this .options.zIndex); with ( this .Lay.style){ display  =   " none " ; zIndex  =   this .zIndex; left  =  top  =   0 ; position  =   " fixed " ; width  =  height  =   " 100% " ; } if (isIE6){ this .Lay.style.position  =   " absolute " ; // ie6设置覆盖层大小程序          this ._resize  =  Bind( this ,  function (){ this .Lay.style.width  =  Math.max(document.documentElement.scrollWidth, document.documentElement.clientWidth)  +   " px " ; this .Lay.style.height  =  Math.max(document.documentElement.scrollHeight, document.documentElement.clientHeight)  +   " px " ; // 遮盖select          this .Lay.innerHTML  =   ' <iframe style="position:absolute;top:0;left:0;width:100%;height:100%;filter:alpha(opacity=0);"></iframe> ' // 设置默认属性   SetOptions:  function (options) { this .options  =  { // 默认值         Lay:         null , // 覆盖层对象         Color:         " #fff " , // 背景色         Opacity:     50 , // 透明度(0-100)         zIndex:         1000 // 层叠顺序     }; this .options, options  ||  {}); // 显示   Show:  function () { // 兼容ie6      if (isIE6){  this ._resize(); window.attachEvent( " onresize " ,  this ._resize); } // 设置样式      with ( this .Lay.style){ // 设置透明度         isIE  ?  filter  =   " alpha(opacity: "   +   this .Opacity  +   " ) "  : opacity  =   this .Opacity  /   100 ; =   this .Color; display  =   " block " ; // 关闭   Close:  function () { this .Lay.style.display  =   " none " ; if (isIE6){ window.detachEvent( " onresize " ,  this ._resize); } var  LightBox  =  Class.create(); =  { function (box, options) { this .Box  =  $(box); // 显示层      this .OverLay  =   new  OverLay(options); // 覆盖层      this .SetOptions(options); this .Fixed  =   !! this .options.Fixed; this .Over  =   !! this .options.Over; this .Center  =   !! this .options.Center; this .onShow  =   this .options.onShow; this .Box.style.zIndex  =   this .OverLay.zIndex  +   1 ; this .Box.style.display  =   " none " ; // 兼容ie6用的属性      if (isIE6){ this ._top  =   this ._left  =   0 ;  this ._select  =  []; this ._fixed  =  Bind( this ,  function (){  this .Center  ?   this .SetCenter() :  this .SetFixed(); }); // 设置默认属性   SetOptions:  function (options) { this .options  =  { // 默认值         Over:     true , // 是否显示覆盖层         Fixed:     false , // 是否固定定位         Center:     false , // 是否居中         onShow:     function (){} // 显示时执行     }; this .options, options  ||  {}); // 兼容ie6的固定定位程序   SetFixed:  function (){ this .Box.style.top  =  document.documentElement.scrollTop  -   this ._top  +   this .Box.offsetTop  +   " px " ; this .Box.style.left  =  document.documentElement.scrollLeft  -   this ._left  +   this .Box.offsetLeft  +   " px " ; this ._top  =  document.documentElement.scrollTop;  this ._left  =  document.documentElement.scrollLeft; // 兼容ie6的居中定位程序   SetCenter:  function (){ this .Box.style.marginTop  =  document.documentElement.scrollTop  -   this .Box.offsetHeight  /   2   +   " px " ; this .Box.style.marginLeft  =  document.documentElement.scrollLeft  -   this .Box.offsetWidth  /   2   +   " px " ; // 显示   Show:  function (options) { // 固定定位      this .Box.style.position  =   this .Fixed  &&   ! isIE6  ?   " fixed "  :  " absolute " ; // 覆盖层      this .Over  &&   this .OverLay.Show(); this .Box.style.display  =   " block " ; // 居中      if ( this .Center){ this .Box.style.top  =   this .Box.style.left  =   " 50% " ; // 设置margin          if ( this .Fixed){ this .Box.style.marginTop  =   -   this .Box.offsetHeight  /   2   +   " px " ; this .Box.style.marginLeft  =   -   this .Box.offsetWidth  /   2   +   " px " ; else { this .SetCenter(); // 兼容ie6      if (isIE6){ if ( ! this .Over){ // 没有覆盖层ie6需要把不在Box上的select隐藏              this ._select.length  =   0 ; " select " ), Bind( this ,  function (o){ if ( ! Contains( this .Box, o)){ o.style.visibility  =   " hidden " ;  this ._select.push(o); } // 设置显示位置          this .Center  ?   this .SetCenter() :  this .Fixed  &&   this .SetFixed(); // 设置定位          this .Fixed  &&  window.attachEvent( " onscroll " ,  this ._fixed); this .onShow(); // 关闭   Close:  function () { this .Box.style.display  =   " none " ; this .OverLay.Close(); if (isIE6){ " onscroll " ,  this ._fixed); this ._select,  function (o){ o.style.visibility  =   " visible " ; }); 
< style > { width : 300px ; background : #FFFFFF ; border : 1px solid #ccc ; line-height : 25px ;  top : 20% ;  left : 20% ; } { background : #f4f4f4 ;  padding : 5px ; } </ style > < dl  id ="idBox"  class ="lightbox" > < dt  id ="idBoxHead" >< b > LightBox </ b >   </ dt > < dd > < br  />< br  /> < input  name =""  type ="button"  value =" 关闭 "  id ="idBoxCancel"   /> < br  />< br  /> </ dd > </ dl > 至于覆盖层一般不需要另外设了,接着就可以实例化一个LightBox:
var  box  =   new  LightBox( " idBox " ); 
其中LightBox有下面几个属性:
还有OverLay属性是覆盖层对象,它也有几个属性:
                
            
                留言评论