[JavaScript]自定义MessageBox

 

前言:

    继上文([JavaScript]自定义Title的显示方式)之后,我的工作是进一步增强一些IE所不能提供的东东.

    还记得Windows下的MessageBox嘛?

    IE呢?Alert?Confirm? 是不是好丑呢?

    不过丑就算了,关键是还不好用.

    本次的目标是,提供好看又好用的Web版的Windows MessageBox.(已测试,兼容IE和FF)

正文:

    首先自然是先画好Html下的对话框样子了(用层来模拟):


    画得不专业,先用着,反正后面可以通过css来调整.

    接下来的工作就是需要通过Javascript动态输入这个层的内容.首先参考[JavaScript]自定义Title的显示方式中的方式,代码虽然很多,不过只不过比[JavaScript]自定义Title的显示方式多了几个层而已,大同小异:
   

  1
  2KMessageBox = {
  3  name: "KMessageBox",
  4  capiton : "消息框",
  5  content: "提示消息",
  6  msgbox : null,
  7  msgcaptioninfo:null,
  8  msgcontent:null,
  9  msgContenttxtmsg:null,
 10  msgbuttonyes:null,
 11  msbbuttonno:null,
 12  msgico:null 
 13}
;
 14
 15KMessageBox.init = function () {
 16    var msgNameSpaceURI = "http://www.w3.org/1999/xhtml";
 17    
 18    if(!msgContainerID)var msgContainerID= "KMessageBox"; }
 19
 20    if(!msgCaptionID)var msgCaptionID= "KMessageBox_caption"; }
 21    if(!msgCaptionInfoID){var msgCaptionInfoID = "KMessageBox_caption_info";}
 22    if(!msgContentID)var msgContentID = "KMessageBox_content"; }
 23    if(!msgContentTxtID)var msgContentTxtID= "KMessageBox_content_txt"; }
 24    if(!msgContentTxtICOID){var msgContentTxtICOID="KMessageBox_content_txt_ico"};
 25    if(!msgContentTxtMsgID){var msgContentTxtMsgID="KMessageBox_content_txt_msg"};
 26    if(!msgButtons){var msgButtonsID="KMessageBox_buttons"};
 27    if(!msgButtonYes){var msgButtonYesID="KMessageBox_buttons_yes"};
 28    if(!msgButtonNo){var msgButtonNoID="KMessageBox_buttons_no"};    
 29    if(!msgButtonOK){var msgButtonOKID="KMessageBox_buttons_ok"};    
 30
 31    var msgContainer = $(msgContainerID);
 32    if(!msgContainer) {
 33      msgContainer = document.createElementNS ? document.createElementNS(msgNameSpaceURI, "div") : document.createElement("div");
 34      msgContainer.setAttribute("id", msgContainerID);
 35      msgContainer.setAttribute("style","MARGIN: 0px auto; POSITION: absolute; TEXT-ALIGN: center;");
 36
 37
 38    var msgCaption = $(msgCaptionID);
 39
 40    if(!msgCaption){
 41      msgCaption = document.createElementNS ? document.createElementNS(msgNameSpaceURI, "div") : document.createElement("div") ;
 42      msgCaption.setAttribute("id",msgCaptionID);
 43      Element.addClassName(msgCaption,"caption");      
 44
 45      
 46      var msgCaptionInfo = $(msgCaptionInfoID);
 47      if(!msgCaptionInfo){
 48      msgCaptionInfo = document.createElementNS ? document.createElementNS(msgNameSpaceURI, "div") : document.createElement("div") ;
 49      msgCaptionInfo.setAttribute("id",msgCaptionInfoID);
 50      Element.addClassName(msgCaptionInfo,"info");
 51      msgCaption.appendChild(msgCaptionInfo);
 52      }

 53      msgContainer.appendChild(msgCaption);
 54      
 55    }

 56    
 57    var msgContent = $(msgContentID);
 58
 59    if(!msgContent){
 60      msgContent= document.createElementNS ? document.createElementNS(msgNameSpaceURI, "div") : document.createElement("div") ;
 61      msgContent.setAttribute("id",msgContentID);
 62      Element.addClassName(msgContent,"content");
 63      
 64      var msgContentTxt = $(msgContentTxtID);
 65      
 66      if(!msgContentTxt ){
 67      msgContentTxt = document.createElementNS ? document.createElementNS(msgNameSpaceURI, "div") : document.createElement("div") ;
 68      msgContentTxt.setAttribute("id",msgContentTxtID);
 69      Element.addClassName(msgContentTxt,"txt");
 70           
 71      var msgContentTxtICO = $(msgContentTxtICOID);
 72      if(!msgContentTxtICO)
 73      {
 74         msgContentTxtICO= document.createElementNS ? document.createElementNS(msgNameSpaceURI, "img") : document.createElement("img") ;
 75         msgContentTxtICO.setAttribute("id",msgContentTxtICOID);
 76         msgContentTxtICO.setAttribute("src","icon_alarm.gif");
 77         msgContentTxtICO.setAttribute("align","absMiddle");
 78         msgContentTxtICO.setAttribute("style","height:52px;width:64px;background-image:url('icon_big_info.gif');");
 79         msgContentTxt.appendChild(msgContentTxtICO);
 80      }

 81      
 82      var msgContentTxtMsg= $(msgContentTxtMsgID);
 83      if(!msgContentTxtMsg)
 84      {
 85         msgContentTxtMsg= document.createElementNS ? document.createElementNS(msgNameSpaceURI, "span") : document.createElement("span") ;
 86         msgContentTxtMsg.setAttribute("id",msgContentTxtMsgID);
 87         
 88         msgContentTxt.appendChild(msgContentTxtMsg);
 89      }

 90
 91
 92      var msgButtons = $(msgButtonsID);
 93      if(!msgButtons)
 94      {
 95         msgButtons = document.createElementNS ? document.createElementNS(msgNameSpaceURI, "div") : document.createElement("div") ;
 96         msgButtons.setAttribute("id",msgButtonsID);
 97         Element.addClassName(msgButtons,"btnlist");
 98         var msgButtonYes = $(msgButtonYesID);
 99          if(!msgButtonYes)
100          {
101            msgButtonYes= document.createElementNS ? document.createElementNS(msgNameSpaceURI, "input") : document.createElement("input") ;
102            msgButtonYes.setAttribute("id",msgButtonYesID);
103            msgButtonYes.setAttribute("type","button");
104            msgButtonYes.setAttribute("value","YES");
105            Element.addClassName(msgButtonYes,"input_set");
106                    
107            msgButtons.appendChild(msgButtonYes);             
108         }

109
110         var msgButtonNo = $(msgButtonNoID);
111          if(!msgButtonNo)
112          {
113            msgButtonNo= document.createElementNS ? document.createElementNS(msgNameSpaceURI, "input") : document.createElement("input") ;
114            msgButtonNo.setAttribute("id",msgButtonNoID);
115            msgButtonNo.setAttribute("type","button");
116            msgButtonNo.setAttribute("value","NO");
117            Element.addClassName(msgButtonNo,"input_set");
118            
119            msgButtons.appendChild(msgButtonNo); 
120            
121         }

122         
123         var msgButtonOK= $(msgButtonOKID);
124          if(!msgButtonOK)
125          {
126            msgButtonOK= document.createElementNS ? document.createElementNS(msgNameSpaceURI, "input") : document.createElement("input") ;
127            msgButtonOK.setAttribute("id",msgButtonOKID);
128            msgButtonOK.setAttribute("type","button");
129            msgButtonOK.setAttribute("value","OK");
130            Element.addClassName(msgButtonOK,"input_set");
131            
132            msgButtons.appendChild(msgButtonOK); 
133            
134         }

135
136
137         msgContentTxt.appendChild(msgButtons);
138      }

139      
140      msgContent.appendChild(msgContentTxt);
141      }

142
143      
144      msgContainer.appendChild(msgContent);
145    }

146
147     document.getElementsByTagName("body").item(0).appendChild(msgContainer);
148    }

