分类:
2006-06-29 13:39:58
ajax.js 代码:
1 | /** |
2 | |
3 | * 定义 Ajax 对象, 静态方法 getTransport 方法返回一个 XMLHttp 对象 |
4 | |
5 | */ |
6 | |
7 | var Ajax = { |
8 | |
9 | getTransport: function() { |
10 | |
11 | return Try.these( |
12 | |
13 | function() {return new ActiveXObject('Msxml2.XMLHTTP')}, |
14 | |
15 | function() {return new ActiveXObject('Microsoft.XMLHTTP')}, |
16 | |
17 | function() {return new XMLHttpRequest()} |
18 | |
19 | ) || false; |
20 | |
21 | }, |
22 | |
23 | |
24 | emptyFunction: function() {} |
25 | |
26 | } |
27 | |
28 | |
29 | /** |
30 | |
31 | * 我以为此时的Ajax对象起到命名空间的作用。 |
32 | |
33 | * Ajax.Base 声明为一个基础对象类型 |
34 | |
35 | * 注意 Ajax.Base 并没有使用 Class.create() 的方式来创建,我想是因为作者并不 |
36 | |
37 | * 希望 Ajax.Base 被库使用者实例化。 |
38 | |
39 | * 作者在其他对象类型的声明中,将会继承于它。 |
40 | |
41 | * 就好像 java 中的私有抽象类 |
42 | |
43 | */ |
44 | |
45 | Ajax.Base = function() {}; |
46 | |
47 | Ajax.Base.prototype = { |
48 | |
49 | /** |
50 | |
51 | * extend (见prototype.js中的定义) 的用法真是让人耳目一新 |
52 | |
53 | * options 首先设置默认属性,然后再 extend 参数对象,那么参数对象中也有同名 |
54 | |
55 | * 的属性,那么就覆盖默认属性值。 |
56 | |
57 | * 想想如果我写这样的实现,应该类似如下: |
58 | |
59 | setOptions: function(options) { |
60 | |
61 | this.options.methed = options.methed? options.methed : 'post'; |
62 | |
63 | .......... |
64 | |
65 | } |
66 | |
67 | 我想很多时候,java 限制了 js 的创意。 |
68 | |
69 | */ |
70 | |
71 | setOptions: function(options) { |
72 | |
73 | this.options = { |
74 | |
75 | method: 'post', |
76 | |
77 | asynchronous: true, |
78 | |
79 | parameters: '' |
80 | |
81 | }.extend(options || {}); |
82 | |
83 | } |
84 | |
85 | } |
86 | |
87 | |
88 | |
89 | /** |
90 | |
91 | * Ajax.Request 封装 XmlHttp |
92 | |
93 | */ |
94 | |
95 | Ajax.Request = Class.create(); |
96 | |
97 | |
98 | /** |
99 | |
100 | * 定义四种事件(状态), 参考 |
101 | |
102 | * |
103 | |
104 | * author/dhtml/reference/properties/readystate_1.asp |
105 | |
106 | */ |
107 | |
108 | Ajax.Request.Events = |
109 | |
110 | ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; |
111 | |
112 | |
113 | /** |
114 | |
115 | * |
116 | |
117 | */ |
118 | |
119 | Ajax.Request.prototype = (new Ajax.Base()).extend({ |
120 | |
121 | initialize: function(url, options) { |
122 | |
123 | this.transport = Ajax.getTransport(); |
124 | |
125 | this.setOptions(options); |
126 | |
127 | |
128 | try { |
129 | |
130 | if (this.options.method == 'get') |
131 | |
132 | url += '?' + this.options.parameters + '&_='; |
133 | |
134 | |
135 | /** |
136 | |
137 | * 此处好像强制使用了异步方式,而不是依照 this.options.asynchronous 的值 |
138 | |
139 | */ |
140 | |
141 | this.transport.open(this.options.method, url, true); |
142 | |
143 | |
144 | /** |
145 | |
146 | * 这里提供了 XmlHttp 传输过程中每个步骤的回调函数 |
147 | |
148 | */ |
149 | |
150 | if (this.options.asynchronous) { |
151 | |
152 | this.transport.onreadystatechange = this.onStateChange.bind(this); |
153 | |
154 | setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10); |
155 | |
156 | } |
157 | |
158 | |
159 | this.transport.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); |
160 | |
161 | this.transport.setRequestHeader('X-Prototype-Version', Prototype.Version); |
162 | |
163 | |
164 | if (this.options.method == 'post') { |
165 | |
166 | this.transport.setRequestHeader('Connection', 'close'); |
167 | |
168 | this.transport.setRequestHeader('Content-type', |
169 | |
170 | 'application/x-www-form-urlencoded'); |
171 | |
172 | } |
173 | |
174 | |
175 | this.transport.send(this.options.method == 'post' ? |
176 | |
177 | this.options.parameters + '&_=' : null); |
178 | |
179 | |
180 | } catch (e) { |
181 | |
182 | } |
183 | |
184 | }, |
185 | |
186 | |
187 | onStateChange: function() { |
188 | |
189 | var readyState = this.transport.readyState; |
190 | |
191 | /** |
192 | |
193 | * 如果不是 Loading 状态,就调用回调函数 |
194 | |
195 | */ |
196 | |
197 | if (readyState != 1) |
198 | |
199 | this.respondToReadyState(this.transport.readyState); |
200 | |
201 | }, |
202 | |
203 | |
204 | /** |
205 | |
206 | * 回调函数定义在 this.options 属性中,比如: |
207 | |
208 | var option = { |
209 | |
210 | onLoaded : function(req) {...}; |
211 | |
212 | ...... |
213 | |
214 | } |
215 | |
216 | new Ajax.Request(url, option); |
217 | |
218 | */ |
219 | |
220 | respondToReadyState: function(readyState) { |
221 | |
222 | var event = Ajax.Request.Events[readyState]; |
223 | |
224 | (this.options['on' + event] || Ajax.emptyFunction)(this.transport); |
225 | |
226 | } |
227 | |
228 | }); |
229 | |
230 | |
231 | /** |
232 | |
233 | * Ajax.Updater 用于绑定一个html元素与 XmlHttp调用的返回值。 |
234 | |
235 | * 类似与 buffalo 的 bind。 |
236 | |
237 | * 如果 options 中有 insertion(from dom.js) 对象的话, |
238 | |
239 | * insertion 能提供更多的插入控制。 |
240 | |
241 | */ |
242 | |
243 | Ajax.Updater = Class.create(); |
244 | |
245 | Ajax.Updater.prototype = (new Ajax.Base()).extend({ |
246 | |
247 | initialize: function(container, url, options) { |
248 | |
249 | this.container = $(container); |
250 | |
251 | this.setOptions(options); |
252 | |
253 | |
254 | if (this.options.asynchronous) { |
255 | |
256 | this.onComplete = this.options.onComplete; |
257 | |
258 | this.options.onComplete = this.updateContent.bind(this); |
259 | |
260 | } |
261 | |
262 | |
263 | this.request = new Ajax.Request(url, this.options); |
264 | |
265 | |
266 | if (!this.options.asynchronous) |
267 | |
268 | this.updateContent(); |
269 | |
270 | }, |
271 | |
272 | |
273 | updateContent: function() { |
274 | |
275 | if (this.options.insertion) { |
276 | |
277 | new this.options.insertion(this.container, |
278 | |
279 | this.request.transport.responseText); |
280 | |
281 | } else { |
282 | |
283 | this.container.innerHTML = this.request.transport.responseText; |
284 | |
285 | } |
286 | |
287 | |
288 | if (this.onComplete) { |
289 | |
290 | setTimeout((function() {this.onComplete(this.request)}).bind(this), 10); |
291 | |
292 | } |
293 | |
294 | } |
295 |