meizz的专栏

梅花雪·疏影横斜

原创 梅花雪脚本控件集:MzPopupLayer 可盖住flash的层基类收藏

新一篇: JavaScript应用:Iframe自适应其加载的内容高度 | 旧一篇: 查找两段文本中相同的词句

Subject: popup layer, cross browser(IE5.0+ Firefox Netscape Mozilla Opera)
NameSpace:  System.Web.UI.WebControls.MzPopupLayer


    网页里做脚本控件的时候经常需要一个层的依托,比如自定义的右键菜单层,下拉式菜单层,模拟窗口层,日期选择录入控件层等等,这些层一般的人都是以一个绝对定位的DIV做的,在老版的http://www.microsoft.com/china 下拉菜单就是用这种DIV层,但是这种层有一个很致命的地方,会被页面里的<select>或者<iframe>或者FLASH之类的东东遮挡住(即使将z-index设置得再高也是无用的),因此需要使用别的技术来实现,所以我想到了用<iframe>作层的载体,它可以“盖”住select,iframe,flash。但是用它当然没有象DIV那么简单,所以我特别封装了这么一个基类,供其它的脚本控件调用。

    在IE5.5+里有一个特殊的对象 window.createPopup() 这个怪胎东东可以跨框架显示,可以“伸”到网页之外显示,拿来做下拉菜单、右键菜单层简直是太好不过了,所以我把它也封装到我这个类里去了,做出一个统一的接口供调用者调用。

 

 


 


/*---------------------------------------------------------------------------*\
|  Subject:    popup layer  cross browser(IE5.0+ Firefox NS Moz Opera)
|  NameSpace:  System.Web.UI.WebControls.MzPopupLayer
|  Author:     meizz
|  Created:    2006-03-19
|  Version:    2006-04-20
|-------------------------------------------------------------
|  MSN: huangfr@msn.com   QQ: 112889082   http://www.meizz.com
|  Email: mz@126.com      CSDN ID:meizz   Copyright (c)  meizz
\*---------------------------------------------------------------------------*/

 

function MzPopupLayer(iframe)
{
  this.id= this.getHashCode();
  this.name=this.id +"_popup";
  this.usePopup = false;
  if (typeof iframe=="undefined")
  {
    try
    {
      this.element =window.createPopup();
      this.usePopup=true;
      this.document=this.element.document;
    }
    catch (ex){this.usePopup = false;}
  }
  this.isOpen=false;
  this.binder=null;
  this.lock=false;
  this.autoFit=false;
  if(!this.usePopup)
  {
    if(document.all)
    {
      if(document.readyState=="complete") document.body.innerHTML+=
        "<iframe id='"+ this.id +"' name='"+ this.name +"'></iframe>";
      else document.write("<iframe id='"+this.id+"' name='"+this.name+"'></iframe>");
      this.element=document.getElementById(this.id);
    }
    else
    {
      this.element = document.createElement("IFRAME");
      this.element.id = this.id;
      this.element.name=this.name;
      document.body.appendChild(this.element);
    }
    with(this.element.style)
    {
      width=0; height=0; borderWidth=0;
      zIndex=MzPopupLayer.zIndex++; position="absolute";
    }
    this.style = this.element.style;var me=this;
    document.attachEvent("onclick", function(e)
    {
      e=e||window.event; e=e.target||e.srcElement;
      if( me.lock) me.srcElement=e;
      if(!me.lock && me.isOpen && e!=me.srcElement) me.hide();
    });
    document.attachEvent("oncontextmenu", function(e)
    {
      if(me.isOpen) me.hide();
    });
    document.attachEvent("onkeydown", function(e)
    {
      e=e||window.event; var k=e.which||e.keyCode;
      if(!me.lock && me.isOpen && (k==27 || k==9)) me.hide();
    });
    window.attachEvent("onscroll", function(){if(me.isOpen)me.hide();});

 

    function sleep(n){var start=new Date().getTime(); //for opera only
    while(true) if(new Date().getTime()-start>n) break;}
    if(window.opera){sleep(500);this.document=this.element.document;}
    else  this.document=frames[this.name].document;

 

    var html = "<html><head></head><body style='border-width:0;padding:0;"+
      "margin:0;overflow:hidden;background-color:white'></body></html>";
    this.document.write(html); this.document.close();

 

    if(window.opera) this.document=this.element.document;
    else this.document=frames[this.name].document;
  }
}
MzPopupLayer.Extends(System, "MzPopupLayer");
MzPopupLayer.zIndex=520;

 

MzPopupLayer.prototype.show = function(left, top, width, height, trigger)
{
  if(this.usePopup)
  {
    this.element.show(left, top, width, height, trigger);
    this.isOpen=this.element.isOpen;
  }
  else
  {
    this.lock=true;
    this.isOpen=true;
    this.binder=trigger;
    this.element.style.top = top;
    this.element.style.left = left;
    this.element.style.width = width;
    this.element.style.height = height;
    setTimeout("Instance('"+this.id+"').lock=false",1);
  }
};

 

