首先,来说一下对话框:
对话框在Windows应用程序中使用非常普遍,许多应用程序的设定,与用户交互需要通过对话框来进行,因此对话框是Windows应用程序中最重要的界面元素之一,是与用户交互的重要手段。对话框是一个特殊的窗口,任何对窗口进行的操作(如移动、最大化、最小化等)也可以在对话框实施。
对话框大致可以分为以下两种:
(1)模态对话框:模态对话框弹出后,独占了系统资源,用户只有在关闭该对话框后才可以继续执行,不能够在关闭对话框之前执行应用程序其他部分的代码。模态对话框一般要求用户做出某种选择。
(2)非模态对话框:非模态对话框弹出后,程序可以在不关闭该对话框的情况下继续执行,在转入到应用程序其他部分的代码时可以不需要用户做出响应。非模态对话框一般用来显示信息,或者实时地进行一些设置。
模态窗口在传统编程语言中很常见,简单的说就是,如果是模态的,就是打开一个子窗口,如果这个子窗口不关闭,就不能操作它的父窗口,原来程序暂停执行,直到这个模态窗口关闭后才回到原来程序继续。
非模态的就是直接显示出来,然后原来的程序继续执行下面的语句,而且其他窗口也呈可用状态。
模态对话框独占了用户的输入,当一个模态对话框打开时,用户只能与该对话框进行交互,而其他用户界面对象收不到输入信息。应用程序用到的大部分对话框都是模态对话框。
通常浏览器中windwo.open或超链接弹出的新窗口就是非模式窗口,而模式窗口是类似alert那种必须关闭才能响应其他事件的窗口。
明白了对话框的模态和非模态,来看下边在B/s结构应用程序的开发中,有时我们会希望使用者按下按钮后开启一个保持在原窗口前方的子窗口,
在IE中,我们可以使用window.showModelessDialog()方法用来创建一个显示HTML内容的非模态对话框。window.showModalDialog()方法用来创建一个显示HTML内容的模态对话框,由于是对话框,因此它并没有一般用window.open()打开的窗口的所有属性。
这里是window.showModalDialog弹出窗口的一个实例函数:
代码如下:
function openWin(src, width, height, showScroll){
window.showModalDialog
(src,"","location:No;status:No;help:No;dialogWidth:"+width+";dialogHeig
ht:"+height+";scroll:"+showScroll+";");
}
// --> script>
例:
代码如下:
('http://www.gxlcms.com', '500px', '400px', 'no')">点击
需要注意的是FireFox浏览器中不支持showmodaldialog() ,这是因为在最初MozillaSuite 中(Firefox 是从这个套件衍生),是支持 showmodaldialog()的,不过后来发现 showmodaldialog() 存在安全隐患,不久后就取消了对showmodaldialog() 的支持,这个事情还发生在 bug 194404 提交前。在想出更好的解决方案前,相信 Firefox 是不会提供对 showmodaldialog() 的支持的。
打开弹窗只能使用window.open实现这样的功能,window.open的语法如下 : oNewWindow = window.open( [sURL] [, sName] [, sFeatures] [, bReplace])
只是,在Firefox下,window.open的参数中,sFeature多了一些功能设定,要让FireFox下开启的窗口跟IE的showModalDialog一样的话, 只要在sFeatures中加个modal=yes就可以了,也许可能是出于安全考虑modal=yes,打开的并不是模式窗口,范例如下: 代码如下: oNewWindow = window.open( [sURL] [, sName] [, sFeatures] [, bReplace]) 由于在firefox没有showModalDialog方法。则用如下判断来兼容两种浏览器: 代码如下: function showDialog(url) { if( document.all ) //IE { feature="dialogWidth:300px;dialogHeight:200px;status:no;help:no"; window.showModalDialog(url,null,feature); } else { //modelessDialog可以将modal换成dialog=yes feature ="width=300,height=200,menubar=no,toolbar=no,location=no,"; feature+="scrollbars=no,status=no,modal=yes"; window.open(url,null,feature); } } //--> 二、JavaScript+div实现模态对话框:
一个类似163邮箱对话框的功能。主要是2个层来完成这个效果,第一就是用来锁住下面整个页面的层,要有透明的效果,可以用filter:alpha(opacity=50)。还有一个层是用来显示对话框内容的,所以zIndex参数一定要设置的比锁频层高。
对话框的CSS可以自己定义一下,要注意的是,CSS中body一定要定义margin:0,否则锁频时,会出现空隙,而产生锁频不完整的问题,还有一个就是Select这个控件的问题,因为在IE里,他的zIndex很高,所以锁频层盖不住他,这里可以用两种办法,一种是把他隐藏掉,一种可以把他的disabled属性设置为false,第二种方法只能禁止编辑它,但是还是会在锁频层上当,效果不佳,还是隐藏掉比较好。 代码如下:
````` var t_DiglogX,t_DiglogY,t_DiglogW,t_DiglogH;
function StrCode(str)
{
if(encodeURIComponent)
return encodeURIComponent(str);
if(escape)
return escape(str);
}
function Browser() { var ua, s, i; this.isIE = false; this.isNS = false; this.isOP = false; this.isSF = false; ua = navigator.userAgent.toLowerCase(); s = "opera"; if ((i = ua.indexOf(s)) >= 0) { this.isOP = true;return; } s = "msie"; if ((i = ua.indexOf(s)) >= 0) { this.isIE = true; return; } s = "netscape6/"; if ((i = ua.indexOf(s)) >= 0) { this.isNS = true; return; }
s = "gecko"; if ((i = ua.indexOf(s)) >= 0) { this.isNS = true; return; }
s = "safari"; if ((i = ua.indexOf(s)) >= 0) { this.isSF = true; return; } }
function DialogShow(showdata,ow,oh,w,h) { var objDialog = document.getElementById("DialogMove"); if (!objDialog) objDialog = document.createElement("div"); t_DiglogW = ow; t_DiglogH = oh; DialogLoc(); objDialog.id = "DialogMove"; var oS = objDialog.style; oS.display = "block"; oS.top = t_DiglogY + "px"; oS.left = t_DiglogX + "px"; oS.margin = "0px"; oS.padding = "0px"; oS.width = w + "px"; oS.height = h + "px"; oS.position = "absolute"; oS.zIndex = "5"; oS.background = "#FFF"; oS.border = "solid #000 1px"; objDialog.innerHTML = showdata; document.body.appendChild(objDialog); }
function DialogHide() { ScreenClean(); var objDialog = document.getElementById("DialogMove"); if (objDialog) objDialog.style.display = "none"; }
function DialogLoc() { var dde = document.documentElement; if (window.innerWidth){ var ww = window.innerWidth; var wh = window.innerHeight; var bgX = window.pageXOffset; var bgY = window.pageYOffset; }else{ var ww = dde.offsetWidth; var wh = dde.offsetHeight; var bgX = dde.scrollLeft; var bgY = dde.scrollTop; } t_DiglogX = (bgX + ((ww - t_DiglogW)/2)); t_DiglogY = (bgY + ((wh - t_DiglogH)/2)); }
function ScreenConvert(){ var browser = new Browser(); var objScreen = document.getElementById("ScreenOver"); if(!objScreen) var objScreen = document.createElement("div"); var oS = objScreen.style; objScreen.id = "ScreenOver"; oS.display = "block"; oS.top = oS.left = oS.margin = oS.padding = "0px"; if (document.body.clientHeight) { var wh = document.body.clientHeight + "px"; }else if (window.innerHeight){ var wh = window.innerHeight + "px"; }else{ var wh = "100%"; } oS.width = "100%"; oS.height = wh; oS.position = "absolute"; oS.zIndex = "3"; if ((!browser.isSF) && (!browser.isOP)){ oS.background = "#cccccc"; }else{ oS.background = "#cccccc"; }
oS.filter = "alpha(opacity=50)"; oS.opacity = 40/100; oS.MozOpacity = 40/100; document.body.appendChild(objScreen); var allselect = document.getElementsByTagName("select"); for (var i=0; iallselect[i].style.visibility = "hidden"; }
function ScreenClean() { var objScreen = document.getElementById("ScreenOver"); if (objScreen) objScreen.style.display = "none"; var allselect = document.getElementsByTagName("select"); for (var i=0; iallselect[i].style.visibility = "visible"; }
function Demo(string) { ScreenConvert(); var ShowDiv=""+string+"
"; DialogShow(ShowDiv,250,120,300,100); } // --> script>
1 2 2 2 value="">2 11
22
三、Javascript模态对话框 取父页的值
1. a.htm 父页
有 window.showModalDialog("b.htm");
有 Html元素
2.b.htm 弹出页面
能否在 b.htm 上取到 a.htm 中 t1值 ?
回答:
在a.html中设置
var results = window.showModalDialog("b.html");
(results){alert(results["key"]);}
在b.html中
window.Value={key:"返回到父页面"}
script>
四、模态对话框模仿MessageBox
代码如下:
模态对话框 //按钮类型 var MB_OK = 1; var MB_CANCEL = 2; var MB_YES = 4; var MB_NO = 8; /*================================================================================*/ /*================================================================================*/ //MessageBox类 //因为利用层不可能实现真正模态对话框,用户仍然可以点击对话框以外的区域,所以需要一个覆盖框-coverIdStr //另一方面为了承载对话框,需要dlgIdStr function CMessageBox(coverIdStr, dlgIdStr) { this.coverIdStr = coverIdStr; this.coverId = document.getElementById(this.coverIdStr); this.dlgIdStr = dlgIdStr; this.dlgId = document.getElementById(this.dlgIdStr); this.dlgCaptionId = null; this.dlgInfoId = null; this.dlgButtonsId = null; this.caption = ""; this.info = ""; this.buttons = MB_OK; this.returnValue = 0; //返回值,0表示不确定,其它值可能是MB_OK、MB_CANCEL、MB_YES、MB_NO this.DoModal = DoModal; this.IniDlg = IniDlg; this.ShowDlg = ShowDlg; } //caption 对话框标题 //info 对话框内容,HTML无效 //buttons 对话框按钮,使用一个按钮类型值或多个按钮类型值相加(但不能重复相加),HTML有效 //objNameStr CMessageBox对象名称 function DoModal(caption, info, buttons, objNameStr) { this.dlgId.innerHTML = "" + " " + " " + " " + ""; this.dlgCaptionId = document.getElementById(this.dlgIdStr + "_caption"); this.dlgInfoId = document.getElementById(this.dlgIdStr + "_info"); this.dlgButtonsId = document.getElementById(this.dlgIdStr + "_buttons"); this.IniDlg(caption, info, buttons, objNameStr); this.ShowDlg(true); } //初始化对话框 function IniDlg(caption, info, buttons, objNameStr) { this.dlgCaptionId.innerText = caption; this.dlgInfoId.innerHTML = info; this.dlgButtonsId.innerHTML = ""; if (parseInt(buttons/8) == 1) { this.dlgButtonsId.innerHTML = "
" + this.dlgButtonsId.innerHTML;//前后空格,避免各个按钮之间离得太近 buttons -= 8; } if (parseInt(buttons/4) == 1) { this.dlgButtonsId.innerHTML = "
" + this.dlgButtonsId.innerHTML; buttons -= 4; } if (parseInt(buttons/2) == 1) { this.dlgButtonsId.innerHTML = "
" + this.dlgButtonsId.innerHTML; buttons -= 2; } if (buttons == 1) { this.dlgButtonsId.innerHTML = "
" + this.dlgButtonsId.innerHTML; } } //显示、隐藏对话框,并确定是点击哪个按钮关闭对话框的 //display为true-显示 //display为false-隐藏 function ShowDlg(display, returnValue) { if (display) { ReSizeDlg(); this.coverId.style.display = "block"; } else { this.coverId.style.display = "none"; } this.returnValue = returnValue; } /*================================================================================*/ /*================================================================================*/ //对话框返回函数 //自行修改函数代码 function OnDlgReturn(objNameStr, returnValue) { alert("CMessageBox 对象 " + objNameStr + " 的返回值是" + returnValue); } //保持cover框覆盖整个客户区 //保持对话框在预期位置 //如果覆盖框id不为cover,则需要手动修改此函数。 //document.body.onscroll和document.body.onresize触发本函数 //同时此函数也被CMessageBox调用 function ReSizeDlg() { var cover = document.getElementById("cover"); cover.style.pixelTop = document.body.scrollTop; cover.style.pixelLeft = document.body.scrollLeft; cover.style.width = document.body.clientWidth; cover.style.height = document.body.clientHeight; } document.body.onscroll = ReSizeDlg; document.body.onresize = ReSizeDlg; /*================================================================================*/ /*================================================================================*/ var objDlg = new CMessageBox("cover", "dlg"); var objDlg2 = new CMessageBox("cover", "dlg");
// --> script>
五、showModalDialog 打开的模态对话框有不少经典的缺陷,解决办法
showModalDialog 打开的模态对话框有不少经典的缺陷,在这里不再冗述,我只谈谈最近碰到的几个问题以及解决办法。
问题1. showModalDialog 打开一个 aspx 页面时,如果该页面在之前已经打开过一次,则自动会加载缓存中的页面,而不能显示最新数据。
解决的办法有两种:
(1). 在打开模态框时,给 url 后面多加一个随机参数,来避免页面被缓存:
var url = 'EditFlowNode.aspx?flowId=0&id=2
&x =' + Math.random();
var result = window.showModalDialog(url, '', 'status:no; help:no;');
(2). 在该 asp.net 页面的 Page_Load 方法里设定不缓存:
protected void Page_Load(object sender, EventArgs e){
Response.Expires = 0;
Response.Cache.SetNoStore();
Response.AppendHeader("Pragma", "no-cache");
}
问题2. 模态对话框中的内容和脚本加载次序不同,导致的问题。
缘起:考虑如下页面的代码
new document
这个页面,如果在普通的 IE 窗口中加载时,提示的信息是 "155",而在模态对话框中执行时,其数值是 "0"。为什么会这样?
我们注意到普通窗口打开该页面时,当跳出 alert 对话框后,整个页面元素都已经正常显示了;而模态框在打开时,跳出 alert 对话框后,其背景却是一片空白;等点击“确定”后,才会显示出网页内容。 由此可以推测,模态框和普通页面在解析执行 HTML 时的次序不同:
普通页面:依次解析 body 中的元素,并随即绘制(render)解析完的元素。如果碰到 script, 则立刻执行之。
模态对话框:依次解析 body 中的元素,但并未立即绘制(render)它们。如果碰到 script, 则立刻执行之。等 body 都加载完毕后,再依次绘制其中的元素。
由于以上我们示例代码中访问到了 offsetWidth 属性,而我们可以推知,该属性一定是当元素被绘制(render)完毕后,才会自动计算出有意义的数值。所以就导致了问题中看到的现象。
之所以考虑到这个问题,其实是因为我在模态对话框中使用一个第三方控件的时候,出现了 bug,经过调试发现根源的原因在于该控件采用了常用的代码模式来输出其 HTML。也就是在一段 HTML 输出后,紧接着输出其初始化脚本。(这个问题值得 ASP.NET 控件开发者引起注意)
幸运的是,我有这个控件的源代码。因此修改源代码解决了这个问题。我的解法类似于这样:
new document
六、使用div仿javascript模态窗口 代码如下:
asfsdfasdfasdf function show(){
id1.style.height=window.screen.height+"px";
id1.style.width=window.screen.width+"px";
id1.style.display='block';
id2.style.display='block'
}
function hide(){
id1.style.display='none'
id2.style.display='none'
}
self.onError=null;
currentX = currentY = 0;
whichIt = null;
lastScrollX = 0; lastScrollY = 0;
NS = (document.layers) ? 1 : 0;
IE = (document.all) ? 1: 0;
function heartBeat() {
if(IE) { diffY = document.body.scrollTop; diffX = document.body.scrollLeft; } if(NS) { diffY = self.pageYOffset; diffX = self.pageXOffset; }
if(diffY != lastScrollY) {
percent = .1 * (diffY - lastScrollY);
if(percent > 0) percent = Math.ceil(percent);
else percent = Math.floor(percent);
if(IE) document.all.id2.style.pixelTop += percent;
if(NS) document.id2.top += percent;
lastScrollY = lastScrollY + percent;
}
if(diffX != lastScrollX) {
percent = .1 * (diffX - lastScrollX);
if(percent > 0) percent = Math.ceil(percent);
else percent = Math.floor(percent);
if(IE) document.all.id2.style.pixelLeft += percent;
if(NS) document.id2.left += percent;
lastScrollX = lastScrollX + percent;
}
}
function checkFocus(x,y) {
stalkerx = document.id2.pageX;
stalkery = document.id2.pageY;
stalkerwidth = document.id2.clip.width;
stalkerheight = document.id2.clip.height;
if( (x > stalkerx && x < (stalkerx+stalkerwidth)) && (y > stalkery && y < (stalkery+stalkerheight))) return true;
else return false;
}
function grabIt(e) {
if(IE) {
whichIt = event.srcElement;
while (whichIt.id.indexOf("id2") == -1) {
whichIt = whichIt.parentElement;
if (whichIt == null) { return true; }
}
whichIt.style.pixelLeft = whichIt.offsetLeft;
whichIt.style.pixelTop = whichIt.offsetTop;
currentX = (event.clientX + document.body.scrollLeft);
currentY = (event.clientY + document.body.scrollTop);
} else {
window.captureEvents(Event.MOUSEMOVE);
if(checkFocus (e.pageX,e.pageY)) {
whichIt = document.id2;
stalkerTouchedX = e.pageX-document.id2.pageX;
StalkerTouchedY = e.pageY-document.id2.pageY;
}
}
return true;
}
function moveIt(e) {
if (whichIt == null) { return false; }
if(IE) {
newX = (event.clientX + document.body.scrollLeft);
newY = (event.clientY + document.body.scrollTop);
distanceX = (newX - currentX); distanceY = (newY - currentY);
currentX = newX; currentY = newY;
whichIt.style.pixelLeft += distanceX;
whichIt.style.pixelTop += distanceY;
if(whichIt.style.pixelTop < document.body.scrollTop) whichIt.style.pixelTop = document.body.scrollTop; if(whichIt.style.pixelLeft < document.body.scrollLeft) whichIt.style.pixelLeft = document.body.scrollLeft; if(whichIt.style.pixelLeft > document.body.offsetWidth - document.body.scrollLeft - whichIt.style.pixelWidth - 20) whichIt.style.pixelLeft = document.body.offsetWidth - whichIt.style.pixelWidth - 20;
if(whichIt.style.pixelTop > document.body.offsetHeight + document.body.scrollTop - whichIt.style.pixelHeight - 5) whichIt.style.pixelTop = document.body.offsetHeight + document.body.scrollTop - whichIt.style.pixelHeight - 5;
event.returnValue = false;
} else {
whichIt.moveTo(e.pageX-StalkerTouchedX,e.pageY-StalkerTouchedY);
if(whichIt.left < 0+self.pageXOffset) whichIt.left = 0+self.pageXOffset;
if(whichIt.top < 0+self.pageYOffset) whichIt.top = 0+self.pageYOffset;
if( (whichIt.left + whichIt.clip.width) >= (window.innerWidth+self.pageXOffset-17)) whichIt.left = ((window.innerWidth+self.pageXOffset)-whichIt.clip.width)-17;
if( (whichIt.top + whichIt.clip.height) >= (window.innerHeight+self.pageYOffset-17)) whichIt.top = ((window.innerHeight+self.pageYOffset)-whichIt.clip.height)-17;
return false;}
return false;
}
function dropIt() {
whichIt = null;
if(NS) window.releaseEvents (Event.MOUSEMOVE);
return true;
}
if(NS) {
window.captureEvents(Event.MOUSEUP|Event.MOUSEDOWN);
window.onmousedown = grabIt;
window.onmousemove = moveIt;
window.onmouseup = dropIt;
}
if(IE) {
document.onmousedown = grabIt;
document.onmousemove = moveIt;
document.onmouseup = dropIt;
}
if(NS || IE) action = window.setInterval("heartBeat()",1)
// --> script>
这里可以放内容,或者添加div用innerhtml进行添加内容就可以了
123