Atlas --AutoCompleteBehavior代码解读整理

定义
Sys.Preview.UI.AutoCompleteBehavior.prototype = {
_mouseOverHandler: null,  //其是对象相关的,故必须在对象初始化时赋值
 _onListMouseOver: Sys$Preview$UI$AutoCompleteBehavior$_onListMouseOver
}
初始化,对 _mouseOverHandler 进行赋值,创建浮动层画布

function  Sys$Preview$UI$AutoCompleteBehavior$initialize()  {
        Sys.Preview.UI.AutoCompleteBehavior.callBaseMethod(
this'initialize');
        
//对 _mouseOverHandler 进行赋值
        this._mouseOverHandler = Function.createDelegate(thisthis._onListMouseOver);
        
//初始化自身的TextBox
        var element = this.get_element();
        
this.initializeTextBox(element);
        
//初始化浮动层画布(自动完成列表)    
        if (!this._completionListElement) {
            
this._completionListElement = document.createElement('DIV');
            document.body.appendChild(
this._completionListElement);
        }

        
        
this.initializeCompletionList(this._completionListElement);
        
        
//把 _completionListElement 设置弹出
        var popupControl = new Sys.UI.Control(this._completionListElement);
        
this._popupBehavior = new Sys.Preview.UI.PopupBehavior(this._completionListElement);
        
this._popupBehavior.set_parentElement(element);
        
this._popupBehavior.set_positioningMode(Sys.Preview.UI.PositioningMode.BottomLeft);
        
this._popupBehavior.initialize();
        popupControl.initialize();
}


