近来忙毕业设计,又很长时间没写blog了。
学ajax也有段时间了,理论是看了不少,也对MagicAjax框架做了下了解,当然要吃透它还是有很长的路要走。
一直觉得对Ajax底层的代码应该总结一下。其实很底层的代码是比较简洁明了的,但功能却比较简单。一般我们都用Send(null).以前我一直在想我怎么来控制当异步传送Http请求时要调用的后台的指定的(我想用的)代码,现在终于明白了(唉,对自己的智商表示怀疑),那就要在Send方法中传送参数。参数中应该包括事件的触发者和它的参数,还有就是ViewState的值。
具体代码如下(里面我加了些注释,后面不再解释):
1__PageForm = null;
2
3function AjaxCallObject()
4{
5 this.Init();
6}
7
8AjaxCallObject.prototype.Init = function()
9{
10 this.XmlHttp = this.GetHttpObject();
11}
12
13AjaxCallObject.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
30AjaxCallObject.prototype.HookAjaxCall = function()
31{
32 __PageForm = document.getElementById('Form1');
33 if (typeof __doPostBack != 'undefined')
34 __doPostBack = this.DoPostBack;
35}
36
37// Replaces normal __doPostBack
38AjaxCallObject.prototype.DoPostBack = function(eventTarget, eventArgument)
39{
40 AJAXCbo.DoAjaxCall(eventTarget, eventArgument);
41}
42
43AjaxCallObject.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
152AjaxCallObject.prototype.OnLoaded = function()
153{
154 // Loaded
155}
156
157AjaxCallObject.prototype.OnInteractive = function()
158{
159 // Interactive
160}
161*/
162AjaxCallObject.prototype.OnComplete = function(responseText, responseXml)
163{
164 this.SetHtmlOfPage(responseText);
165 return true;
166}
167
168/*AjaxCallObject.prototype.OnAbort = function()
169{}*/
170
171AjaxCallObject.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
185AjaxCallObject.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
218AjaxCallObject.prototype.EncodePostData = function(data)
219{
220 return data.split("%").join("%25").split("=").join("%3d").split("&").join("%26").split("+").join("%2b");
221}
222
223AjaxCallObject.prototype.SetHtmlOfPage = function(html)
224{
225 document.close(); // for IE
226 document.write(html);//用新的html代码替代页面上的html代码
227 document.close(); // for Firefox
228}
229
230var AJAXCbo = new AjaxCallObject();
代码长了点,不过可以直接用了,只要在相应的后台代码中给服务器控件加段代码就成了。比如说,Web页面上放了个按钮控件,ID为Button1,那么在后台代码的Page_Load中加上下面一段代码:2
3function AjaxCallObject()
4{
5 this.Init();
6}
7
8AjaxCallObject.prototype.Init = function()
9{
10 this.XmlHttp = this.GetHttpObject();
11}
12
13AjaxCallObject.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
30AjaxCallObject.prototype.HookAjaxCall = function()
31{
32 __PageForm = document.getElementById('Form1');
33 if (typeof __doPostBack != 'undefined')
34 __doPostBack = this.DoPostBack;
35}
36
37// Replaces normal __doPostBack
38AjaxCallObject.prototype.DoPostBack = function(eventTarget, eventArgument)
39{
40 AJAXCbo.DoAjaxCall(eventTarget, eventArgument);
41}
42
43AjaxCallObject.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
152AjaxCallObject.prototype.OnLoaded = function()
153{
154 // Loaded
155}
156
157AjaxCallObject.prototype.OnInteractive = function()
158{
159 // Interactive
160}
161*/
162AjaxCallObject.prototype.OnComplete = function(responseText, responseXml)
163{
164 this.SetHtmlOfPage(responseText);
165 return true;
166}
167
168/*AjaxCallObject.prototype.OnAbort = function()
169{}*/
170
171AjaxCallObject.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
185AjaxCallObject.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
218AjaxCallObject.prototype.EncodePostData = function(data)
219{
220 return data.split("%").join("%25").split("=").join("%3d").split("&").join("%26").split("+").join("%2b");
221}
222
223AjaxCallObject.prototype.SetHtmlOfPage = function(html)
224{
225 document.close(); // for IE
226 document.write(html);//用新的html代码替代页面上的html代码
227 document.close(); // for Firefox
228}
229
230var AJAXCbo = new AjaxCallObject();
Button1.Attributes.Add("onclick","modify();");
这里的modify是我在页面的html里定义的一个方法,其内容是:<script>
function modify()
{
if(typeof(AJAXCbo) == 'undefined')
{
var AJAXCbo = new AjaxCallObject();
}
AJAXCbo.HookAjaxCall();
}
</script>
到这就结束了,你可以看到无刷新更新的效果了。接下来的工作就是想办法更进一步,只把更新过的值传到相应的控件,该怎么做还需要继续努力了,呵呵。function modify()
{
if(typeof(AJAXCbo) == 'undefined')
{
var AJAXCbo = new AjaxCallObject();
}
AJAXCbo.HookAjaxCall();
}
</script>
水平有限,难免有错误,望能和大家多多交流!
例子代码下载:/Files/fxb248/ajaxtestaaa.rar