posts - 1,  comments - 1,  trackbacks - 0

           



          //-------------------- mContentLoader.js
          /*
           *        Ajax的輔助對象,執(zhí)行所有與Ajax處理相關(guān)的工作
           *
           
          */

          var net = new Object();

          net.READY_STATE_UNINITIALIZED
          = 0;
          net.READY_STATE_LOADING      
          = 1;
          net.READY_STATE_LOADED       
          = 2;
          net.READY_STATE_INTERACTIVE  
          = 3;
          net.READY_STATE_COMPLETE     
          = 4;

          /*
           *     構(gòu)造函數(shù)
           *     component指定這個輔助所提供的對象,并假定component有一個ajaxUpdate()方法處理響應(yīng),一個handleError()方法處理錯誤
           *     url指定這個輔助從服務(wù)器端獲取數(shù)據(jù)時調(diào)用的url
           *     mothd指定HTTP請求方法,有效值有GET和POST
           *     requestParams以key=value格式的字符串組形勢指定一組傳遞給請求的請求參數(shù)
           
          */

          net.ContentLoader 
          = function( component, url, method, requestParams ) {
             
          this.component     = component;
             
          this.url           = url;
             
          this.requestParams = requestParams;
             
          this.method        = method;
          }


          net.ContentLoader.prototype 
          = {

             getTransport: 
          function() {
                
          var transport;
                
          if ( window.XMLHttpRequest )
                   transport 
          = new XMLHttpRequest();
                
          else if ( window.ActiveXObject ) {
                   
          try {
                      transport 
          = new ActiveXObject('Msxml2.XMLHTTP');
                   }

                   
          catch(err) {
                      transport 
          = new ActiveXObject('Microsoft.XMLHTTP');
                   }

                }

                
          return transport;
             }
          ,

             sendRequest: 
          function() {

                
          //if ( window.netscape && window.netscape.security.PrivilegeManager.enablePrivilege)
                //   netscape.security.PrivilegeManager.enablePrivilege('UniversalBrowserRead');

                
          var requestParams = []
                
          for ( var i = 0 ; i < arguments.length ;  i++ )
                   requestParams.push(arguments[i]);

                
          var oThis = this;
                
          var request = this.getTransport();
                request.open( 
          this.method, this.url, true );
                request.setRequestHeader( 'Content
          -Type', 'application/x-www-form-urlencoded');
                request.onreadystatechange 
          = function() { oThis.handleAjaxResponse(request) };
                request.send( 
          this.queryString(requestParams) );
            }
          ,

            queryString: 
          function(args) {

               
          var requestParams = [];
               
          for ( var i = 0 ; i < this.requestParams.length ; i++ )
                  requestParams.push(
          this.requestParams[i]);
               
          for ( var j = 0 ; j < args.length ; j++ )
                  requestParams.push(args[j]);

               
          var queryString = "";
               
          if ( requestParams && requestParams.length > 0 ) {
                  
          for ( var i = 0 ; i < requestParams.length ; i++ )
                     queryString 
          += requestParams[i] + '&';
                  queryString 
          = queryString.substring(0, queryString.length-1);
               }

               
          return queryString;
            }
          ,

            handleAjaxResponse: 
          function(request) {
               
          if ( request.readyState == net.READY_STATE_COMPLETE ) {
                  
          if ( this.isSuccess(request) )
                     
          this.component.ajaxUpdate(request);
                  
          else
                     
          this.component.handleError(request);
               }

            }
          ,

            isSuccess: 
          function(request) {
              
          return  request.status == 0
                  
          || (request.status >= 200 && request.status < 300);
            }


          }
          ;


          //-------------------- mTextSuggest.js
          /*
           *    輸入前提示組件,可重用在大部分需要這些功能的應(yīng)用中,為此考慮一下特征
           *    1.不修改HTML標(biāo)記,只簡單修改head部分來注入組件行為
           *    2.組件能夠使用不同的URL,并為所有配置選項(xiàng)提供合理的默認(rèn)值
           *      3.組件不引入任何全局變量,防止全局變量混亂
           *    4.組件使用開源框架,以減少編碼工作量,并提高方案的質(zhì)量和健壯性
           
          */

           
           
           
          /*
           ************************************創(chuàng)建TextSuggest***********************************************
           
          */

          TextSuggest 
          = Class.create();

          TextSuggest.prototype 
          = {

          /*
           *    構(gòu)造函數(shù)
           *    andId:要附加提示行為的文本字段的ID
           *    url:處理請求的服務(wù)器URL
           *    options:options對象為組件的每一個配置參數(shù)提供一個屬性
           
          */

             initialize: 
          function(anId, url, options) {
                
          this.id          = anId;
                
          this.textInput   = $(this.id);
                
                
          //檢測瀏覽器類型
                var browser = navigator.userAgent.toLowerCase();
                
          this.isIE        = browser.indexOf("msie"!= -1;
                
          this.isOpera     = browser.indexOf("opera")!= -1;
                
                
          this.suggestions = [];
                
          this.setOptions(options);
                
          this.initAjax(url);

                
          this.injectSuggestBehavior();
             }
          ,


          /*
           *    為options每個屬性都指定一個默認(rèn)值
           *    然后,使用在構(gòu)造時傳入的options對象調(diào)用Prototype庫的extend()方法,來覆蓋默認(rèn)值
           *    最后結(jié)果是一個合并的options對象,包含默認(rèn)值和指定的覆蓋值
           
          */

             setOptions: 
          function(options) {
                
          this.options = {
                   suggestDivClassName: 'suggestDiv',   
          //指定用來保存提示的生成div元素的css類名
                   suggestionClassName: 'suggestion',   //指定用來保存每一條提示的生成span元素的css類名
                   matchClassName     : 'match',        //指定用來保存匹配用戶輸入內(nèi)容的提示部分的span元素的css類名
                   matchTextWidth     :  true,          //用來指示為提示生成的div是否需要將自身大小設(shè)置為與它附加到的文本字段的寬度匹配
                   selectionColor     : '#b1c09c',      //為選中的提示的背景顏色指定一個十六進(jìn)制值
                   matchAnywhere      : false,          //指定匹配是只查找字符串的開始位置,還是查找任意位置
                   ignoreCase         : false,          //指定匹配是否是區(qū)別大小寫的 
                   count              : 10              //顯示最大提示數(shù)量         
                }
          .extend(options || {});
             }
          ,


          /*
           ************************************支持Ajax***********************************************
           
          */


          //-----------------------文本提示--發(fā)送Ajax請求
          /*
           *    發(fā)送請求限制
           *    如果沒有正在處理的請求,就調(diào)用callRicoAjaxEngine()來發(fā)送請求,反之不發(fā)送
           *    通過設(shè)置一個內(nèi)部布爾屬性this.pendingRequest實(shí)現(xiàn),當(dāng)Ajax請求發(fā)送時值為true,當(dāng)返回的請求被處理后值為false
           *    用來基于服務(wù)器的處理速度限制事件的發(fā)送速度
           
          */

             sendRequestForSuggestions: 
          function() {

               
          if ( this.handlingRequest ) {
                  
          this.pendingRequest = true;
                  
          return;
               }


               
          this.handlingRequest = true;
               
          this.callRicoAjaxEngine();
             }
          ,

          /*
           *    使用Rico提供的一個出色的Ajax處理函數(shù)
           *    ajaxEngine這個API支持為請求注冊邏輯名,和注冊知道如何處理Ajax響應(yīng)的對象
           *    ajaxEngine.registerRequest()為一個(可能很長或很怪的)URL注冊邏輯名,在發(fā)送請求時可以使用這個邏輯名
           *    ajaxEngine.registerAjaxObject()用來注冊一個Ajax處理對象
           
          */

             initAjax: 
          function(url) {
                ajaxEngine.registerRequest( 
          this.id + '_request', url );
                ajaxEngine.registerAjaxObject( 
          this.id + '_updater', this );
             }
          ,
             
          /*
           *    發(fā)送請求
           *    先將對象的內(nèi)部狀態(tài)和options對象的特定屬性存入數(shù)組callParms
           *    再將外部請求參數(shù)存入數(shù)組callParms
           *    通過ajaxEngine.sendRequest.apply( ajaxEngine, callParms )發(fā)送
           *  apply()方法見最后注釋
           
          */

             callRicoAjaxEngine: 
          function() {
                
          var callParms = [];
                callParms.push( 
          this.id + '_request');
                callParms.push( 'id
          ='             + this.id);
                callParms.push( 'count
          ='          + this.options.count);
                callParms.push( 'query
          ='          + this.lastRequestString);
                callParms.push( 'match_anywhere
          =+ this.options.matchAnywhere);
                callParms.push( 'ignore_case
          ='    + this.options.ignoreCase);

                
          var additionalParms = this.options.requestParameters || [];
                
          forvar i=0 ; i < additionalParms.length ; i++ )
                   callParms.push(additionalParms[i]);

                ajaxEngine.sendRequest.apply( ajaxEngine, callParms );
             }
          ,

          //-----------------------文本提示--處理Ajax請求

          /*
           *    處理請求
           *    224 先通過createSuggestions()方法將響應(yīng)解析成提示在內(nèi)存中的表現(xiàn)形式,保存在suggestions屬性中
           *    226 如果沒找到提示,將探出框隱藏,并清空隱藏字段中的內(nèi)部值
           *    230 如果找到提示,創(chuàng)建下拉框的UI元素,使用提示組裝,并顯示給用戶
           *      236 最后將this.handlingRequest重新設(shè)置為false,表示響應(yīng)處理完成
           
          */

             ajaxUpdate: 
          function( ajaxResponse ) {

                
          this.createSuggestions( ajaxResponse );

                
          if ( this.suggestions.length == 0 ) {
                   
          this.hideSuggestions();
                   $( 
          this.id + "_hidden" ).value = "";
                }

                
          else {
                   
          this.updateSuggestionsDiv();
                   
          this.showSuggestions();
                   
          this.updateSelection(0);
                }


                
          this.handlingRequest = false;

                
          if ( this.pendingRequest ) {
                   
          this.pendingRequest    = false;
                   
          this.lastRequestString = this.textInput.value;
                   
          this.sendRequestForSuggestions();
                }

             }
          ,

             createSuggestions: 
          function(ajaxResponse) {
                
          this.suggestions = [];
                
          var entries = ajaxResponse.getElementsByTagName('entry');
                
          for ( var i = 0 ; i < entries.length ; i++ ) {
                   
          var strText  = this.getElementContent(entries[i].getElementsByTagName('text')[0]);
                   
          var strValue = this.getElementContent(entries[i].getElementsByTagName('value')[0]);
                   
          this.suggestions.push( { text: strText, value: strValue } );
                }

             }
          ,

          /*
           ************************************事件處理***********************************************
           
          */

           
          //行為注入
             injectSuggestBehavior: function() {

                
          if ( this.isIE )
                   
          this.textInput.autocomplete = "off";   //關(guān)閉IE自動完成

                
          var keyEventHandler = new TextSuggestKeyHandler(this);   //創(chuàng)建控制器
                
                
          //Insertion.After由Prototype庫提供,添加一個不可見文本字段來防止回車鍵提交表單
                new Insertion.After( this.textInput,
                                     '
          <input type="text" id="'+this.id+'_preventtsubmit'+'" style="display:none"/>' );
                
          new Insertion.After( this.textInput,
                                     '
          <input type="hidden" name="'+this.id+'_hidden'+'" id="'+this.id+'_hidden'+'"/>' );

                
          this.createSuggestionsDiv();     //創(chuàng)建UI
             }
          ,

          //TextSuggest的選擇處理方法
             moveSelectionUp: function() {
                
          //selectedIndex: select對象中當(dāng)前被選option的下標(biāo)
                if ( this.selectedIndex > 0 ) {
                   
          this.updateSelection(this.selectedIndex - 1);
                }

             }
          ,

             moveSelectionDown: 
          function() {
                
          if ( this.selectedIndex < (this.suggestions.length - 1)  ) {
                   
          this.updateSelection(this.selectedIndex + 1);
                }

             }
          ,

             updateSelection: 
          function(n) {
                
          var span = $( this.id + "_" + this.selectedIndex );
                
          if ( span ){
                   span.style.backgroundColor 
          = "";  //清除之前的選擇
                }

                
          this.selectedIndex = n;
                
          var span = $( this.id + "_" + this.selectedIndex );
                
          if ( span ){
                   span.style.backgroundColor 
          = this.options.selectionColor;
                }

             }
          ,

          //文本輸入處理函數(shù)
             handleTextInput: function() {
               
          var previousRequest    = this.lastRequestString;    //上次請求的值
               this.lastRequestString = this.textInput.value;      //現(xiàn)在請求的值
               if ( this.lastRequestString == "" )
                  
          this.hideSuggestions();
               
          else if ( this.lastRequestString != previousRequest ) {
                  
          this.sendRequestForSuggestions();                //數(shù)據(jù)的Ajax請求
               }

             }
          ,

             setInputFromSelection: 
          function() {
               
          var hiddenInput = $( this.id + "_hidden" );
               
          var suggestion  = this.suggestions[ this.selectedIndex ];

               
          this.textInput.value = suggestion.text;             //更新可見的值
               hiddenInput.value    = suggestion.value;            //更新隱藏的值  
               this.hideSuggestions();
             }
          ,



          /*
           ************************************提示的彈出框界面***********************************************
           
          */

           
           
          //創(chuàng)建DIV
             createSuggestionsDiv: function() {
                
          this.suggestionsDiv = document.createElement("div");                   //創(chuàng)建DIV
                this.suggestionsDiv.className = this.options.suggestDivClassName;      //設(shè)置樣式

                
          var divStyle = this.suggestionsDiv.style;            //添加行為樣式
                divStyle.position = 'absolute';
                divStyle.zIndex   
          = 101;
                divStyle.display  
          = "none";

                
          this.textInput.parentNode.appendChild(this.suggestionsDiv);           //插入到文檔中
             }
          ,

          //定位彈出框
             positionSuggestionsDiv: function() {
                
          //通過Rico提供的toDocumentPosition()方法來計算文本字段的絕對位置
                var textPos = RicoUtil.toDocumentPosition(this.textInput);
                
          var divStyle = this.suggestionsDiv.style;
                divStyle.top  
          = (textPos.y + this.textInput.offsetHeight) + "px";
                divStyle.left 
          = textPos.x + "px";

                
          if ( this.options.matchTextWidth )
                   divStyle.width 
          = (this.textInput.offsetWidth- this.padding()) + "px";
             }
          ,

          //計算左邊和右邊的填充值
             padding: function() {
               
          try{
                
          var styleFunc = RicoUtil.getElementsComputedStyle;
                
          var lPad    = styleFunc( this.suggestionsDiv, "paddingLeft",      "padding-left" );
                
          var rPad    = styleFunc( this.suggestionsDiv, "paddingRight",     "padding-right" );
                
          var lBorder = styleFunc( this.suggestionsDiv, "borderLeftWidth",  "border-left-width" );
                
          var rBorder = styleFunc( this.suggestionsDiv, "borderRightWidth""border-right-width" );

                lPad    
          = isNaN(lPad)    ? 0 : lPad;
                rPad    
          = isNaN(rPad)    ? 0 : rPad;
                lBorder 
          = isNaN(lBorder) ? 0 : lBorder;
                rBorder 
          = isNaN(rBorder) ? 0 : rBorder;

                
          return parseInt(lPad) + parseInt(rPad) + parseInt(lBorder) + parseInt(rBorder);
               }
          catch (e){
                
          return 0;
               }

             }
          ,

          //創(chuàng)建彈出框的內(nèi)容
             updateSuggestionsDiv: function() {
                
          this.suggestionsDiv.innerHTML = "";                    //除去以前的內(nèi)容
                var suggestLines = this.createSuggestionSpans();      //創(chuàng)建新內(nèi)容
                for ( var i = 0 ; i < suggestLines.length ; i++ )
                   
          this.suggestionsDiv.appendChild(suggestLines[i]);
             }
          ,

          //創(chuàng)建提示列表的條目
             createSuggestionSpans: function() {
                
          var regExpFlags = "";
                
          if ( this.options.ignoreCase )
                   regExpFlags 
          = 'i';
                
          var startRegExp = "^";
                
          if ( this.options.matchAnywhere )
                   startRegExp 
          = '';

                
          var regExp  = new RegExp( startRegExp + this.lastRequestString, regExpFlags );

                
          var suggestionSpans = [];
                
          for ( var i = 0 ; i < this.suggestions.length ; i++ )
                   suggestionSpans.push( 
          this.createSuggestionSpan( i, regExp ) )

                
          return suggestionSpans;
             }
          ,

          //創(chuàng)建列表的條目span
             createSuggestionSpan: function( n, regExp ) {
                
          var suggestion = this.suggestions[n];

                
          var suggestionSpan = document.createElement("span");
                suggestionSpan.className 
          = this.options.suggestionClassName;
                suggestionSpan.style.width   
          = '100%';
                suggestionSpan.style.display 
          = 'block';
                suggestionSpan.id            
          = this.id + "_" + n;
                suggestionSpan.onmouseover   
          = this.mouseoverHandler.bindAsEventListener(this);
                suggestionSpan.onclick       
          = this.itemClickHandler.bindAsEventListener(this);

                
          var textValues = this.splitTextValues( suggestion.text,
                                                       
          this.lastRequestString.length,
                                                       regExp );

                
          var textMatchSpan = document.createElement("span");
                textMatchSpan.id            
          = this.id + "_match_" + n;
                textMatchSpan.className     
          = this.options.matchClassName;
                textMatchSpan.onmouseover   
          = this.mouseoverHandler.bindAsEventListener(this);
                textMatchSpan.onclick       
          = this.itemClickHandler.bindAsEventListener(this);

                textMatchSpan.appendChild( document.createTextNode(textValues.mid) );

                suggestionSpan.appendChild( document.createTextNode( textValues.start ) );
                suggestionSpan.appendChild( textMatchSpan );
                suggestionSpan.appendChild( document.createTextNode( textValues.end ) );

                
          return suggestionSpan;
             }
          ,

             splitTextValues: 
          function( text, len, regExp ) {
                
          var startPos  = text.search(regExp);
                
          var matchText = text.substring( startPos, startPos + len );
                
          var startText = startPos == 0 ? "" : text.substring(0, startPos);
                
          var endText   = text.substring( startPos + len );
                
          return { start: startText, mid: matchText, end: endText };
             }
          ,

          //列表?xiàng)l目的鼠標(biāo)事件處理函數(shù)
             mouseoverHandler: function(e) {
                
          var src = e.srcElement ? e.srcElement : e.target;
                
          var index = parseInt(src.id.substring(src.id.lastIndexOf('_')+1));
                
          this.updateSelection(index);
             }
          ,

             itemClickHandler: 
          function(e) {
                
          this.mouseoverHandler(e);
                
          this.hideSuggestions();
                
          this.textInput.focus();
             }
          ,

          //顯示和隱藏彈出框
             showSuggestions: function() {
                
          var divStyle = this.suggestionsDiv.style;
                
          if ( divStyle.display == '' )
                   
          return;
                
          this.positionSuggestionsDiv();
                divStyle.display 
          = '';
             }
          ,

             hideSuggestions: 
          function() {
                
          this.suggestionsDiv.style.display = 'none';
             }
          ,

             getElementContent: 
          function(element) {
                
          return element.firstChild.data;
             }

          }



          //---------------控制器對象,用來擔(dān)任事件的代理


          TextSuggestKeyHandler 
          = Class.create();

          TextSuggestKeyHandler.prototype 
          = {

          /*
           *   構(gòu)造方法
           *   控制器保存提示組件的引用和HTML標(biāo)單的輸入字段,通過this.addKeyHandling()為輸入字段添加處理函數(shù)
           
          */

             initialize: 
          function( textSuggest ) {
                
          this.textSuggest = textSuggest;
                
          this.input       = this.textSuggest.textInput;
                
          this.addKeyHandling();
             }
          ,

          //bindAsEventListener()是prototype庫提供的一個閉包機(jī)制,該機(jī)制允許處理函數(shù)調(diào)用控制器的方法
             addKeyHandling: function() {
                
          this.input.onkeyup    = this.keyupHandler.bindAsEventListener(this);
                
          this.input.onkeydown  = this.keydownHandler.bindAsEventListener(this);
                
          this.input.onblur     = this.onblurHandler.bindAsEventListener(this);
                
          if ( this.isOpera )
                   
          this.input.onkeypress = this.keyupHandler.bindAsEventListener(this);
             }
          ,

          //處理按下按鍵
             keydownHandler: function(e) {
                
          var upArrow   = 38;     //上箭頭
                var downArrow = 40;     //下箭頭

                
          if ( e.keyCode == upArrow ) {
                   
          this.textSuggest.moveSelectionUp();
                   setTimeout( 
          this.moveCaretToEnd.bind(this), 1 );
                }

                
          else if ( e.keyCode == downArrow ){
                   
          this.textSuggest.moveSelectionDown();
                }

             }
          ,

          //處理放開按鍵
             keyupHandler: function(e) {
                
          if ( this.input.length == 0 && !this.isOpera )
                   
          this.textSuggest.hideSuggestions();

               
          if ( !this.handledSpecialKeys(e) )
                  
          this.textSuggest.handleTextInput();
             }
          ,

          //幾個特殊 按鍵
             handledSpecialKeys: function(e) {
                
          var enterKey  = 13;   //上箭頭
                var upArrow   = 38;   //下箭頭
                var downArrow = 40;   //回車鍵

                
          if ( e.keyCode == upArrow || e.keyCode == downArrow ) {
                   
          return true;
                }

                
          else if ( e.keyCode == enterKey ) {
                   
          this.textSuggest.setInputFromSelection();
                   
          return true;
                }


                
          return false;
             }
          ,

          //修改上箭頭在文本字段中使光標(biāo)后退的默認(rèn)行為
             moveCaretToEnd: function() {
                
          var pos = this.input.value.length;
                
          if (this.input.setSelectionRange) {
                   
          this.input.setSelectionRange(pos,pos);
                }

                
          else if(this.input.createTextRange){
                   
          var m = this.input.createTextRange();
                   m.moveStart('character',pos);
                   m.collapse();
                   m.select();
                }

             }
          ,

             onblurHandler: 
          function(e) {
                
          if ( this.textSuggest.suggestionsDiv.style.display == '' )
                   
          this.textSuggest.setInputFromSelection();
                
          this.textSuggest.hideSuggestions();
             }


          }
          ;

          posted on 2007-09-24 09:08 趙曦 閱讀(622) 評論(1)  編輯  收藏

          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 镇巴县| 沐川县| 清原| 安乡县| 桃源县| 青海省| 微博| 扶绥县| 仙游县| 红河县| 乳山市| 永川市| 达日县| 孝义市| 金秀| 泰宁县| 保德县| 延寿县| 瑞金市| 广安市| 岗巴县| 湟中县| 西昌市| 都匀市| 盈江县| 水城县| 巫溪县| 女性| 云南省| 彩票| 衡阳市| 高平市| 彭山县| 平安县| 天门市| 张家川| 寿阳县| 永春县| 泰和县| 宁安市| 东安县|