近来忙毕业设计,又很长时间没写blog了。
学ajax也有段时间了,理论是看了不少,也对MagicAjax框架做了下了解,当然要吃透它还是有很长的路要走。
一直觉得对Ajax底层的代码应该总结一下。其实很底层的代码是比较简洁明了的,但功能却比较简单。一般我们都用Send(null).以前我一直在想我怎么来控制当异步传送Http请求时要调用的后台的指定的(我想用的)代码,现在终于明白了(唉,对自己的智商表示怀疑),那就要在Send方法中传送参数。参数中应该包括事件的触发者和它的参数,还有就是ViewState的值。
具体代码如下(里面我加了些注释,后面不再解释):
1
__PageForm = null;
2
3
function AjaxCallObject()
4
{
5
this.Init();
6
}
7
8
AjaxCallObject.prototype.Init = function()
9
{
10
this.XmlHttp = this.GetHttpObject();
11
}
12
13
AjaxCallObject.prototype.GetHttpObject = function()
14
{
15
var xmlhttp;
16
if (!xmlhttp)
17
{
18
try
19
{
20
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
21
}
22
catch (e)
23
{
24
xmlhttp = false;
25
}
26
}
27
return xmlhttp;
28
}
29
30
AjaxCallObject.prototype.HookAjaxCall = function()
31
{
32
__PageForm = document.getElementById('Form1');
33
if (typeof __doPostBack != 'undefined')
34
__doPostBack = this.DoPostBack;
35
}
36
37
// Replaces normal __doPostBack
38
AjaxCallObject.prototype.DoPostBack = function(eventTarget, eventArgument)
39
{
40
AJAXCbo.DoAjaxCall(eventTarget, eventArgument);
41
}
42
43
AjaxCallObject.prototype.DoAjaxCall = function(eventTarget, eventArgument)
44
{
45
var theData = '';
46
var theform = __PageForm;
47
48
if(theform == null)
49
{
50
return;
51
}
52
53
var thePage = theform.action;//得到页面地址
54
var eName = '';
55
56
theData = '__EVENTTARGET=' + this.EncodePostData(eventTarget.split("$").join(":")) + '&';//得到事件的发起者,也就是object Sender
57
theData += '__EVENTARGUMENT=' + this.EncodePostData(eventArgument) + '&';//得到参数,就是EventArgs e
58
59
var elemCount = theform.elements.length;
60
for( var i=0; i<elemCount; i++ )
61
{
62
curElem = theform.elements[i];
63
eName = curElem.name;
64
if( eName && eName != '' && curElem.tagName != "EMBED")
65
{
66
if( eName == '__EVENTTARGET' || eName == '__EVENTARGUMENT' )
67
{}
68
else
69
{
70
var type = curElem.type;
71
var val = curElem.value;
72
73
if ( type == "submit" || type == "button" )
74
continue;
75
76
val = this.EncodePostData(val);
77
78
if ( type == "select-multiple" || type == "select-one" )
79
{
80
var selectLength = curElem.options.length;
81
var optNameStr = this.EncodePostData(eName);
82
for (var j=0; j < selectLength; j++)
83
if (curElem.options[j].selected)
84
theData = theData + optNameStr + '=' + this.EncodePostData(curElem.options[j].value) + '&';
85
}
86
else if ( (type != "checkbox" && type != "radio") || curElem.checked )
87
{
88
theData = theData + this.EncodePostData(eName) + '=' + val + '&';
89
}
90
}
91
}
92
}
93
94
if (theData.substr(theData.length-1) == "&")
95
theData = theData.substr(0, theData.length-1);
96
//alert(theData);
97
98
if( this.XmlHttp )
99
{
100
//注释的是旧的代码,有问题,回送回来的状态都是0,原因还不明
101
/*AJAXCbo = new AjaxCallObject();
102
103
if( this.XmlHttp.readyState == 4 || this.XmlHttp.readyState == 0 )
104
{
105
// Asynchronous
106
this.XmlHttp.open("POST", thePage, true);
107
this.XmlHttp.onreadystatechange = function(){ AJAXCbo.ReadyStateChange(); };
108
this.XmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
109
this.XmlHttp.send(theData);
110
}*/
111
var oThis = this;
112
AJAXCbo = new AjaxCallObject();
113
114
if( this.XmlHttp.readyState == 4 || this.XmlHttp.readyState == 0 )
115
{
116
ajaxCallType = "async";
117
118
if ( ! ajaxCallType || ajaxCallType.toLowerCase() != "sync")
119
{
120
// 异步传输
121
this.XmlHttp.open("POST", thePage, true);
122
this.XmlHttp.onreadystatechange = function(){ oThis.ReadyStateChange(); };
123
this.XmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
124
this.XmlHttp.send(theData);
125
}
126
else
127
{
128
// 同步传输,页面会刷新
129
window.setTimeout(
130
function()
131
{
132
oThis.XmlHttp.open("POST", thePage, false);
133
oThis.XmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
134
oThis.XmlHttp.send(theData);
135
136
if( oThis.XmlHttp.status == 200 && oThis.XmlHttp.statusText == "OK" )
137
oThis.OnComplete(oThis.XmlHttp.responseText, oThis.XmlHttp.responseXML);
138
else
139
oThis.OnError(oThis.XmlHttp.status, oThis.XmlHttp.statusText, oThis.XmlHttp.responseText);
140
}, 1);
141
}
142
}
143
}
144
return true;
145
}
146
147
/*AjaxCallObject.prototype.OnLoading = function()
148
{
149
// Loading
150
}
151
152
AjaxCallObject.prototype.OnLoaded = function()
153
{
154
// Loaded
155
}
156
157
AjaxCallObject.prototype.OnInteractive = function()
158
{
159
// Interactive
160
}
161
*/
162
AjaxCallObject.prototype.OnComplete = function(responseText, responseXml)
163
{
164
this.SetHtmlOfPage(responseText);
165
return true;
166
}
167
168
/*AjaxCallObject.prototype.OnAbort = function()
169
{}*/
170
171
AjaxCallObject.prototype.OnError = function(status, statusText, responseText)
172
{
173
if (status==200)
174
{
175
// a weird bug of Opera sometimes invokes OnError when there's no error
176
this.OnComplete(responseText);
177
return;
178
}
179
180
document.close(); // for IE
181
document.write(responseText);
182
document.close(); // for Firefox
183
}
184
185
AjaxCallObject.prototype.ReadyStateChange = function()
186
{
187
/*if( this.XmlHttp.readyState == 1 )
188
{
189
this.OnLoading();
190
}
191
else if( this.XmlHttp.readyState == 2 )
192
{
193
this.OnLoaded();
194
}
195
else if( this.XmlHttp.readyState == 3 )
196
{
197
this.OnInteractive();
198
}
199
else */
200
//alert("ly");
201
//alert(this.XmlHttp.readyState);
202
if( this.XmlHttp.readyState == 4)
203
{
204
/*if( this.XmlHttp.status == 0 )
205
this.OnAbort();
206
else*/
207
if( this.XmlHttp.status == 200 )
208
{
209
this.OnComplete(this.XmlHttp.responseText, this.XmlHttp.responseXML);
210
}
211
else
212
{
213
this.OnError(this.XmlHttp.status, this.XmlHttp.statusText, this.XmlHttp.responseText);
214
}
215
}
216
}
217
218
AjaxCallObject.prototype.EncodePostData = function(data)
219
{
220
return data.split("%").join("%25").split("=").join("%3d").split("&").join("%26").split("+").join("%2b");
221
}
222
223
AjaxCallObject.prototype.SetHtmlOfPage = function(html)
224
{
225
document.close(); // for IE
226
document.write(html);//用新的html代码替代页面上的html代码
227
document.close(); // for Firefox
228
}
229
230
var AJAXCbo = new AjaxCallObject();
代码长了点,不过可以直接用了,只要在相应的后台代码中给服务器控件加段代码就成了。比如说,Web页面上放了个按钮控件,ID为Button1,那么在后台代码的Page_Load中加上下面一段代码:
__PageForm = null;2