149       
150    this.msgbox = $(this.name);
151    this.msgcaptioninfo = $(msgCaptionInfoID);
152    this.msgContenttxtmsg= $(msgContentTxtMsgID);
153    this.msgbuttonyes = $(msgButtonYesID);
154    this.msgbuttonno = $(msgButtonNoID);
155    this.msgbuttonok = $(msgButtonOKID);
156    this.msgico = $(msgContentTxtICOID);
157    Element.hide(this.msgbox);
158   
159}

160
161

    接下来应该为MessageBox提供行为能力.我们需要模拟Confirm和Alert.
    原始的Confrim需要返回false或者true来决定是否要运行postback事件.
    在这里我转换了一下思路,不返回值,而是直接将postback事件的脚本(_doPostBack('',''))传入MessageBox,并绑定到相关的按钮上.所以我们的需要接受传入的参数主要有:消息标题,消息内容,按钮事件
    OK,接下来构造Javascript中MessageBox的ShowConfirm函数:

 1KMessageBox.ShowConfirm = function (imgdir,caption,msg,YesClick,NoClick) {
 2    
 3    if (!this.msgbox ) return;
 4    
 5    this.msgcaptioninfo.innerHTML = caption;
 6    this.msgContenttxtmsg.innerHTML = msg;
 7    //为了提示消息前面的图片可以适应实际的相对位置,传入程序父目录,主要为封装为Server控件做准备
 8       if(imgdir != "")
 9       {
10         this.msgico.setAttribute("src",imgdir+"/kinnsoft_client/KMessageBox/icon_alarm.gif");
11       }

12       else
13       {
14         this.msgico.setAttribute("src","/kinnsoft_client/KMessageBox/icon_alarm.gif");
15       }

16    
17        //使用prototype类库
18    Element.show(this.msgbox);
19    Element.show(this.msgbuttonyes);
20    Element.show(this.msgbuttonno);
21    Element.hide(this.msgbuttonok);
22    
23    var x=0,y=0;
24    x = (document.documentElement.scrollLeft || document.body.scrollLeft);
25    y = (document.documentElement.scrollTop || document.body.scrollTop);
26    
27        /*一下这段这么复杂的处理方法,是为了符合最新web标准,因为在aspx页面中会默认加入
28<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
29新的标准中不支持document.body.clientHeight 属性,它是MSIE所有的
30
31*/

32    var theWidth=0,theHeight=0;
33    
34    if (window.innerWidth) 
35    
36      theWidth = window.innerWidth 
37      theHeight = window.innerHeight 
38    }
 