MzPopupLayer.prototype.bind = function(trigger, width, height)
{
  var e=trigger, x=e.offsetLeft, y=e.offsetTop;
  while(e=e.offsetParent){x+=e.offsetLeft; y+=e.offsetTop;}

 

  var DL, DT, top=0, left=0;

 

  if(window.pageXOffset){DL=window.pageXOffset;}
  else if(document.documentElement&&document.documentElement.scrollLeft){
    DL=document.documentElement.scrollLeft;}
  else if(document.body){DL=document.body.scrollLeft;}

 

  if(window.pageYOffset){DT=window.pageYOffset;}
  else if(document.documentElement&&document.documentElement.scrollTop){
    DT=document.documentElement.scrollTop;}
  else if(document.body){DT=document.body.scrollTop;}

 

  if(this.usePopup)
  {
    if(this.autoFit)
    {
      this.element.show(0, 0, 1, 1, trigger);
      width = this.document.body.scrollWidth;
      height = this.document.body.scrollHeight;
    }
    top=trigger.offsetHeight;
    if(screen.availHeight-(screenTop+y+top-DT)<height) top=0-height;
  }
  else
  {
    var DW, DH;
    if(window.innerWidth){DW=window.innerWidth;}
    else if(document.documentElement&&document.documentElement.clientWidth){
      DW=document.documentElement.clientWidth;}
    else if(document.body){DW=document.body.clientWidth;}

 

    if(window.innerHeight){DH=window.innerHeight;}
    else if(document.documentElement&&document.documentElement.clientHeight){
      DH=document.documentElement.clientHeight;}
    else if(document.body){DH=document.body.clientHeight;}

 

    try{this.element.style.width="1px"; //possible error on reload page Netscape
    this.element.style.height="1px";
    this.document.body.style.overflow="auto";
    if(!window.opera) var EW=this.document.body.scrollWidth;  //always retrieve inexact width in Opera
    var EH=this.document.body.scrollHeight;
    this.document.body.style.overflow="hidden";}
    catch(ex){EW=width||100; EH=height||100;} width=EW; height=EH;

 

    var OH=trigger.offsetHeight;
    if(window.opera && trigger.tagName=="INPUT"){x+=3; y+=3; OH-=6;} //repair for Opera
    if(DT+DH-y-OH<height&&y-DT>height) top=y-height; else top=y+OH;
    if (x + width > DL + DW) left = DW + DL - width;
    else if (x - DL < 0) left = DL; else left = x;
  }
  this.show(left, top, width, height, trigger);
};

 

MzPopupLayer.prototype.hide = function()
{
  if(this.usePopup)
  {
    this.element.hide();
    this.isOpen=this.element.isOpen;
  }
  else
  {
    this.isOpen=false;
    this.binder=null;
    this.srcElement=null;
    with(this.element.style){width="0px"; height="0px";}
  }
};

 

MzPopupLayer.prototype.createStyleSheet = function(url)
{
  if(this.document.createStyleSheet)
  {
    if(typeof url!="string") return this.document.createStyleSheet();
    else return this.document.createStyleSheet(url);
  }
  var e=null, d=this.document;if(url){ e=d.createElement("LINK");
  e.href=url;e.type="text/css"; e.rel="Stylesheet";}else{
  e=d.createElement("STYLE");   e.type="text/css"; }
  d.getElementsByTagName("HEAD")[0].appendChild(e);
  try{e = d.styleSheets[d.styleSheets.length-1];}catch (ex){
  throw "Your browser isn't support document.styleSheets!";}
  return new MzStyleSheet(e);
}
function MzStyleSheet(styleSheet)
{
  this.self=styleSheet;
  if (this.self.rules) this.rules=this.self.rules;
  else if (this.self.cssRules) this.rules=this.self.cssRules;
  this.addRule = function(selector,style,i)
  {
    if (this.self.addRule) return this.self.addRule(selector,style,i);
    else if (this.self.insertRule)
    {
      if(typeof i=="undefined")i=this.self.cssRules.length;
      return this.self.insertRule(selector+"{"+style+"}",i);
    }
  };
  this.removeRule = function(i)
  {
    if (this.self.removeRule) this.self.removeRule(i);
    else if (this.self.deleteRule)
    {
      if(typeof i=="undefined")i=0;this.self.deleteRule(i);
    }
  };
}


 

 

 


成员属性列表:
.document  层体的document对象,可以做如 document.body 之类的操作
.isOpen  布尔值 指层的显示/隐藏状态
.autoFit  布尔值 层的高宽将自适应其加载的内容高宽
.usePopup  布尔值 指层目前是使用window.createPopup()还是使用iframe

成员方法列表:
.show(left, top, width, height, trigger)
.bind(trigger, width, height)
.hide()
.createStyleSheet([url])  //此方法在Opera里有BUG



 2006-04-20 增加了 autoFit 属性,层体将自适应其加载的内容的高宽!