3
function AjaxCallObject()4
{5
this.Init();6
}7

8
AjaxCallObject.prototype.Init = function()9
{10
this.XmlHttp = this.GetHttpObject();11
}12
13
AjaxCallObject.prototype.GetHttpObject = function()14
{ 15
var xmlhttp;16
if (!xmlhttp) 17
{18
try 19
{20
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");21
} 22
catch (e) 23
{24
xmlhttp = false;25
}26
}27
return xmlhttp;28
}29

30
AjaxCallObject.prototype.HookAjaxCall = function()31
{32
__PageForm = document.getElementById('Form1');33
if (typeof __doPostBack != 'undefined')34
__doPostBack = this.DoPostBack;35
}36

37
// Replaces normal __doPostBack38
AjaxCallObject.prototype.DoPostBack = function(eventTarget, eventArgument)39
{ 40
AJAXCbo.DoAjaxCall(eventTarget, eventArgument);41
}42
43
AjaxCallObject.prototype.DoAjaxCall = function(eventTarget, eventArgument)44
{45
var theData = '';46
var theform = __PageForm;47
48
if(theform == null)49
{50
return;51
}52
53
var thePage = theform.action;//得到页面地址54
var eName = '';55

56
theData = '__EVENTTARGET=' + this.EncodePostData(eventTarget.split("$").join(":")) + '&';//得到事件的发起者,也就是object Sender57
theData += '__EVENTARGUMENT=' + this.EncodePostData(eventArgument) + '&';//得到参数,就是EventArgs e58

59
var elemCount = theform.elements.length;60
for( var i=0; i<elemCount; i++ )61
{62
curElem = theform.elements[i];63
eName = curElem.name;64
if( eName && eName != '' && curElem.tagName != "EMBED")65
{66
if( eName == '__EVENTTARGET' || eName == '__EVENTARGUMENT' )67
{}68
else69
{70
var type = curElem.type;71
var val = curElem.value;72

73
if ( type == "submit" || type == "button" )74
continue;75

76
val = this.EncodePostData(val);77

78
if ( type == "select-multiple" || type == "select-one" )79
{80
var selectLength = curElem.options.length;81
var optNameStr = this.EncodePostData(eName);82
for (var j=0; j < selectLength; j++)83
if (curElem.options[j].selected)84
theData = theData + optNameStr + '=' + this.EncodePostData(curElem.options[j].value) + '&';85
}86
else if ( (type != "checkbox" && type != "radio") || curElem.checked )87
{88
theData = theData + this.EncodePostData(eName) + '=' + val + '&';89
}90
}91
}92
}93
94
if (theData.substr(theData.length-1) == "&")95
theData = theData.substr(0, theData.length-1);96
//alert(theData);97
98
if( this.XmlHttp )99
{ 100
//注释的是旧的代码,有问题,回送回来的状态都是0,原因还不明101
/*AJAXCbo = new AjaxCallObject();102

103
if( this.XmlHttp.readyState == 4 || this.XmlHttp.readyState == 0 )104
{105
// Asynchronous106
this.XmlHttp.open("POST", thePage, true);107
this.XmlHttp.onreadystatechange = function(){ AJAXCbo.ReadyStateChange(); };108
this.XmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');109
this.XmlHttp.send(theData);110
}*/111
var oThis = this;112
AJAXCbo = new AjaxCallObject();113

114
if( this.XmlHttp.readyState == 4 || this.XmlHttp.readyState == 0 )115
{116
ajaxCallType = "async";117
118
if ( ! ajaxCallType || ajaxCallType.toLowerCase() != "sync")119
{120
// 异步传输121
this.XmlHttp.open("POST", thePage, true);122
this.XmlHttp.onreadystatechange = function(){ oThis.ReadyStateChange(); };123
this.XmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');124
this.XmlHttp.send(theData);125
}126
else127
{128
// 同步传输,页面会刷新129
window.setTimeout(130
function()131
{132
oThis.XmlHttp.open("POST", thePage, false);133
oThis.XmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');134
oThis.XmlHttp.send(theData);135

136
if( oThis.XmlHttp.status == 200 && oThis.XmlHttp.statusText == "OK" )137
oThis.OnComplete(oThis.XmlHttp.responseText, oThis.XmlHttp.responseXML);138
else139
oThis.OnError(oThis.XmlHttp.status, oThis.XmlHttp.statusText, oThis.XmlHttp.responseText);140
}, 1);141
} 142
}143
}144
return true;145
}146