39    else if (document.documentElement && document.documentElement.clientWidth) 
40    
41      theWidth = document.documentElement.clientWidth 
42      theHeight = document.documentElement.clientHeight 
43    }
 
44    else if (document.body) 
45    
46      theWidth = document.body.clientWidth 
47      theHeight = document.body.clientHeight 
48    }

49    
50       //做div居中处理
51    this.msgbox.style.left = (theWidth  - this.msgbox.offsetWidth)/2+x;
52    this.msgbox.style.top = (theHeight - this.msgbox.offsetHeight)/2+y; 
53
54      //绑定传入的事件
55    this.msgbuttonyes.onclick = YesClick;//function(){ alert('yes');};
56    this.msgbuttonno.onclick = NoClick;
57      //绑定隐藏div的事件,使用prototype类库
58    Event.observe(this.msgbuttonyes,"click",function(){KMessageBox.Hide();},true);
59    Event.observe(this.msgbuttonno,"click",function(){KMessageBox.Hide();},true);
60}

   有了显示还需要做隐藏处理,即上面调用的KMessageBox.Hide();
  
 1KMessageBox.Hide = function()
 2{
 3    if (!this.msgbox ) return;
 4    Element.hide(this.msgbox);
 5    //detach 事件,防止IE 内存泄漏
 6    Event.stopObserving(this.msgbuttonyes,"click",function(){KMessageBox.Hide();},true)
 7    Event.stopObserving(this.msgbuttonno,"click",function(){KMessageBox.Hide();},true)
 8    Event.stopObserving(this.msgbuttonok,"click",function(){KMessageBox.Hide();},true)
 9}

10

    至于模拟Alert,就可以模仿ShowConfirm来做了,so easy
   
    ok,整个MessageBox 类看起来已经像模像样了.运行一下...
   
     噫,不对,好像缺了点什么....没错,它不是ShowModal类型的...用户还可以任意点下面的页面元素.

     这个怎么模拟?

     当然还是div了...做一个整个页面大小的div覆盖在所有页面元素之上,MessageBox层之下.
    
     不过有个弊端,div不能覆盖select控件,那只好搬出iframe了..所谓道高一尺魔高一丈

   
 1function DialogModal()
 2    this.blankImgHandle = null
 3    this.tags = new Array("applet""iframe""select","object","embed");  
 4}

 5
 6 
 7DialogModal.Show = function() 
 8{     
 9debugger;
10        var NameSpaceURI = "http://www.w3.org/1999/xhtml";
11        this.blankImgHandle = document.createElementNS ? document.createElementNS(NameSpaceURI, "iframe") : document.createElement("iframe") ;//iframe
12        this.blankImgHandle.setAttribute("id","blankImgHanldle");
13        with (this.blankImgHandle.style)
14            position = "absolute"
15            left     = 0
16            top      = (document.documentElement.scrollTop || document.body.scrollTop); 
17            height   = "100%"; //这边用100%在 标准生成的aspx页面好像比起效果,去掉doctype那句就可以,所以我直接设置一个分辨率即1024X768
18            width    = "100%"
19            zIndex   = "9999"; //这个zIndex比页面所有元素大,但是要比MessageBox小,保证MessageBox 不被罩住
20            filter   = "progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=40)"
21            opacity  = "0.1";             
22        }
          
23         
24       document.getElementsByTagName("body").item(0).appendChild(this.blankImgHandle);         
25   }
         
26         
27DialogModal.Close = function(){                
28      if (this.blankImgHandle) 
29      
30          Element.remove(this.blankImgHandle);
31          this.blankImgHandle = null;
32      }
             
33  }

34

    在MessageBox中Show的时候,调用DialogModal.Show,Hide的时候调用DialogModal.Hide 即ok了.

    有了上面的两个Javascript类,我们就可以很好的做服务端的封装了,取到control的dopostback函数,直接传入给ShowConfrim就可以了.
   
1//ShowConfirm客户端事件
2private string JS_CONFIRM = "KMessageBox.ShowConfirm('{0}','{1}','{2}',{3},{4});return false;";
3
4//获取DoPostBack事件,这边还有个难点,怎么取得客户端验证事件,目前我还没有解决
5strOnClickScript = "function(){" + Page.ClientScript.GetPostBackEventReference(control, ""+ ";}";
6//注册MessageBox事件,
7 control.Attributes["onclick"+= string.Format(JS_CONFIRM, this.mImgDir, caption, content, strOnClickScript, "function(){}");

源码:

代码插入比较慢,而且经常ShowDialogModal框不返回,晕死.....直接down吧: KMessageBox_Source

KMessageBox.js

 

KMessageBox.css
posted @ 2006-08-10 09:32  浪子  阅读(12628)  评论(55编辑  收藏  举报