
/**
 * An autosuggest textbox control.
 * @class
 * @scope public
 */
function AutoSuggestControl_MultiFiltered(oTextbox /*:HTMLInputElement*/, 
							oFilterArray /*:nullable, Series of Controls to filter the list*/, 
                            oProvider /*:nullable, SuggestionProvider*/,
                            oTextboxID /*:nullable, The ID textbox for a value/id scenario*/,
                            ochkFilter /*:nullable, The ID textbox for a value/id scenario*/,
                            oDefaultValueArray /*:nullable, A default value for the textbox control and/or its ID textbox*/) {
     //debugger;
     /**
     * An array of default values for the textbox and/or the textboxID.
     * @scope private
     */
    this.textboxDefaultValueArray /*:HTMLInputElement*/ = oDefaultValueArray; 

    /**
     * The currently selected suggestions.
     * @scope private
     */   
    this.cur /*:int*/ = -1;

    //071806 - define a custom event
    this.onDataFilled = new YAHOO.util.CustomEvent("onDataFilled", this);

    /**
     * The number [count] of suggestions.
     * @scope private
     */   
    this.count /*:int*/ = 0;

    /**
     * The dropdown list layer.
     * @scope private
     */
    this.layer = null;
    //this.oPanel=null;	//panel add
    /**
     * Suggestion provider for the autosuggest feature.
     * @scope private.
     */
    this.provider /*:SuggestionProvider*/ = oProvider;
    
    /**
     * The textbox to capture.
     * @scope private
     */
    this.textbox /*:HTMLInputElement*/ = oTextbox;
   
    /**
     * The textbox to capture the ID for value/id pairs [e.g. dropdowns].
     * @scope private
     */
    this.textboxID /*:HTMLInputElement*/ = oTextboxID; 
    
     /**
     * Holds the textbox's value following focus on textbox.
     * Will be used to allow the user to hit escape key to replace
     * this value in the textbox.
     * @scope private
     */
    this.textboxHold="";  
    this.textboxIDHold="";  
    
     /**
     * The filtering array of textboxes.
     * @scope private
     */
    this.textboxFilterArray /*:HTMLInputElement*/ = oFilterArray;   
   
      /**
     * A checkbox to select or deselect filtering.
     * @scope private
     */
    this.chkFilter /*:HTMLInputElement*/ = ochkFilter;   
   
      /**
     * A variable that holds whether a suggestion has been selected by
     * clicking on the dropdown layer - needed for Mozilla
     * @scope private
     */
    this.SuggestionClicked /*:bool*/ = false;     
   
   
    var browser = navigator.appName;
    var b_version = navigator.appVersion;
    var version = parseFloat(b_version);
    //debugger
   if(navigator.appName=="Microsoft Internet Explorer" && version < 7)
   {
		this.browser="IE";	
	}
	else
	{
		//Under the heading of we just can't have nice things in Mozilla:
		//did a Google search and found others to have problems dynamically creating elements 
		//as is done below for the Scroll buttons in Mozilla.  Am excluding this functionality for any
		//browser except Internet Explorer.
		//Discussion found by Google search on this topic:
		//http://www.codingforums.com/archive/index.php?t-69776.html
		this.browser="other";	
	}

	if (this.browser == "IE") {
	    /*v3.0 */
	    this.btnScrollUp = document.createElement("input");
	    this.btnScrollUp.type = 'button';
	    this.btnScrollUp.name = 'scrollUp';
	    this.btnScrollUp.value = '^';
	    this.btnScrollDown = document.createElement("input");
	    this.btnScrollDown.type = 'button';
	    this.btnScrollDown.name = 'scrollUp';
	    this.btnScrollDown.value = 'v';
	}
	else {
	    this.lblScrollMsg = document.createElement("label");
	    this.lblScrollMsg.innerHTML = 'Click Page Dn or Page Up to scroll this list';
	    this.lblScrollMsg.style.backgroundColor = '#ffffff';
	    this.lblScrollMsg.style.color = '#0000ff';
	    this.lblScrollMsg.style.font = 'italic 10pt arial';
	    
	}
	    
   this.scrollPos=0;	/*:int the position of the scroll*/
   this.pageSize=30;	/*:int the number of records to scroll per scroll button click*/



   
    //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_MultiFiltered.prototype.autosuggest = function (aSuggestions /*:Array*/,
                                                     bTypeAhead /*:boolean*/,bHasIDbox /*:boolean*/) {
    //make sure there's at least one suggestion
    if (aSuggestions.length > 0) {
        if (bTypeAhead) {
			//if(aSuggestions[0][0] != null)	//check for multidim array that carries values and IDs
			if(bHasIDbox)	//check for multidim array that carries values and IDs
			{
				this.typeAhead(aSuggestions[0][0]);	//First element of multidim array
				this.textboxID.value=aSuggestions[0][1];
			}
			else
			{
				this.typeAhead(aSuggestions[0]);
			}
        }
        
        this.showSuggestions(aSuggestions);  
    } else {
        this.hideSuggestions();
    }
};

