posts - 1,  comments - 1,  trackbacks - 0

           



          //-------------------- mContentLoader.js
          /*
           *        Ajax的輔助對象,執行所有與Ajax處理相關的工作
           *
           
          */

          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;

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

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

           
           
           
          /*
           ************************************創建TextSuggest***********************************************
           
          */

          TextSuggest 
          = Class.create();

          TextSuggest.prototype 
          = {

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

             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每個屬性都指定一個默認值
           *    然后,使用在構造時傳入的options對象調用Prototype庫的extend()方法,來覆蓋默認值
           *    最后結果是一個合并的options對象,包含默認值和指定的覆蓋值
           
          */

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


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


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

             sendRequestForSuggestions: 
          function() {

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


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

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

             initAjax: 
          function(url) {
                ajaxEngine.registerRequest( 
          this.id + '_request', url );
                ajaxEngine.registerAjaxObject( 
          this.id + '_updater', this );
             }
          ,
             
          /*
           *    發送請求
           *    先將對象的內部狀態和options對象的特定屬性存入數組callParms
           *    再將外部請求參數存入數組callParms
           *    通過ajaxEngine.sendRequest.apply( ajaxEngine, callParms )發送
           *  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()方法將響應解析成提示在內存中的表現形式,保存在suggestions屬性中
           *    226 如果沒找到提示,將探出框隱藏,并清空隱藏字段中的內部值
           *    230 如果找到提示,創建下拉框的UI元素,使用提示組裝,并顯示給用戶
           *      236 最后將this.handlingRequest重新設置為false,表示響應處理完成
           
          */

             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";   //關閉IE自動完成

                
          var keyEventHandler = new TextSuggestKeyHandler(this);   //創建控制器
                
                
          //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();     //創建UI
             }
          ,

          //TextSuggest的選擇處理方法
             moveSelectionUp: function() {
                
          //selectedIndex: select對象中當前被選option的下標
                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;
                }

             }
          ,

          //文本輸入處理函數
             handleTextInput: function() {
               
          var previousRequest    = this.lastRequestString;    //上次請求的值
               this.lastRequestString = this.textInput.value;      //現在請求的值
               if ( this.lastRequestString == "" )
                  
          this.hideSuggestions();
               
          else if ( this.lastRequestString != previousRequest ) {
                  
          this.sendRequestForSuggestions();                //數據的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();
             }
          ,



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

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

                
          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;
               }

             }
          ,

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

          //創建提示列表的條目
             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;
             }
          ,

          //創建列表的條目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 };
             }
          ,

          //列表條目的鼠標事件處理函數
             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;
             }

          }



          //---------------控制器對象,用來擔任事件的代理


          TextSuggestKeyHandler 
          = Class.create();

          TextSuggestKeyHandler.prototype 
          = {

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

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

          //bindAsEventListener()是prototype庫提供的一個閉包機制,該機制允許處理函數調用控制器的方法
             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;
             }
          ,

          //修改上箭頭在文本字段中使光標后退的默認行為
             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 趙曦 閱讀(621) 評論(1)  編輯  收藏

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


          網站導航:
           
          主站蜘蛛池模板: 庆城县| 江阴市| 姚安县| 福鼎市| 四会市| 辽源市| 蓬安县| 盐山县| 安义县| 德保县| 绿春县| 弥勒县| 兴业县| 高州市| 清涧县| 凯里市| 安仁县| 太康县| 天水市| 西乌| 疏勒县| 晋州市| 安国市| 南江县| 富裕县| 丹凤县| 盐边县| 长治市| 三穗县| 东辽县| 会泽县| 昌平区| 滨州市| 陈巴尔虎旗| 乾安县| 綦江县| 乌什县| 绍兴市| 安溪县| 赣州市| 兴化市|