扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
作者:meizz 来源:CSDN 2008年1月20日
关键字: 层基类 FLASH 盖住 MzPopupLayer
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
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者