/**
 * Creates the dropdown layer to display multiple suggestions.
 * @scope private
 */
AutoSuggestControl_MultiFiltered.prototype.createDropDown = function() {

    var oThis = this;

    //create the layer and assign styles
    this.layer = document.createElement("div");
    this.layer.className = "suggestions";
    this.layer.style.visibility = "hidden";
    //for some reason, had to hardcode the width for VPR_Inventory's Edit_Item.aspx
    //for the txtAddess textbox of the TransactionClauseGenerator TCG.  Otherwise, the
    //size for this single control came out at 155px.
    if (this.textbox.id.indexOf("txtAddress") > 0) {
        this.layer.style.width = "428px";
    }
    else {
        this.layer.style.width = this.textbox.offsetWidth;
    }


    //when the user clicks on the a suggestion, get the text (innerHTML)
    //and place it into a textbox
    this.layer.onmousedown =
    this.layer.onmouseup =
    this.layer.onmouseover = function(oEvent) {
        oEvent = oEvent || window.event;
        oTarget = oEvent.target || oEvent.srcElement;

        if (oEvent.type == "mousedown") {
            //debugger;
            if (oThis.browser == "IE") {
                /*v3.0 start*/
                if (oEvent.srcElement.name == "scrollDown" || oEvent.srcElement.name == "scrollUp") {
                    /*
                    oThis.textbox.value=oEvent.srcElement.name;
                    oThis.hideSuggestions();
                    oThis.SuggestionClicked = true;	
                    */
                    return;
                }

            }
            else {
                if (oEvent.target.value == "v" || oEvent.target.value == "^")
                    return;
            }   /*v3.0 end*/
            //oThis.textbox.value = oTarget.firstChild.nodeValue;
            if (oThis.textboxID != null) {
                X = oTarget.firstChild.nodeValue.split(",")
                oThis.textbox.value = X[0];
                oThis.textboxID.value = X[1];
            }
            else {
                oThis.textbox.value = oTarget.firstChild.nodeValue;
            }
            oThis.hideSuggestions();
            oThis.SuggestionClicked = true;

        } else if (oEvent.type == "mouseover") {
            oThis.highlightSuggestion(oTarget);
        } else {
            oThis.textbox.focus();
        }
    };


    document.body.appendChild(this.layer);
};

/**
 * Gets the left coordinate of the textbox.
 * @scope private
 * @return The left coordinate of the textbox in pixels.
 */
AutoSuggestControl_MultiFiltered.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_MultiFiltered.prototype.getTop = function() /*:int*/{

    var oNode = this.textbox;
    var iTop = 0;

    while (oNode.tagName != "BODY") {
        iTop += oNode.offsetTop;
        oNode = oNode.offsetParent;


    }

    return iTop;
};

/**
 * Holds values for textbox and textboxID
 * @scope private
 */
AutoSuggestControl_MultiFiltered.prototype.holdValues = function () {
	//Hold on to the textbox values for later replacement by escape key
	this.textboxHold=this.textbox.value;
	if(this.textboxID != null){
	this.textboxIDHold=this.textboxID.value;
	}
};

/**
 * Handles three keydown events.
 * @scope private
 * @param oEvent The event object for the keydown event.
 */
