[JavaScript]自定义MessageBox
前言:
继上文([JavaScript]自定义Title的显示方式)之后,我的工作是进一步增强一些IE所不能提供的东东.
还记得Windows下的MessageBox嘛?
IE呢?Alert?Confirm? 是不是好丑呢?
不过丑就算了,关键是还不好用.
本次的目标是,提供好看又好用的Web版的Windows MessageBox.(已测试,兼容IE和FF)
正文:
首先自然是先画好Html下的对话框样子了(用层来模拟):
画得不专业,先用着,反正后面可以通过css来调整.
接下来的工作就是需要通过Javascript动态输入这个层的内容.首先参考[JavaScript]自定义Title的显示方式中的方式,代码虽然很多,不过只不过比[JavaScript]自定义Title的显示方式多了几个层而已,大同小异:
1
2
KMessageBox = {
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
15
KMessageBox.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

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

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

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

有了显示还需要做隐藏处理,即上面调用的KMessageBox.Hide();
1
KMessageBox.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

2

3

4

5

6

7

8

9

10

至于模拟Alert,就可以模仿ShowConfirm来做了,so easy
ok,整个MessageBox 类看起来已经像模像样了.运行一下...
噫,不对,好像缺了点什么....没错,它不是ShowModal类型的...用户还可以任意点下面的页面元素.
这个怎么模拟?
当然还是div了...做一个整个页面大小的div覆盖在所有页面元素之上,MessageBox层之下.
不过有个弊端,div不能覆盖select控件,那只好搬出iframe了..所谓道高一尺魔高一丈
1
function DialogModal(){
2
this.blankImgHandle = null;
3
this.tags = new Array("applet", "iframe", "select","object","embed");
4
}
5
6
7
DialogModal.Show = function()
8
{
9
debugger;
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
27
DialogModal.Close = function(){
28
if (this.blankImgHandle)
29
{
30
Element.remove(this.blankImgHandle);
31
this.blankImgHandle = null;
32
}
33
};
34

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

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

2

3

4

5

6

7

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


【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· SQL Server 2025 AI相关能力初探
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库