2006-03-22 增加对象绑定功能 .bind() 可以使用层与某个对象绑定,智能地在它周围显示
2006-03-22 层的自动隐藏功能实现

 


 

2006-03-20 createStyleSheet()方法的实现,可以创建styleSheet对象,并且可以.rules .addRule() .removeRule()操作(已经解决跨浏览器兼容)

 


 

2006-03-19 创建此类(前身是MzLayer类,在Calendar3.0里曾使用),iframe和createPopup()的智能使用,hide() show()方法的等

发表于 @ 2006年03月22日 16:57:00|评论(loading...)|编辑

新一篇: JavaScript应用:Iframe自适应其加载的内容高度 | 旧一篇: 查找两段文本中相同的词句

评论

#holin 发表于2006-03-23 09:06:00  IP: 221.12.2.*
好东西
#lf 发表于2006-03-23 14:29:00  IP: 218.80.75.*
怎么应用?
#JK 发表于2006-05-31 15:41:00  IP: 219.134.77.*
这一个层可以盖住select:

<html>
<body>
<script language="javascript">
var oldX;
var oldY;
function MouseDown(obj)
{
oldX = event.x-obj.style.pixelLeft;
oldY = event.y-obj.style.pixelTop;
obj.setCapture(); //====>这里

}

function MouseUp(obj)
{
obj.releaseCapture(); //=====这里
}

function MouseMove(obj)
{
if(event.button==1)
{
obj.style.pixelLeft = (event.x-oldX);
obj.style.pixelTop = (event.y-oldY);
}
}
</script>

<select name="s1">
<option value="ss">sssss</option>
</select>
<div id="menu1" style="position:absolute; left:168px; top:52px; width:186px; z-index:2; background-color: #FF0000; layer-background-color: #FF0000; border: 1px none #000000; visibility: visible" onMouseDown="MouseDown(this);" onMouseUp="MouseUp(this);" onmouseMove="MouseMove(this);">
<iframe style="z-index:-1;position:absolute;top:0;left:0;width:100%;height:100%"></iframe>
<table width="100%" border="1" cellspacing="0" cellpadding="0" bgcolor="#FF0000" style="z-index:2; ">
<tr><td>fdsaf dsafdsf</td></tr>
</table>
</div>
</body>
</html>
#无心(cuixiping) 发表于2006-06-29 12:01:00  IP: 59.61.66.*
单纯为了盖住flash层的话,倒不用那么复杂,只需要为flash的html代码加上:
<param name="wmode" value="opaque">
即可。
#ctbinzi 发表于2006-07-08 20:13:00  IP: 58.214.163.*
无心(cuixiping)

呵呵
#wuhaihao 发表于2006-07-09 19:24:00  IP: 218.206.101.*
用createPopup()好像会被IE的拉截工具;或是杀毒的截获掉;到时就显示不出来了;
#hshxf 发表于2006-07-11 11:15:00  IP: 210.72.232.*
createPopup,在服务器端ie访问,能够超出浏览器,在客户端ie访问不能超出ie。
#mynickel 发表于2006-08-02 20:56:00  IP: 222.240.66.*
to hshxf:
这是浏览器设置问题
调整IE的安全,在自定义级别中的“允许由脚本初始化的窗口,没有大小和位置限制”项选为启动。
#mynickel 发表于2006-08-09 19:19:00  IP: 202.103.95.*
如果发现右键菜单出现显示异常,请做如下设置:
调整IE的安全,在自定义级别中的“允许由脚本初始化的窗口,没有大小和位置限制”项选为启动。
#gu1dai 发表于2006-09-21 11:53:00  IP: 218.242.214.*
老大,你少贴了一些代码

hashCode()

方法在哪?
#gu1dai 发表于2006-09-21 13:01:00  IP: 218.242.214.*
firefox不兼容
错误: document.attachEvent is not a function
源文件:http://localhost/2345guestbook/js/meizz_popup.js
行:58

#gu1dai 发表于2006-09-21 13:02:00  IP: 218.242.214.*
firefox不兼容
错误: document.attachEvent is not a function
源文件:http://localhost/2345guestbook/js/meizz_popup.js
行:58

#careprad 发表于2006-12-19 16:35:44  IP:
确实没有跨浏览器啊 好几个地方使用了IE特性
#axiang_2898 发表于2006-12-27 09:36:31  IP: 222.68.188.*
你好,我在用到你的:Web Calendar ver 3.0 网页日历控件时的问题?
我在网页头加上:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
当我在页面上加上上面的一行代码时,那个JS的日历控件打不开,不能用,这是怎么回事呢?急,谢谢你能尽快回答!
#useinhere 发表于2007-06-23 11:22:15  IP: 221.221.82.*
请问meizz老师您有可动态加载的树形菜单的源码下载吗?
发表评论  


当前用户设置只有注册用户才能发表评论。如果你没有登录,请点击登录
Csdn Blog version 3.1a
Copyright © meizz