AutoSuggestControl_MultiFiltered.prototype.handleKeyDown = function(oEvent /*:Event*/) {
    /**/
    //debugger;
    switch (oEvent.keyCode) {
        case 38: //up arrow
            this.previousSuggestion();
            break;

        case 40: //down arrow 
            this.nextSuggestion();
            break;
        case 13: //enter
            this.hideSuggestions();
            break;
        case 33: //pageUp
            this.scrollPos = this.scrollPos - this.pageSize;
            this.getSuggestions();
            break;
        case 34: //pageDown
            this.scrollPos = this.scrollPos + this.pageSize;
            this.getSuggestions();
            break;
    }

};

/**
 * Handles keyup events.
 * @scope private
 * @param oEvent The event object for the keyup event.
 */
AutoSuggestControl_MultiFiltered.prototype.handleKeyUp = function (oEvent /*:Event*/) {
    var iKeyCode = oEvent.keyCode;

	//if escape key (27) replace textbox textboxID
	if(iKeyCode==27) {
		if(this.textboxHold != null && this.textboxHold.length>0) {
		this.textbox.value=this.textboxHold;
		if(this.textboxID != null) {
			this.textboxID.value=this.textboxIDHold;
			}
		} //else {window.status=this.textbox.id;}
		return;
	}
  
    //for backspace (8) and delete (46), shows suggestions without typeahead
    if (iKeyCode == 8 || iKeyCode == 46) {
        this.provider.requestSuggestions(this, false);
        	if(this.textboxID !=null && this.textbox.value.length==0)
			{
				this.textboxID.value="";
			}
    //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.provider.requestSuggestions(this, true);
        this.provider.requestSuggestions(this, false);
    }
};

/**
 * Handles keyup events.
 * @scope private
 * @param oEvent The event object for the keyup event.
 */
AutoSuggestControl_MultiFiltered.prototype.handleKeyUp_chkFilter = function (oEvent /*:Event*/) {
	this.holdValues();
	//clear the textbox and textboxID to show full list of suggestions to come
	this.textbox.value="";
	if(this.textboxID != null){this.textboxID.value="";}
	this.textbox.focus();
	{this.provider.requestSuggestions(this,false);}

};


/** doverm 030306
 * Handles onfocus events.  Populates the dropdown with filtered data.
 * @scope private
 * @param oEvent The event object for the onfocus event.
 */
AutoSuggestControl_MultiFiltered.prototype.getSuggestions = function(oEvent) {
//document.body.style.cursor = "wait";

if(this.textboxHold==null || this.textbox.value.length>0) {
	this.holdValues();
}	
//this.textbox.value="";
//if(this.textboxID != null){
//	this.textboxID.value="";
//}
//alert(this.SuggestionClicked);
this.cur = -1;

this.SuggestionClicked = false
if(this.SuggestionClicked ==false)
{
//	this.textbox.value="";
//	if(this.textboxID != null){
//	this.textboxID.value="";
//	}
	this.provider.requestSuggestions(this, false);
}
else
{
	this.SuggestionClicked =false;
	this.textbox.blur();
}

//document.body.style.cursor = "default";
};


/** doverm 030306
 * Handles onclick events. 
 * @scope private
 * @param oEvent The event object for the onfocus event.
 */
AutoSuggestControl_MultiFiltered.prototype.howdy = function (oEvent) {
//TODO: QUESTION: How does the wdc screw up this control?
//alert("howdy");
//this.provider.requestSuggestions(this, false);
};

/**
 * Hides the suggestion dropdown.
 * @scope private
 */
AutoSuggestControl_MultiFiltered.prototype.hideSuggestions = function () {
    this.layer.style.visibility = "hidden";
    /*this.scrollPos=0;	reset the scroll position*/
    //Hold on to the textbox values after onblur event
    this.holdValues();

    //if textboxID value is blank, clear the textbox.
	//This to keep the two boxes in synch
	if(this.textboxID !=null && this.textboxID.value.length==0)
	{this.textbox.value="";}
	//set to the default value if this control has no value selected 
	//and if includes a textboxDefaultValueArray
	if(this.textbox.value.length==0 && 
	this.textboxDefaultValueArray!=null && 
	this.textboxDefaultValueArray.length>0){
			//debugger;
			this.textbox.value=this.textboxDefaultValueArray[0];
			if(this.textboxID!=null){
				this.textboxID.value=this.textboxDefaultValueArray[1];
			}
        }
};

