protoype.js學習之Ajax對象(三)
??1?/**
??2??*?Ajax類,getTransport類方法返回一個xmlhttp對象,注意這里就用到了Try.these
??3??*/
??4?var?Ajax?=?{
??5?????getTransport:?function()?{
??6?????????return?Try.these(
??7?????????????????function()?{
??8?????????????????????return?new?XMLHttpRequest()
??9?????????????????},
?10?????????????????function()?{
?11?????????????????????return?new?ActiveXObject('Msxml2.XMLHTTP')
?12?????????????????},
?13?????????????????function()?{
?14?????????????????????return?new?ActiveXObject('Microsoft.XMLHTTP')
?15?????????????????}
?16?????????????????)?||?false;
?17?????},
?18?
?19?????activeRequestCount:?0
?20?}
?21?
?22?Ajax.Responders?=?{
?23?????responders:?[],
?24?
?25?????_each:?function(iterator)?{
?26?????????this.responders._each(iterator);
?27?????},
?28?
?29?????register:?function(responderToAdd)?{
?30?????????if?(!this.include(responderToAdd))
?31?????????????this.responders.push(responderToAdd);
?32?????},
?33?
?34?????unregister:?function(responderToRemove)?{
?35?????????this.responders?=?this.responders.without(responderToRemove);
?36?????},
?37?
?38?????dispatch:?function(callback,?request,?transport,?json)?{
?39?????????this.each(function(responder)?{
?40?????????????if?(responder[callback]?&&?typeof?responder[callback]?==?'function')?{
?41?????????????????try?{
?42?????????????????????responder[callback].apply(responder,?[request,?transport,?json]);
?43?????????????????}?catch?(e)?{
?44?????????????????}
?45?????????????}
?46?????????});
?47?????}
?48?};
?49?
?50?Object.extend(Ajax.Responders,?Enumerable);
?51?
?52?Ajax.Responders.register({
?53?????onCreate:?function()?{
?54?????????Ajax.activeRequestCount++;
?55?????},
?56?
?57?????onComplete:?function()?{
?58?????????Ajax.activeRequestCount--;
?59?????}
?60?});
?61?/**
?62??*??Ajax.Base?聲明為一個基礎對象類型,這里沒有使用Class.create()方法,
?63??*??因為Ajax.Base不需要實例化,只是作為基類,讓子類來繼承。
?64??*/
?65?Ajax.Base?=?function()?{
?66?};
?67?/**
?68??*?Ajax.Base提供了一些Ajax.Request?Ajax.PeriodicalUpdater共享的方法
?69??*?這些方法被放在一個基類中,避免在Ajax.Request和Ajax.PeriodicalUpdater都實現。他們繼承Ajax.Base
?70??*?The?Ajax?Object的options決定了怎樣的Ajax?Request執行,在Ajax?Request初始化時,
?71??*?options首先設置默認屬性,然后再extend參數對象,參數對象中有同名的屬性,就覆蓋默認的屬性值
?72??*?有一些屬性是Ajax請求必須的,所以在Ajax.base對象中設置了默認值
?73??*??????????????????????
?74??*/
?75?Ajax.Base.prototype?=?{
?76?????setOptions:?function(options)?{
?77?????????this.options?=?{
?78?????????????method:???????'post',
?79?????????????asynchronous:?true,
?80?????????????contentType:??'application/x-www-form-urlencoded',
?81?????????????parameters:???''
?82?????????}
?83?????????Object.extend(this.options,?options?||?{});
?84?????},
?85?????//下面兩個方法判斷是否正常返回了響應
?86?????responseIsSuccess:?function()?{
?87?????????return?this.transport.status?==?undefined
?88?????????????????||?this.transport.status?==?0
?89?????????????????||?(this.transport.status?>=?200?&&?this.transport.status?<?300);
?90?????},
?91?
?92?????responseIsFailure:?function()?{
?93?????????return?!this.responseIsSuccess();
?94?????}
?95?}
?96?//Request對象,這回用了Class.create(),因為下面initialize初始化
?97?Ajax.Request?=?Class.create();
?98?
?99?//Events對象,對應XMLHttpRequest中的請求狀態
100?//Uninitialized:?未初始化;Loading:?正在加載?;Loaded:已加載;Interactive:交互中;Complete:完成
101?
102?Ajax.Request.Events?=
103?['Uninitialized',?'Loading',?'Loaded',?'Interactive',?'Complete'];
104?
105?/**
106??*?Ajax.Request繼承了Ajax.Base,并且添加了一個構造方法(initialize)
107??*?initialize方法是必須的,因為Ajax請求屬性繼承Ajax.Base的后,至少還需要一個請求URL,才能工作。
108??*?有趣的是,初始化方法中調用了一個request的方法,所以請求被立刻執行,當Ajax.Request實例被初始化時。
109??*/
110?Ajax.Request.prototype?=?Object.extend(new?Ajax.Base(),?{
111?????initialize:?function(url,?options)?{
112?????????this.transport?=?Ajax.getTransport();
113?????????this.setOptions(options);//設置請求的的屬性,調用Ajax.Base方法
114?????????this.request(url);
115?????},
116?
117?/**
118??*?在Prototype中,一個Ajax.Request是一個到服務器的一個異步的請求,一個沒有處理的response返回給調用者。
119??*/
120?????request:?function(url)?{
121?????????//從Ajax.Base’s?options對象中,獲得請求參數字符串,如果this.options.parameters為空,請求參數被設空。
122?????????//如果參數不為空,在請求參數后添加"&_=",應該是確保url的唯一性,避免瀏覽器緩存請求的結果。
123?????????var?parameters?=?this.options.parameters?||?'';
124?????????if?(parameters.length?>?0)?parameters?+=?'&_=';
125?????????
126?????????/*?Simulate?other?verbs?over?post?*/
127?????????if?(this.options.method?!=?'get'?&&?this.options.method?!=?'post')?{
128?????????????parameters?+=?(parameters.length?>?0???'&'?:?'')?+?'_method='?+?this.options.method;
129?????????????this.options.method?=?'post';
130?????????}
131?????????//下面請求將被發送,為了捕捉網絡的異常,相關的代碼被放到try塊中
132?????????try?{
133?????????????this.url?=?url;
134?????????????//如果請求方法是get,參數將被連接到URL后
135?????????????if?(this.options.method?==?'get'?&&?parameters.length?>?0)
136?????????????????this.url?+=?(this.url.match(/\?/)???'&'?:?'?')?+?parameters;
137?????????????????
138?????????????//onCreate事件被發給Responders對象,
139?????????????//請求開始?,Ajax.Responders中注冊onCreate的方法就會執行
140?????????????Ajax.Responders.dispatch('onCreate',?this,?this.transport);
141?????????????
142?????????????//XMLHttpRequest.open()方法,建立對服務器的調用。
143?????????????this.transport.open(this.options.method,?this.url,
144?????????????????????this.options.asynchronous);
145?????????????????????
146?????????????//這里提供了XMLHttpRequest傳輸過程中每個步驟的回調函數
147?????????????//每10ms會調用一次這個方法,傳的參數是Loading
148?????????????if?(this.options.asynchronous)
149?????????????????setTimeout(function()?{
150?????????????????????this.respondToReadyState(1)
151?????????????????}.bind(this),?10);
152?????????????????
153?????????????//XMLHttpRequest狀態改變時,onStateChange方法調用。
154?????????????this.transport.onreadystatechange?=?this.onStateChange.bind(this);
155?????????????
156?????????????//設置request頭
157?????????????this.setRequestHeaders();
158?????????????
159?????????????//如果方法是post,參數被作為POST?headers?被send()方法發送出去,否則,什么也不發送。
160?????????????var?body?=?this.options.postBody???this.options.postBody?:?parameters;
161?????????????this.transport.send(this.options.method?==?'post'???body?:?null);
162?
163?????????????/*?Force?Firefox?to?handle?ready?state?4?for?synchronous?requests?*/
164?????????????if?(!this.options.asynchronous?&&?this.transport.overrideMimeType)
165?????????????????this.onStateChange();
166?
167?????????}?catch?(e)?{
168?????????????
169?????????????this.dispatchException(e);
170?????????}
171?????},
172?????
173?????//設置request頭
174?????setRequestHeaders:?function()?{
175?????????//默認的請求頭被建立,requestHeaders是個數組
176?????????var?requestHeaders?=
177?????????????????['X-Requested-With',?'XMLHttpRequest',
178?????????????????????????'X-Prototype-Version',?Prototype.Version,
179?????????????????????????'Accept',?'text/javascript,?text/html,?application/xml,?text/xml,?*/*'];
180?????????//如果請求用post方法,Content-type將被添加到請求頭中
181?????????if?(this.options.method?==?'post')?{
182?????????????requestHeaders.push('Content-type',?this.options.contentType);
183?
184?????????????/*?Force?"Connection:?close"?for?Mozilla?browsers?to?work?around
185?????????????????????????*?a?bug?where?XMLHttpReqeuest?sends?an?incorrect?Content-length
186?????????????????????????*?header.?See?Mozilla?Bugzilla?#246651.
187?????????????????????????*/
188?????????????if?(this.transport.overrideMimeType)
189?????????????????requestHeaders.push('Connection',?'close');
190?????????}
191?????????//如果在request的options中有requestHeaders屬性
192?????????//它們將添加到requestHeaders
193?????????if?(this.options.requestHeaders)
194?????????????requestHeaders.push.apply(requestHeaders,?this.options.requestHeaders);
195?????????????
196?????????//requestHeaders中每一個key-value對,通過XMLhttpRequest的setRequestHeader方法設置請求實例的請求頭屬性中
197?????????
198?????????for?(var?i?=?0;?i?<?requestHeaders.length;?i?+=?2)
199?????????????this.transport.setRequestHeader(requestHeaders[i],?requestHeaders[i?+?1]);
200?????},
201?????/**
202??????*?狀態變化,并且readyState不是Loading時就調用回調函數。
203??????*/
204?????onStateChange:?function()?{
205?????????var?readyState?=?this.transport.readyState;
206?????????if?(readyState?!=?1)
207?????????????this.respondToReadyState(this.transport.readyState);
208?????},
209?????
210?????//根據name取得XMLHttpRequest中指定的HTTP頭
211?????header:?function(name)?{
212?????????try?{
213?????????????return?this.transport.getResponseHeader(name);
214?????????}?catch?(e)?{
215?????????}
216?????},
217?????//執行HTTP頭中'X-JSON'對應的內容
218?????evalJSON:?function()?{
219?????????try?{
220?????????????return?eval('('?+?this.header('X-JSON')?+?')');
221?????????}?catch?(e)?{
222?????????}
223?????},
224?????
225?/**
226??*?執行包含在response?text中的腳本,并返回結果
227??*/
228?????evalResponse:?function()?{
229?????????try?{
230?????????????return?eval(this.transport.responseText);
231?????????}?catch?(e)?{
232?????????????this.dispatchException(e);
233?????????}
234?????},
235?
236?????respondToReadyState:?function(readyState)?{
237?????????//readyState將被映射到Events定義得事件
238?????????var?event?=?Ajax.Request.Events[readyState];
239?????????//獲取當前的XMLHttpRequest對象,執行HTTP頭中'X-JSON'對應的內容
240?????????var?transport?=?this.transport,?json?=?this.evalJSON();
241?????????//如果event?==?'Complete',response響應被接受。
242?????????if?(event?==?'Complete')?{
243?????????????try?{//按優先級觸發事件?如果處理函數不存在則執行emptyFunction忽略此事件
244?????????????????(this.options['on'?+?this.transport.status]
245?????????????????????????||?this.options['on'?+?(this.responseIsSuccess()???'Success'?:?'Failure')]
246?????????????????????????||?Prototype.emptyFunction)(transport,?json);
247?????????????}?catch?(e)?{
248?????????????????this.dispatchException(e);
249?????????????}
250?????????????//如果響應的Content-type是?text/javascript,prototype將用evalResponse方法執行包含在請求的js代碼
251?????????????if?((this.header('Content-type')?||?'').match(/^text\/javascript/i))
252?????????????????this.evalResponse();
253?????????}
254?????//XMLHttpRequest狀態的變化,onLoaded,?onInteractive,?onComplete方法調用并傳json對象
255?????//同時事件還發送給Responders對象
256?????????try?{
257?????????????(this.options['on'?+?event]?||?Prototype.emptyFunction)(transport,?json);
258?????????????Ajax.Responders.dispatch('on'?+?event,?this,?transport,?json);
259?????????}?catch?(e)?{
260?????????????this.dispatchException(e);
261?????????}
262?
263?????????/*?Avoid?memory?leak?in?MSIE:?clean?up?the?oncomplete?event?handler?*/
264?????????if?(event?==?'Complete')
265?????????????this.transport.onreadystatechange?=?Prototype.emptyFunction;
266?????},
267?
268?????dispatchException:?function(exception)?{//?處理異常,Prototype.emptyFunction為默認的處理方法
269?????????(this.options.onException?||?Prototype.emptyFunction)(this,?exception);
270?????????Ajax.Responders.dispatch('onException',?this,?exception);
271?????}
272?});
273?
274?/**
275??*?Ajax.Updater繼承Ajax.Request,是一格Ajax.Request功能增強類。它執行和Ajax.Request同樣的任務,
276??*?但是response不僅可以傳遞個onComplete處理,還可以響應后的HTML結果自動放到指定的container
277??*/
278?Ajax.Updater?=?Class.create();
279?
280?Object.extend(Object.extend(Ajax.Updater.prototype,?Ajax.Request.prototype),?{
281?????//初始化方法比Ajax.Request多了一個container參數,response
282?????//將被放置在container中
283?????initialize:?function(container,?url,?options)?{
284?????????//success:請求響應成功時,接收response的容器對象
285?????????this.containers?=?{
286?????????????success:?container.success???$(container.success)?:?$(container),
287?????????????failure:?container.failure???$(container.failure)?:
288??????????????????????(container.success???null?:?$(container))
289?????????}
290?
291?????????this.transport?=?Ajax.getTransport();
292?????????this.setOptions(options);
293?
294?????????var?onComplete?=?this.options.onComplete?||?Prototype.emptyFunction;
295?????????
296?????????//onComplete擴展包含一個對updateContent()方法的調用
297?????????this.options.onComplete?=?(function(transport,?object)?{
298?????????????this.updateContent();
299?????????????onComplete(transport,?object);
300?????????}).bind(this);
301?
302?????????this.request(url);
303?????},
304?
305?????updateContent:?function()?{
306?????????//如果AJAX請求響應成功,則獲取接收的容器對象,否則獲取請求錯誤時的容器對象。
307?????????var?receiver?=?this.responseIsSuccess()??
308????????????????????????this.containers.success?:?this.containers.failure;
309?????????var?response?=?this.transport.responseText;
310?????????
311?????????//如果this.options.evalScripts為false,從response移出所有的JavaScript腳本
312?????????if?(!this.options.evalScripts)
313?????????????response?=?response.stripScripts();
314?????
315?????????//如果接收對象存在
316?????????if?(receiver)?{
317?????????????//判斷是將響應文本insertion還是update到receiver對象中
318?????????????if?(this.options.insertion)?{
319?????????????????new?this.options.insertion(receiver,?response);
320?????????????}?else?{
321?????????????????Element.update(receiver,?response);
322?????????????}
323?????????}
324?
325?????????if?(this.responseIsSuccess())?{
326?????????????if?(this.onComplete)
327?????????????????setTimeout(this.onComplete.bind(this),?10);
328?????????}
329?????}
330?});
331?
332?/**
333??*?Ajax.PeriodicalUpdater對Ajax.Updater進行包裝。對Ajax.Updater添加了一個定時器。
334??*?周期性的執行Ajax.Updater對象來更新DOM?element
335??*/
336?Ajax.PeriodicalUpdater?=?Class.create();
337?Ajax.PeriodicalUpdater.prototype?=?Object.extend(new?Ajax.Base(),?{
338?????initialize:?function(container,?url,?options)?{
339?????????this.setOptions(options);
340?????????this.onComplete?=?this.options.onComplete;
341?
342?????????this.frequency?=?(this.options.frequency?||?2);//兩次刷新之間的間隔?
343?????????this.decay?=?(this.options.decay?||?1);//重負執行任務的時候保持的衰敗水平
344?
345?????????this.updater?=?{};
346?????????this.container?=?container;
347?????????this.url?=?url;
348?
349?????????this.start();//開始Ajax.Updater循環
350?????},
351?
352?????start:?function()?{
353?????????//使options的onComplete的指針指向當前的Ajax.PeriodicalUpdater對的updateComplete方法。
354?????????this.options.onComplete?=?this.updateComplete.bind(this);
355?????????this.onTimerEvent();
356?????},
357?
358?????stop:?function()?{
359?????????this.updater.options.onComplete?=?undefined;
360?????????clearTimeout(this.timer);
361?????????(this.onComplete?||?Prototype.emptyFunction).apply(this,?arguments);
362?????},
363?
364?????updateComplete:?function(request)?{
365?????????if?(this.options.decay)?{
366?????????????this.decay?=?(request.responseText?==?this.lastText??
367???????????????????????????this.decay?*?this.options.decay?:?1);
368?
369?????????????this.lastText?=?request.responseText;
370?????????}
371?????????//?返回一個標志(timer)留作被stop函數調用,?以停止定時器
372?????????this.timer?=?setTimeout(this.onTimerEvent.bind(this),
373?????????????????this.decay?*?this.frequency?*?1000);
374?????},
375?
376?????onTimerEvent:?function()?{
377?????????this.updater?=?new?Ajax.Updater(this.container,?this.url,?this.options);
378?????}
379?});
??2??*?Ajax類,getTransport類方法返回一個xmlhttp對象,注意這里就用到了Try.these
??3??*/
??4?var?Ajax?=?{
??5?????getTransport:?function()?{
??6?????????return?Try.these(
??7?????????????????function()?{
??8?????????????????????return?new?XMLHttpRequest()
??9?????????????????},
?10?????????????????function()?{
?11?????????????????????return?new?ActiveXObject('Msxml2.XMLHTTP')
?12?????????????????},
?13?????????????????function()?{
?14?????????????????????return?new?ActiveXObject('Microsoft.XMLHTTP')
?15?????????????????}
?16?????????????????)?||?false;
?17?????},
?18?
?19?????activeRequestCount:?0
?20?}
?21?
?22?Ajax.Responders?=?{
?23?????responders:?[],
?24?
?25?????_each:?function(iterator)?{
?26?????????this.responders._each(iterator);
?27?????},
?28?
?29?????register:?function(responderToAdd)?{
?30?????????if?(!this.include(responderToAdd))
?31?????????????this.responders.push(responderToAdd);
?32?????},
?33?
?34?????unregister:?function(responderToRemove)?{
?35?????????this.responders?=?this.responders.without(responderToRemove);
?36?????},
?37?
?38?????dispatch:?function(callback,?request,?transport,?json)?{
?39?????????this.each(function(responder)?{
?40?????????????if?(responder[callback]?&&?typeof?responder[callback]?==?'function')?{
?41?????????????????try?{
?42?????????????????????responder[callback].apply(responder,?[request,?transport,?json]);
?43?????????????????}?catch?(e)?{
?44?????????????????}
?45?????????????}
?46?????????});
?47?????}
?48?};
?49?
?50?Object.extend(Ajax.Responders,?Enumerable);
?51?
?52?Ajax.Responders.register({
?53?????onCreate:?function()?{
?54?????????Ajax.activeRequestCount++;
?55?????},
?56?
?57?????onComplete:?function()?{
?58?????????Ajax.activeRequestCount--;
?59?????}
?60?});
?61?/**
?62??*??Ajax.Base?聲明為一個基礎對象類型,這里沒有使用Class.create()方法,
?63??*??因為Ajax.Base不需要實例化,只是作為基類,讓子類來繼承。
?64??*/
?65?Ajax.Base?=?function()?{
?66?};
?67?/**
?68??*?Ajax.Base提供了一些Ajax.Request?Ajax.PeriodicalUpdater共享的方法
?69??*?這些方法被放在一個基類中,避免在Ajax.Request和Ajax.PeriodicalUpdater都實現。他們繼承Ajax.Base
?70??*?The?Ajax?Object的options決定了怎樣的Ajax?Request執行,在Ajax?Request初始化時,
?71??*?options首先設置默認屬性,然后再extend參數對象,參數對象中有同名的屬性,就覆蓋默認的屬性值
?72??*?有一些屬性是Ajax請求必須的,所以在Ajax.base對象中設置了默認值
?73??*??????????????????????
?74??*/
?75?Ajax.Base.prototype?=?{
?76?????setOptions:?function(options)?{
?77?????????this.options?=?{
?78?????????????method:???????'post',
?79?????????????asynchronous:?true,
?80?????????????contentType:??'application/x-www-form-urlencoded',
?81?????????????parameters:???''
?82?????????}
?83?????????Object.extend(this.options,?options?||?{});
?84?????},
?85?????//下面兩個方法判斷是否正常返回了響應
?86?????responseIsSuccess:?function()?{
?87?????????return?this.transport.status?==?undefined
?88?????????????????||?this.transport.status?==?0
?89?????????????????||?(this.transport.status?>=?200?&&?this.transport.status?<?300);
?90?????},
?91?
?92?????responseIsFailure:?function()?{
?93?????????return?!this.responseIsSuccess();
?94?????}
?95?}
?96?//Request對象,這回用了Class.create(),因為下面initialize初始化
?97?Ajax.Request?=?Class.create();
?98?
?99?//Events對象,對應XMLHttpRequest中的請求狀態
100?//Uninitialized:?未初始化;Loading:?正在加載?;Loaded:已加載;Interactive:交互中;Complete:完成
101?
102?Ajax.Request.Events?=
103?['Uninitialized',?'Loading',?'Loaded',?'Interactive',?'Complete'];
104?
105?/**
106??*?Ajax.Request繼承了Ajax.Base,并且添加了一個構造方法(initialize)
107??*?initialize方法是必須的,因為Ajax請求屬性繼承Ajax.Base的后,至少還需要一個請求URL,才能工作。
108??*?有趣的是,初始化方法中調用了一個request的方法,所以請求被立刻執行,當Ajax.Request實例被初始化時。
109??*/
110?Ajax.Request.prototype?=?Object.extend(new?Ajax.Base(),?{
111?????initialize:?function(url,?options)?{
112?????????this.transport?=?Ajax.getTransport();
113?????????this.setOptions(options);//設置請求的的屬性,調用Ajax.Base方法
114?????????this.request(url);
115?????},
116?
117?/**
118??*?在Prototype中,一個Ajax.Request是一個到服務器的一個異步的請求,一個沒有處理的response返回給調用者。
119??*/
120?????request:?function(url)?{
121?????????//從Ajax.Base’s?options對象中,獲得請求參數字符串,如果this.options.parameters為空,請求參數被設空。
122?????????//如果參數不為空,在請求參數后添加"&_=",應該是確保url的唯一性,避免瀏覽器緩存請求的結果。
123?????????var?parameters?=?this.options.parameters?||?'';
124?????????if?(parameters.length?>?0)?parameters?+=?'&_=';
125?????????
126?????????/*?Simulate?other?verbs?over?post?*/
127?????????if?(this.options.method?!=?'get'?&&?this.options.method?!=?'post')?{
128?????????????parameters?+=?(parameters.length?>?0???'&'?:?'')?+?'_method='?+?this.options.method;
129?????????????this.options.method?=?'post';
130?????????}
131?????????//下面請求將被發送,為了捕捉網絡的異常,相關的代碼被放到try塊中
132?????????try?{
133?????????????this.url?=?url;
134?????????????//如果請求方法是get,參數將被連接到URL后
135?????????????if?(this.options.method?==?'get'?&&?parameters.length?>?0)
136?????????????????this.url?+=?(this.url.match(/\?/)???'&'?:?'?')?+?parameters;
137?????????????????
138?????????????//onCreate事件被發給Responders對象,
139?????????????//請求開始?,Ajax.Responders中注冊onCreate的方法就會執行
140?????????????Ajax.Responders.dispatch('onCreate',?this,?this.transport);
141?????????????
142?????????????//XMLHttpRequest.open()方法,建立對服務器的調用。
143?????????????this.transport.open(this.options.method,?this.url,
144?????????????????????this.options.asynchronous);
145?????????????????????
146?????????????//這里提供了XMLHttpRequest傳輸過程中每個步驟的回調函數
147?????????????//每10ms會調用一次這個方法,傳的參數是Loading
148?????????????if?(this.options.asynchronous)
149?????????????????setTimeout(function()?{
150?????????????????????this.respondToReadyState(1)
151?????????????????}.bind(this),?10);
152?????????????????
153?????????????//XMLHttpRequest狀態改變時,onStateChange方法調用。
154?????????????this.transport.onreadystatechange?=?this.onStateChange.bind(this);
155?????????????
156?????????????//設置request頭
157?????????????this.setRequestHeaders();
158?????????????
159?????????????//如果方法是post,參數被作為POST?headers?被send()方法發送出去,否則,什么也不發送。
160?????????????var?body?=?this.options.postBody???this.options.postBody?:?parameters;
161?????????????this.transport.send(this.options.method?==?'post'???body?:?null);
162?
163?????????????/*?Force?Firefox?to?handle?ready?state?4?for?synchronous?requests?*/
164?????????????if?(!this.options.asynchronous?&&?this.transport.overrideMimeType)
165?????????????????this.onStateChange();
166?
167?????????}?catch?(e)?{
168?????????????
169?????????????this.dispatchException(e);
170?????????}
171?????},
172?????
173?????//設置request頭
174?????setRequestHeaders:?function()?{
175?????????//默認的請求頭被建立,requestHeaders是個數組
176?????????var?requestHeaders?=
177?????????????????['X-Requested-With',?'XMLHttpRequest',
178?????????????????????????'X-Prototype-Version',?Prototype.Version,
179?????????????????????????'Accept',?'text/javascript,?text/html,?application/xml,?text/xml,?*/*'];
180?????????//如果請求用post方法,Content-type將被添加到請求頭中
181?????????if?(this.options.method?==?'post')?{
182?????????????requestHeaders.push('Content-type',?this.options.contentType);
183?
184?????????????/*?Force?"Connection:?close"?for?Mozilla?browsers?to?work?around
185?????????????????????????*?a?bug?where?XMLHttpReqeuest?sends?an?incorrect?Content-length
186?????????????????????????*?header.?See?Mozilla?Bugzilla?#246651.
187?????????????????????????*/
188?????????????if?(this.transport.overrideMimeType)
189?????????????????requestHeaders.push('Connection',?'close');
190?????????}
191?????????//如果在request的options中有requestHeaders屬性
192?????????//它們將添加到requestHeaders
193?????????if?(this.options.requestHeaders)
194?????????????requestHeaders.push.apply(requestHeaders,?this.options.requestHeaders);
195?????????????
196?????????//requestHeaders中每一個key-value對,通過XMLhttpRequest的setRequestHeader方法設置請求實例的請求頭屬性中
197?????????
198?????????for?(var?i?=?0;?i?<?requestHeaders.length;?i?+=?2)
199?????????????this.transport.setRequestHeader(requestHeaders[i],?requestHeaders[i?+?1]);
200?????},
201?????/**
202??????*?狀態變化,并且readyState不是Loading時就調用回調函數。
203??????*/
204?????onStateChange:?function()?{
205?????????var?readyState?=?this.transport.readyState;
206?????????if?(readyState?!=?1)
207?????????????this.respondToReadyState(this.transport.readyState);
208?????},
209?????
210?????//根據name取得XMLHttpRequest中指定的HTTP頭
211?????header:?function(name)?{
212?????????try?{
213?????????????return?this.transport.getResponseHeader(name);
214?????????}?catch?(e)?{
215?????????}
216?????},
217?????//執行HTTP頭中'X-JSON'對應的內容
218?????evalJSON:?function()?{
219?????????try?{
220?????????????return?eval('('?+?this.header('X-JSON')?+?')');
221?????????}?catch?(e)?{
222?????????}
223?????},
224?????
225?/**
226??*?執行包含在response?text中的腳本,并返回結果
227??*/
228?????evalResponse:?function()?{
229?????????try?{
230?????????????return?eval(this.transport.responseText);
231?????????}?catch?(e)?{
232?????????????this.dispatchException(e);
233?????????}
234?????},
235?
236?????respondToReadyState:?function(readyState)?{
237?????????//readyState將被映射到Events定義得事件
238?????????var?event?=?Ajax.Request.Events[readyState];
239?????????//獲取當前的XMLHttpRequest對象,執行HTTP頭中'X-JSON'對應的內容
240?????????var?transport?=?this.transport,?json?=?this.evalJSON();
241?????????//如果event?==?'Complete',response響應被接受。
242?????????if?(event?==?'Complete')?{
243?????????????try?{//按優先級觸發事件?如果處理函數不存在則執行emptyFunction忽略此事件
244?????????????????(this.options['on'?+?this.transport.status]
245?????????????????????????||?this.options['on'?+?(this.responseIsSuccess()???'Success'?:?'Failure')]
246?????????????????????????||?Prototype.emptyFunction)(transport,?json);
247?????????????}?catch?(e)?{
248?????????????????this.dispatchException(e);
249?????????????}
250?????????????//如果響應的Content-type是?text/javascript,prototype將用evalResponse方法執行包含在請求的js代碼
251?????????????if?((this.header('Content-type')?||?'').match(/^text\/javascript/i))
252?????????????????this.evalResponse();
253?????????}
254?????//XMLHttpRequest狀態的變化,onLoaded,?onInteractive,?onComplete方法調用并傳json對象
255?????//同時事件還發送給Responders對象
256?????????try?{
257?????????????(this.options['on'?+?event]?||?Prototype.emptyFunction)(transport,?json);
258?????????????Ajax.Responders.dispatch('on'?+?event,?this,?transport,?json);
259?????????}?catch?(e)?{
260?????????????this.dispatchException(e);
261?????????}
262?
263?????????/*?Avoid?memory?leak?in?MSIE:?clean?up?the?oncomplete?event?handler?*/
264?????????if?(event?==?'Complete')
265?????????????this.transport.onreadystatechange?=?Prototype.emptyFunction;
266?????},
267?
268?????dispatchException:?function(exception)?{//?處理異常,Prototype.emptyFunction為默認的處理方法
269?????????(this.options.onException?||?Prototype.emptyFunction)(this,?exception);
270?????????Ajax.Responders.dispatch('onException',?this,?exception);
271?????}
272?});
273?
274?/**
275??*?Ajax.Updater繼承Ajax.Request,是一格Ajax.Request功能增強類。它執行和Ajax.Request同樣的任務,
276??*?但是response不僅可以傳遞個onComplete處理,還可以響應后的HTML結果自動放到指定的container
277??*/
278?Ajax.Updater?=?Class.create();
279?
280?Object.extend(Object.extend(Ajax.Updater.prototype,?Ajax.Request.prototype),?{
281?????//初始化方法比Ajax.Request多了一個container參數,response
282?????//將被放置在container中
283?????initialize:?function(container,?url,?options)?{
284?????????//success:請求響應成功時,接收response的容器對象
285?????????this.containers?=?{
286?????????????success:?container.success???$(container.success)?:?$(container),
287?????????????failure:?container.failure???$(container.failure)?:
288??????????????????????(container.success???null?:?$(container))
289?????????}
290?
291?????????this.transport?=?Ajax.getTransport();
292?????????this.setOptions(options);
293?
294?????????var?onComplete?=?this.options.onComplete?||?Prototype.emptyFunction;
295?????????
296?????????//onComplete擴展包含一個對updateContent()方法的調用
297?????????this.options.onComplete?=?(function(transport,?object)?{
298?????????????this.updateContent();
299?????????????onComplete(transport,?object);
300?????????}).bind(this);
301?
302?????????this.request(url);
303?????},
304?
305?????updateContent:?function()?{
306?????????//如果AJAX請求響應成功,則獲取接收的容器對象,否則獲取請求錯誤時的容器對象。
307?????????var?receiver?=?this.responseIsSuccess()??
308????????????????????????this.containers.success?:?this.containers.failure;
309?????????var?response?=?this.transport.responseText;
310?????????
311?????????//如果this.options.evalScripts為false,從response移出所有的JavaScript腳本
312?????????if?(!this.options.evalScripts)
313?????????????response?=?response.stripScripts();
314?????
315?????????//如果接收對象存在
316?????????if?(receiver)?{
317?????????????//判斷是將響應文本insertion還是update到receiver對象中
318?????????????if?(this.options.insertion)?{
319?????????????????new?this.options.insertion(receiver,?response);
320?????????????}?else?{
321?????????????????Element.update(receiver,?response);
322?????????????}
323?????????}
324?
325?????????if?(this.responseIsSuccess())?{
326?????????????if?(this.onComplete)
327?????????????????setTimeout(this.onComplete.bind(this),?10);
328?????????}
329?????}
330?});
331?
332?/**
333??*?Ajax.PeriodicalUpdater對Ajax.Updater進行包裝。對Ajax.Updater添加了一個定時器。
334??*?周期性的執行Ajax.Updater對象來更新DOM?element
335??*/
336?Ajax.PeriodicalUpdater?=?Class.create();
337?Ajax.PeriodicalUpdater.prototype?=?Object.extend(new?Ajax.Base(),?{
338?????initialize:?function(container,?url,?options)?{
339?????????this.setOptions(options);
340?????????this.onComplete?=?this.options.onComplete;
341?
342?????????this.frequency?=?(this.options.frequency?||?2);//兩次刷新之間的間隔?
343?????????this.decay?=?(this.options.decay?||?1);//重負執行任務的時候保持的衰敗水平
344?
345?????????this.updater?=?{};
346?????????this.container?=?container;
347?????????this.url?=?url;
348?
349?????????this.start();//開始Ajax.Updater循環
350?????},
351?
352?????start:?function()?{
353?????????//使options的onComplete的指針指向當前的Ajax.PeriodicalUpdater對的updateComplete方法。
354?????????this.options.onComplete?=?this.updateComplete.bind(this);
355?????????this.onTimerEvent();
356?????},
357?
358?????stop:?function()?{
359?????????this.updater.options.onComplete?=?undefined;
360?????????clearTimeout(this.timer);
361?????????(this.onComplete?||?Prototype.emptyFunction).apply(this,?arguments);
362?????},
363?
364?????updateComplete:?function(request)?{
365?????????if?(this.options.decay)?{
366?????????????this.decay?=?(request.responseText?==?this.lastText??
367???????????????????????????this.decay?*?this.options.decay?:?1);
368?
369?????????????this.lastText?=?request.responseText;
370?????????}
371?????????//?返回一個標志(timer)留作被stop函數調用,?以停止定時器
372?????????this.timer?=?setTimeout(this.onTimerEvent.bind(this),
373?????????????????this.decay?*?this.frequency?*?1000);
374?????},
375?
376?????onTimerEvent:?function()?{
377?????????this.updater?=?new?Ajax.Updater(this.container,?this.url,?this.options);
378?????}
379?});