对浮动层画布初始化的过程中会对其鼠标等事件赋值

     function  Sys$Preview$UI$AutoCompleteBehavior$initializeCompletionList(element)  {
        
var completionListStyle = element.style;
        completionListStyle.visibility 
= 'hidden';
        completionListStyle.backgroundColor 
= 'window';
        completionListStyle.color 
= 'windowtext';
        completionListStyle.border 
= 'solid 1px buttonshadow';
        completionListStyle.cursor 
= 'default';
        completionListStyle.unselectable 
= 'unselectable';
        completionListStyle.overflow 
= 'hidden';
        
var elementBounds = Sys.UI.DomElement.getBounds(this.get_element());        
        completionListStyle.width 
= (elementBounds.width - 2+ 'px';
        
        $addHandler(element, 
"mousedown"this._mouseDownHandler);
        $addHandler(element, 
"mouseup"this._mouseUpHandler);
        $addHandler(element, 
"mouseover"this._mouseOverHandler);
    }


接受到异步消息时,会动态在 _completionListElement 中增加DIV/TEXT节点  

function  Sys$Preview$UI$AutoCompleteBehavior$_update(prefixText, completionItems, cacheResults)  {
        
if (cacheResults && this.get_enableCaching()) {
            
if (!this._cache) {
                
this._cache = {};
            }

            
this._cache[prefixText] = completionItems;
        }


        
this._completionListElement.innerHTML = '';
        
this._selectIndex = -1;
        
if (completionItems && completionItems.length) {
            
for (var i = 0; i < completionItems.length; i++{
                
var itemElement = document.createElement('div');
                
//Creates a text string from the specified value.     Returns the created TextNode object.(TextNode, Represents a string of text as a node in the document hierarchy.)
                itemElement.appendChild(document.createTextNode(completionItems[i]));  
                itemElement.__item 
= '';
                
                
var itemElementStyle = itemElement.style;
                itemElementStyle.padding 
= '1px';
                itemElementStyle.textAlign 
= 'left';
                itemElementStyle.textOverflow 
= 'ellipsis';
                itemElementStyle.backgroundColor 
= 'window';
                itemElementStyle.color 
= 'windowtext';
                
                
this._completionListElement.appendChild(itemElement);
            }

            
this._popupBehavior.show();
        }

        
else {
            
this._popupBehavior.hide();
        }

    }


具体相关 _completionListElement 函数实现


    
function  Sys$Preview$UI$AutoCompleteBehavior$initializeCompletionList(element)  {
        $addHandler(element, 
"mouseover"this._mouseOverHandler);
    }


    
function  Sys$Preview$UI$AutoCompleteBehavior$_onListMouseDown(ev)  {
        
if (ev.target !== this._completionListElement) {
            
this._setText(ev.target.firstChild.nodeValue);
        }

    }


    
function  Sys$Preview$UI$AutoCompleteBehavior$_onListMouseUp(ev)  {
        
this.get_element().focus(); //光标返回到textbox上
    }


    
function  Sys$Preview$UI$AutoCompleteBehavior$_onListMouseOver(ev)  {
        
var item = ev.target;
        
this._selectIndex = -1;
        
this._highlightItem(item);
    }

 

 

 


/**
 * An autosuggest textbox control.
 * @class
 * @scope public
 
*/

function  AutoSuggestControl(oTextbox  /*:HTMLInputElement*/
                            oProvider 
/*:SuggestionProvider*/ {
    
    
/**
     * The currently selected suggestions.
     * @scope private
     
*/
   
    
this.cur /*:int*/ = -1;

    
/**
     * The dropdown list layer.
     * @scope private
     
*/

    
this.layer = null;
    
    
/**
     * Suggestion provider for the autosuggest feature.
     * @scope private.
     
*/

    
this.provider /*:SuggestionProvider*/ = oProvider;
    
    
/**
     * The textbox to capture.
     * @scope private
     
*/

    
this.textbox /*:HTMLInputElement*/ = oTextbox;
    
    
/**
     * Timeout ID for fast typers.
     * @scope private
     
*/

    
this.timeoutId /*:int*/ = null;

    
/**
     * The text that the user typed.
     * @scope private
     
*/

    
this.userText /*:String*/ = oTextbox.value;
    
    
//initialize the control
    this.init();
    
}


/**
 * Autosuggests one or more suggestions for what the user has typed.
 * If no suggestions are passed in, then no autosuggest occurs.
 * @scope private
 * @param aSuggestions An array of suggestion strings.
 * @param bTypeAhead If the control should provide a type ahead suggestion.
 
*/

AutoSuggestControl.prototype.autosuggest 
=   function  (aSuggestions  /*:Array*/ ,
                                                     bTypeAhead 
/*:boolean*/ {
    
    
//re-initialize pointer to current suggestion
    this.cur = -1;
    
    
//make sure there's at least one suggestion
    if (aSuggestions.length > 0{
        
if (bTypeAhead) {
           
this.typeAhead(aSuggestions[0]);
        }

        
        
this.showSuggestions(aSuggestions);
    }
 else {
        
this.hideSuggestions();
    }

}
;

/**
 * Creates the dropdown layer to display multiple suggestions.
 * @scope private
 
*/

AutoSuggestControl.prototype.createDropDown 
=   function  ()  {


    
//create the layer and assign styles
    this.layer = document.createElement("div");
    
this.layer.className = "suggestions";
    
this.layer.style.visibility = "hidden";
    
this.layer.style.width = this.textbox.offsetWidth;
    document.body.appendChild(
this.layer);    
    
    
//when the user clicks on the a suggestion, get the text (innerHTML)
    //and place it into a textbox
    var oThis = this;
    
this.layer.onmousedown = 
    
this.layer.onmouseup = 
    
this.layer.onmouseover = function (oEvent) {
        oEvent 
= oEvent || window.event;
        oTarget 
= oEvent.target || oEvent.srcElement;

        
if (oEvent.type == "mousedown"{
            oThis.textbox.value 
= oTarget.firstChild.nodeValue;
            oThis.hideSuggestions();
        }
 else if (oEvent.type == "mouseover"{
            oThis.highlightSuggestion(oTarget);
        }
 else {
            oThis.textbox.focus();
        }

    }
;
    
}
;

/**
 * Gets the left coordinate of the textbox.
 * @scope private
 * @return The left coordinate of the textbox in pixels.
 
*/

AutoSuggestControl.prototype.getLeft 
=   function  ()  /*:int*/   {

    
var oNode = this.textbox;
    
var iLeft = 0;
    
    
while(oNode.tagName != "BODY"{
        iLeft 
+= oNode.offsetLeft;
        oNode 
= oNode.offsetParent;        
    }

    
    
return iLeft;
}
;

/**
 * Gets the top coordinate of the textbox.
 * @scope private
 * @return The top coordinate of the textbox in pixels.
 
*/

AutoSuggestControl.prototype.getTop 
=   function  ()  /*:int*/   {

    
var oNode = this.textbox;
    
var iTop = 0;
    
    
while(oNode.tagName != "BODY"{
        iTop 
+= oNode.offsetTop;
        oNode 
= oNode.offsetParent;
    }

    
    
return iTop;
}
;

/**
 * Highlights the next or previous suggestion in the dropdown and
 * places the suggestion into the textbox.
 * @param iDiff Either a positive or negative number indicating whether
 *              to select the next or previous sugggestion, respectively.
 * @scope private
 
*/

AutoSuggestControl.prototype.goToSuggestion 
=   function  (iDiff  /*:int*/ {
    
var cSuggestionNodes = this.layer.childNodes;
    
    
if (cSuggestionNodes.length > 0{
        
var oNode = null;
    
        
if (iDiff > 0{
            
if (this.cur < cSuggestionNodes.length-1{
                oNode 
= cSuggestionNodes[++this.cur];
            }
        
        }
 else {
            
if (this.cur > 0{
                oNode 
= cSuggestionNodes[--this.cur];
            }
    
        }

        
        
if (oNode) {
            
this.highlightSuggestion(oNode);
            
this.textbox.value = oNode.firstChild.nodeValue;
        }

    }

}
;

/**
 * Handles three keydown events.
 * @scope private
 * @param oEvent The event object for the keydown event.
 
*/

AutoSuggestControl.prototype.handleKeyDown 
=   function  (oEvent  /*:Event*/ {

    
switch(oEvent.keyCode) {
        
case 38//up arrow
            this.goToSuggestion(-1);
            
break;
        
case 40//down arrow 
            this.goToSuggestion(1);
            
break;
        
case 27//esc
            this.textbox.value = this.userText;
            
this.selectRange(this.userText.length, 0);
            
/* falls through */
        
case 13//enter
            this.hideSuggestions();
            oEvent.returnValue 
= false;
            
if (oEvent.preventDefault) {
                oEvent.preventDefault();
            }

            
break;
    }


}
;

/**
 * Handles keyup events.
 * @scope private
 * @param oEvent The event object for the keyup event.
 
*/

AutoSuggestControl.prototype.handleKeyUp 
=   function  (oEvent  /*:Event*/ {

    
var iKeyCode = oEvent.keyCode;
    
var oThis = this;
    
    
//get the currently entered text
    this.userText = this.textbox.value;
    
    clearTimeout(
this.timeoutId);

    
//for backspace (8) and delete (46), shows suggestions without typeahead
    if (iKeyCode == 8 || iKeyCode == 46{
        
        
this.timeoutId = setTimeout( function () {
            oThis.provider.requestSuggestions(oThis, 
false);
        }
250);
        
    
//make sure not to interfere with non-character keys
    }
 else if (iKeyCode < 32 || (iKeyCode >= 33 && iKeyCode < 46|| (iKeyCode >= 112 && iKeyCode <= 123)) {
        
//ignore
    }
 else {
        
//request suggestions from the suggestion provider with typeahead
        this.timeoutId = setTimeout( function () {
            oThis.provider.requestSuggestions(oThis, 
true);
        }
250);
    }

}
;

/**
 * Hides the suggestion dropdown.
 * @scope private
 
*/

AutoSuggestControl.prototype.hideSuggestions 
=   function  ()  {
    
this.layer.style.visibility = "hidden";
}
;

/**
 * Highlights the given node in the suggestions dropdown.
 * @scope private
 * @param oSuggestionNode The node representing a suggestion in the dropdown.
 
*/

AutoSuggestControl.prototype.highlightSuggestion 
=   function  (oSuggestionNode)  {
    
    
for (var i=0; i < this.layer.childNodes.length; i++{
        
var oNode = this.layer.childNodes[i];
        
if (oNode == oSuggestionNode) {
            oNode.className 
= "current"
        }
 else if (oNode.className == "current"{
            oNode.className 
= "";
        }

    }

}
;

/**
 * Initializes the textbox with event handlers for
 * auto suggest functionality.
 * @scope private
 
*/

AutoSuggestControl.prototype.init 
=   function  ()  {

    
//save a reference to this object
    var oThis = this;
    
    
//assign the onkeyup event handler
    this.textbox.onkeyup = function (oEvent) {
    
        
//check for the proper location of the event object
        if (!oEvent) {
            oEvent 
= window.event;
        }
    
        
        
//call the handleKeyUp() method with the event object
        oThis.handleKeyUp(oEvent);
    }
;
    
    
//assign onkeydown event handler
    this.textbox.onkeydown = function (oEvent) {

        
//check for the proper location of the event object
        if (!oEvent) {
            oEvent 
= window.event;
        }
    
        
        
//call the handleKeyDown() method with the event object
        oThis.handleKeyDown(oEvent);
    }
;
    
    
//assign onblur event handler (hides suggestions)    
    this.textbox.onblur = function () {
        oThis.hideSuggestions();
    }
;
    
    
//create the suggestions dropdown
    this.createDropDown();
}
;

/**
 * Selects a range of text in the textbox.
 * @scope public
 * @param iStart The start index (base 0) of the selection.
 * @param iEnd The end index of the selection.
 
*/

AutoSuggestControl.prototype.selectRange 
=   function  (iStart  /*:int*/ , iEnd  /*:int*/ {

    
//use text ranges for Internet Explorer
    if (this.textbox.createTextRange) {
        
var oRange = this.textbox.createTextRange(); 
        oRange.moveStart(
"character", iStart); 
        oRange.moveEnd(
"character", iEnd - this.textbox.value.length);      
        oRange.select();
        
    
//use setSelectionRange() for Mozilla
    }
 else if (this.textbox.setSelectionRange) {
        
this.textbox.setSelectionRange(iStart, iEnd);
    }
     

    
//set focus back to the textbox
    this.textbox.focus();      
}


/**
 * Builds the suggestion layer contents, moves it into position,
 * and displays the layer.
 * @scope private
 * @param aSuggestions An array of suggestions for the control.
 
*/

AutoSuggestControl.prototype.showSuggestions 
=   function  (aSuggestions  /*:Array*/ {
    
    
var oDiv = null;
    
this.layer.innerHTML = "";  //clear contents of the layer
    
    
for (var i=0; i < aSuggestions.length; i++{
        oDiv 
= document.createElement("div");
        oDiv.appendChild(document.createTextNode(aSuggestions[i]));
        
this.layer.appendChild(oDiv);
    }

    
    
this.layer.style.left = this.getLeft() + "px";
    
this.layer.style.top = (this.getTop()+this.textbox.offsetHeight) + "px";
    
this.layer.style.visibility = "visible";

}
;

/**
 * Inserts a suggestion into the textbox, highlighting the 
 * suggested part of the text.
 * @scope private
 * @param sSuggestion The suggestion for the textbox.
 
*/

AutoSuggestControl.prototype.typeAhead 
=   function  (sSuggestion  /*:String*/ {

    
//check for support of typeahead functionality
    if (this.textbox.createTextRange || this.textbox.setSelectionRange){
        
var iLen = this.textbox.value.length; 
        
this.textbox.value = sSuggestion; 
        
this.selectRange(iLen, sSuggestion.length);
    }

}
;

/**
 * Provides suggestions for state/province names.
 * @class
 * @scope public
 
*/

function  SuggestionProvider()  {
    
this.http = zXmlHttp.createRequest();
}


/**
 * Request suggestions for the given autosuggest control. 
 * @scope protected
 * @param oAutoSuggestControl The autosuggest control to provide suggestions for.
 
*/

SuggestionProvider.prototype.requestSuggestions 
=   function  (oAutoSuggestControl  /*:AutoSuggestControl*/ ,
                                                            bTypeAhead 
/*:boolean*/ {

    
var oHttp = this.http;
                                   
    
//cancel any active requests                          
    if (oHttp.readyState != 0{
        oHttp.abort();
    }
                 
    
    
//define the data
    var oData = 
        requesting: 
"StatesAndProvinces"
        text: oAutoSuggestControl.userText,
        limit: 
5 
    }
;
    
    
//open connection to server
    oHttp.open("post""suggestions.php"true);
    oHttp.onreadystatechange 
= function () {
        
if (oHttp.readyState == 4{
            
//evaluate the returned text JavaScript (an array)
            var aSuggestions = JSON.parse(oHttp.responseText);

            
//provide suggestions to the control
            oAutoSuggestControl.autosuggest(aSuggestions, bTypeAhead);        
        }
    
    }
;

    
//send the request
    oHttp.send(JSON.stringify(oData));

}
;
div.suggestions  {
    -moz-box-sizing
: border-box;
    box-sizing
: border-box;
    background-color
: white;
    border
: 1px solid black;
    position
: absolute;   
}


div.suggestions div 
{
    cursor
: default;
    padding
: 0px 3px;
}


div.suggestions div.current 
{
    background-color
: #3366cc;
    color
: white;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值