/**
 * Highlights the given node in the suggestions dropdown.
 * @scope private
 * @param oSuggestionNode The node representing a suggestion in the dropdown.
 */
AutoSuggestControl_MultiFiltered.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_MultiFiltered.prototype.init = function() {

    //save a reference to this object
    var oThis = this;

    
    //doverm 030306 - assign the onfocus event handler
    this.textbox.onfocus = function(oEvent) {

        //check for the proper location of the event object
        if (!oEvent) {
            oEvent = window.event;
        }

        //populate the textbox with suggestions
        oThis.getSuggestions(oEvent);
    };

    //doverm 030306 - assign the onfocus event handler
    this.textbox.onclick = function(oEvent) {

        //check for the proper location of the event object
        if (!oEvent) {
            oEvent = window.event;
        }

        //populate the textbox with suggestions
        oThis.howdy(oEvent);
    };

    //assign the onkeyup event handler to the textbox
    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);
    };

    if (this.chkFilter != null) {
        //assign the onkeyup event handler to the chkFilter, if exists
        this.chkFilter.onclick = 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_chkFilter(oEvent);
        };
    }
    //debugger;
    //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();
    };
    if (this.browser == "IE") {
        /*v3.0 start*/
        //debugger;
        //        if(this.btnScrollUp.attachEvent)
        //            this.btnScrollUp.attachEvent('onclick',oThis.getSuggestions());
        //        else    
        //            this.btnScrollUp.setAttribute('onclick',oThis.getSuggestions());

        // debugger;
        this.btnScrollUp.onclick = function(oEvent) {
            //alert("howdy from btnScrollUp");
            //check for the proper location of the event object
            if (!oEvent) {
                oEvent = window.event;
            }
            oThis.scrollPos = oThis.scrollPos - oThis.pageSize;
            //populate the textbox with suggestions
            oThis.getSuggestions(oEvent);
        }
        this.btnScrollDown.onclick = function(oEvent) {
            //check for the proper location of the event object
            if (!oEvent) {
                oEvent = window.event;
            }
            //this.style.backgroundColor = '#ff0000';
            //alert("howdy from btnScrollDown");
            oThis.scrollPos = oThis.scrollPos + oThis.pageSize;
            //populate the textbox with suggestions
            oThis.getSuggestions(oEvent);
        }
        /*v3.0 end */
    }
    //create the suggestions dropdown
    this.createDropDown();
};

/**
 * Highlights the next suggestion in the dropdown and
 * places the suggestion into the textbox.
 * @scope private
 */
AutoSuggestControl_MultiFiltered.prototype.nextSuggestion = function () {
    var cSuggestionNodes = this.layer.childNodes;

    if (cSuggestionNodes.length > 0 && this.cur < cSuggestionNodes.length-1) {
        var oNode = cSuggestionNodes[++this.cur];
        this.highlightSuggestion(oNode);
        if(this.textboxID != null)
        {
			X=oNode.firstChild.nodeValue.split(",")
			this.textbox.value = X[0]
			this.textboxID.value=X[1];
		}
		else
		{
			this.textbox.value = oNode.firstChild.nodeValue;
		}
       // this.textbox.value = oNode.firstChild.nodeValue; 
    }
};

/**
 * Highlights the previous suggestion in the dropdown and
 * places the suggestion into the textbox.
 * @scope private
 */
AutoSuggestControl_MultiFiltered.prototype.previousSuggestion = function () {
    var cSuggestionNodes = this.layer.childNodes;

    if (cSuggestionNodes.length > 0 && this.cur > 0) {
        var oNode = cSuggestionNodes[--this.cur];
        this.highlightSuggestion(oNode);
        if(this.textboxID != null)
        {
			X=oNode.firstChild.nodeValue.split(",")
			this.textbox.value = X[0]
			this.textboxID.value=X[1];
		}
		else
		{
			this.textbox.value = oNode.firstChild.nodeValue;
		}
       // this.textbox.value = oNode.firstChild.nodeValue;   
    }
};

/**
 * Selects a range of text in the textbox.
 * @scope public
 * @param iStart The start index (base 0) of the selection.
 * @param iLength The number of characters to select.
 */
