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?});
          posted on 2006-12-21 17:29 windfree 閱讀(1008) 評論(0)  編輯  收藏 所屬分類: javascriptajax
          主站蜘蛛池模板: 佛坪县| 清水河县| 波密县| 石河子市| 马龙县| 乡宁县| 千阳县| 安化县| 射洪县| 伽师县| 瓮安县| 牡丹江市| 肇源县| 丹凤县| 曲阜市| 吕梁市| 祥云县| 文登市| 柳林县| 兴山县| 土默特右旗| 隆林| 敦化市| 乐昌市| 高碑店市| 桐城市| 峡江县| 建始县| 开阳县| 吉隆县| 韩城市| 甘孜县| 纳雍县| 三原县| 潼南县| 和平县| 兴和县| 汉中市| 彭泽县| 新晃| 万宁市|