147
/*AjaxCallObject.prototype.OnLoading = function()148
{149
// Loading150
}151

152
AjaxCallObject.prototype.OnLoaded = function()153
{154
// Loaded155
}156

157
AjaxCallObject.prototype.OnInteractive = function()158
{159
// Interactive160
}161
*/162
AjaxCallObject.prototype.OnComplete = function(responseText, responseXml)163
{164
this.SetHtmlOfPage(responseText);165
return true;166
}167

168
/*AjaxCallObject.prototype.OnAbort = function()169
{}*/170

171
AjaxCallObject.prototype.OnError = function(status, statusText, responseText)172
{173
if (status==200)174
{175
// a weird bug of Opera sometimes invokes OnError when there's no error176
this.OnComplete(responseText);177
return;178
}179

180
document.close(); // for IE181
document.write(responseText);182
document.close(); // for Firefox183
}184

185
AjaxCallObject.prototype.ReadyStateChange = function()186
{187
/*if( this.XmlHttp.readyState == 1 )188
{189
this.OnLoading();190
}191
else if( this.XmlHttp.readyState == 2 )192
{193
this.OnLoaded();194
}195
else if( this.XmlHttp.readyState == 3 )196
{197
this.OnInteractive();198
}199
else */200
//alert("ly");201
//alert(this.XmlHttp.readyState);202
if( this.XmlHttp.readyState == 4)203
{204
/*if( this.XmlHttp.status == 0 )205
this.OnAbort();206
else*/207
if( this.XmlHttp.status == 200 )208
{209
this.OnComplete(this.XmlHttp.responseText, this.XmlHttp.responseXML);210
}211
else212
{213
this.OnError(this.XmlHttp.status, this.XmlHttp.statusText, this.XmlHttp.responseText); 214
}215
}216
}217

218
AjaxCallObject.prototype.EncodePostData = function(data)219
{220
return data.split("%").join("%25").split("=").join("%3d").split("&").join("%26").split("+").join("%2b");221
}222

223
AjaxCallObject.prototype.SetHtmlOfPage = function(html)224
{225
document.close(); // for IE226
document.write(html);//用新的html代码替代页面上的html代码227
document.close(); // for Firefox228
}229

230
var AJAXCbo = new AjaxCallObject();
Button1.Attributes.Add("onclick","modify();");
<script>
function modify()
{
if(typeof(AJAXCbo) == 'undefined')
{
var AJAXCbo = new AjaxCallObject();
}
AJAXCbo.HookAjaxCall();
}
</script>水平有限,难免有错误,望能和大家多多交流!
例子代码下载:/Files/fxb248/ajaxtestaaa.rar