AutoSuggestControl_MultiFiltered.prototype.selectRange = function (iStart /*:int*/, iLength /*:int*/) {

    //use text ranges for Internet Explorer
    if (this.textbox.createTextRange) {
        var oRange = this.textbox.createTextRange(); 
        oRange.moveStart("character", iStart); 
        oRange.moveEnd("character", iLength - this.textbox.value.length);      
        oRange.select();
        
    //use setSelectionRange() for Mozilla
    } else if (this.textbox.setSelectionRange) {
        this.textbox.setSelectionRange(iStart, iLength);
    }     

    //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_MultiFiltered.prototype.showSuggestions = function(aSuggestions /*:Array*/) {

    var oDiv = null;

    this.layer.innerHTML = "";  //clear contents of the layer

    //this.oPanel=document.createElement("panel");//panel add	


    for (var i = 0; i < aSuggestions.length; i++) {
        oDiv = document.createElement("div");
        /*
        if(aSuggestions[i][0] != null)	//check for multidim array that carries values and IDs
        {
        oDiv.appendChild(document.createTextNode(aSuggestions[i][0]));	//First element of multidim array
        }
        else
        {
        oDiv.appendChild(document.createTextNode(aSuggestions[i]));
        }
        */
        if (aSuggestions[0][0] != undefined) {
            if (aSuggestions[0][0].indexOf("session timed-out") >= 0)	//handle session time-out errors
            {
                oDiv.appendChild(document.createTextNode(aSuggestions[i]));
                return;
            }
            else {
                oDiv.appendChild(document.createTextNode(aSuggestions[i]));
            }
        }
        else {
            if (aSuggestions[0].indexOf("session timed-out") >= 0)	//handle session time-out errors
            {
                oDiv.appendChild(document.createTextNode(aSuggestions[i]));
                return;
            }
            else {
                oDiv.appendChild(document.createTextNode(aSuggestions[i]));
            }
        }



        this.layer.appendChild(oDiv);

    }

    if (this.browser == "IE") {
        /*v3.0 - scoll up down*/
        var oDivScroll = null;
        oDivScroll = document.createElement("div");
        /**/

        oDivScroll.appendChild(this.btnScrollDown);
        oDivScroll.appendChild(this.btnScrollUp);

        /*
        oDivScroll.appendChild(document.createElement("<input name='scrollDown' type='button' value='v' />"));     
        oDivScroll.appendChild(document.createElement("<input name='scrollUp' type='button' value='^' />"));  
        */
        this.layer.appendChild(oDivScroll);
    }
    else {
        var oDivScrollMsg = null;
        oDivScrollMsg = document.createElement("div");
        oDivScrollMsg.appendChild(this.lblScrollMsg);
        this.layer.appendChild(this.lblScrollMsg);
    }
    if (this.browser == "IE") {
        //for some reason adding 15 to top and 10 to left makes layer align better for IE
        this.layer.style.top = (this.getTop() + this.textbox.offsetHeight) + 15 + "px";
        this.layer.style.left = this.getLeft() + 10 + "px";
    }
    else {
        this.layer.style.top = (this.getTop() + this.textbox.offsetHeight) + "px";
        this.layer.style.left = this.getLeft() + "px";
    }
    this.layer.style.visibility = "visible";


    if (this.textboxID == null) {

        //071806 fire this object's onDataFilled event, passing the data object as a parameter
        //account for *IsBlank, *IsNotBlank and a Blank for NSFNumberDD
        //		if(aSuggestions[1].indexOf("*")>=0)
        //		{
        //			this.count=aSuggestions.length-4;
        //		}
        //		else
        //		{
        this.count = aSuggestions.length - 1;
        //		}

    }
    else {
        this.count = aSuggestions.length - 1;
    }
    this.onDataFilled.fire(this);

};

/**
 * Inserts a suggestion into the textbox, highlighting the 
 * suggested part of the text.
 * @scope private
 * @param sSuggestion The suggestion for the textbox.
 */
AutoSuggestControl_MultiFiltered.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; 
        try
        {
			this.selectRange(iLen, sSuggestion.length);
        }
        catch(ex)
        {
			alert(ex.message);
        }
    }
};

