function findPosX(obj)
{
    var curleft = 0;
	if (obj.offsetParent)
	{
		while (obj.offsetParent)
		{
			curleft += obj.offsetLeft;
			obj = obj.offsetParent;
		}
	}
	else if (obj.x)
        curleft += obj.x;
	return curleft;
}

function findPosY(obj)
{
	var curtop = 0;
	if (obj.offsetParent)
	{
		while (obj.offsetParent)
		{
			curtop += obj.offsetTop;
			obj = obj.offsetParent;
		}
	}
	else if (obj.y)
		curtop += obj.y;
	return curtop;
}	

function getUserAgentVersion(userAgent, versionName)
{
	var version = 0.0;
	var tempStr = userAgent.toLowerCase();
	var pos = tempStr.indexOf(versionName);
		
	if (pos != -1) 
	{
		var versionStr = tempStr.substring(pos + versionName.length,tempStr.length);
		if (versionStr.indexOf(" ") > -1)
			version = parseFloat(versionStr.substring(0, versionStr.indexOf(" ")));
		else
			version = parseFloat(versionStr);
	}
	return version;
}

function AjaxDropDown(config)
{
    if (typeof config != 'undefined')
        this.Init(null, null, null, null, config);
}

AjaxDropDown.prototype.Init = function(instanceName, anchorControlId, dropdownId, url, config)
{
    this.instanceName = '';
    this.anchorControlId = '';
    this.dropdownId = '';
    this.url = '';
    this.hideDelay = 300;
    this.uselist = false;           // true= ul/li, etc ; false= div
    this.setposition = true;
    this.listclass = '';            // class to use on the list (li), uselist must be set to true
    this.ondropdownclick = null;    // method to call when the user clicks on an option    
    this.logged = false;
    this.suggestDisabled = null;
    this.turnOff = null;
    this.searchItems = null;
    this.searchcurrentpos = -1;
    
    if (typeof config != 'undefined')
    {
        this.instanceName = config['instancename'];
        this.anchorControlId = config['anchorcontrolid'];
        this.dropdownId = config['dropdownid'];
        this.url = config['url'];

        if (typeof config['hidedelay'] != 'hidedelay')
            this.hidedelay = config['hidedelay'];

        if (typeof config['uselist'] != 'undefined')
        {
            this.uselist = config['uselist'] === true;
            this.setposition = false;
        }
        
        if (typeof config['listclass'] != 'undefined')
            this.listclass = config['listclass'];
        if (typeof config['onDropDownClick'] != 'undefined')
            this.ondropdownclick = config['onDropDownClick'];
        if (typeof config['isipuser'] != 'undefined')
            this.isipuser = config['isipuser'];
        if (typeof config['logged'] != 'undefined')
            this.logged = config['logged'];
        if (typeof config['suggestDisabled'] != 'undefined')
            this.suggestDisabled = config['suggestDisabled'];
        if (typeof config['turnoff'] != 'undefined')
            this.turnOff = config['turnoff'];
    }
    else
    {
        this.instanceName = instanceName;
        this.anchorControlId = anchorControlId;
        this.dropdownId = dropdownId;
        this.url = url;
        this.hideDelay = 300;
        this.logged = this.Logged;
        if (typeof this.logged == 'undefined')
            this.logged = false;
        if (typeof this.isipuser == 'undefined')
            this.isipuser = false;
        this.suggestDisabled = this.DisableSuggest;
        this.turnOff = this.TurnOff;
    }

    this.turnoffMessage1 = "TURN SUGGESTIONS OFF";
    this.turnoffMessage2 = "(adjust preferences in " + (this.isipuser ? "Desktop" : "My Safari") + ")";
    this.isIE = false;
    this.timer = null;
    this.lastQuery = "";
    this.active = true;
    if (window.XMLHttpRequest) 
        this.httpReq = new XMLHttpRequest();

    var dropdown = document.getElementById(this.dropdownId);
    dropdown.style.display = "none";
    if (this.setposition)
        dropdown.style.position = "absolute";

    var ua = navigator.userAgent.toLowerCase(); 
    if (this.setposition)
    {
        if (ua.indexOf("safari") > -1)
        {
            dropdown.style.top = "auto";
            dropdown.style.left = "auto";
            dropdown.style['marginTop'] = "20px";
        
            // disable dropdown for older safari versions (known to crash)
            if (getUserAgentVersion(ua, "applewebkit/") < 418.9 || getUserAgentVersion(ua, "safari/") < 419.3)
                this.active = false;				
        }
        else
        {
            dropdown.style.top = "auto";
            dropdown.style.left = "auto";
        }
    }

    if (navigator.product == "Gecko" && ua.indexOf('webkit') == -1)
    {
        var thisObj = this;
        document.getElementById(this.anchorControlId).addEventListener("keypress", function (event) { thisObj.keyPress(event); }, false);
        document.getElementById(this.anchorControlId).addEventListener("blur", function () { thisObj.Hide(); },false);
    } 
    else
    {
        var thisObj = this;
        try
        {
            document.getElementById(this.anchorControlId).attachEvent('onkeydown', function (event) { thisObj.keyPress(event); });
            document.getElementById(this.anchorControlId).attachEvent('onblur', function () { thisObj.Hide(); });
            this.isIE = true;
        }
        catch (E)
        {
            //for Konqueror
            document.getElementById(this.anchorControlId).onkeydown = function (event) { thisObj.keyPress(event); };
            document.getElementById(this.anchorControlId).onblur = function () { thisObj.Hide(); };
        }
    }

    document.getElementById(this.anchorControlId).setAttribute("autocomplete","off");      
}

AjaxDropDown.prototype.Hide = function() 
{
    var thisObj = this;
    window.setTimeout(function() { thisObj.hideDropDown(); }, this.hideDelay);
}
      
AjaxDropDown.prototype.hideDropDown = function() 
{
    if (document.all)
        this.closeShim(document.getElementById(this.dropdownId));
    document.getElementById(this.dropdownId).style.display = "none";
    this.removeHighlight();
}

AjaxDropDown.prototype.removeHighlight = function()
{
    var activeLine = document.getElementById("DropDownActive");
    if (activeLine)
        activeLine.removeAttribute("id");
    return activeLine;
}

AjaxDropDown.prototype.setHighlight = function(elm)
{
    this.removeHighlight();
    elm.setAttribute("id", "DropDownActive");
}

AjaxDropDown.prototype.keyPress = function(event) 
{
    if (this.active == false)
        return;

    if (this.suggestDisabled && this.suggestDisabled())
        return;
        
    if (event.keyCode == 13)
    {
        highlight = document.getElementById("DropDownActive");
        if (!highlight || highlight.firstChild.data != this.turnoffMessage1)
            this.Start(event);
        else
        {
            if (!this.isIE) 
                event.preventDefault();
            this.Hide();
            if (this.turnOff)
                this.turnOff();
        }
    }
    else if (event.keyCode == 40 || event.keyCode == 63233)
    {
        highlight = document.getElementById("DropDownActive");
        if (!highlight)
        {
            this.searchcurrentpos = 0;
            highlight = document.getElementById(this.dropdownId + "_inner").firstChild.firstChild;
        }
        else 
        {
            highlight.removeAttribute("id");
            if (highlight.nextSibling)
            {
                this.searchcurrentpos += 1;
                var dta = highlight.nextSibling.firstChild.data;
                if (escape(dta) == "%A0")
                    highlight = highlight.nextSibling.nextSibling;
                else
                {
                    if (dta == this.turnoffMessage2)
                    {
                        highlight.setAttribute("id","DropDownActive");
                        return;
                    }
                    else
                        highlight = highlight.nextSibling;
                }
            }
        }
        
        if (highlight) 
        {
            highlight.setAttribute("id","DropDownActive");
            var res = document.getElementById(this.dropdownId);
            if (highlight.offsetTop + highlight.offsetHeight > res.scrollTop + res.offsetHeight)
                res.scrollTop = highlight.offsetTop - res.offsetHeight + highlight.offsetHeight;
        }

        if (!this.isIE) 
            event.preventDefault();

        if (highlight)
        {
            var selectedtext = this._getSelectedText(this.searchcurrentpos);
            if (selectedtext != null)
                this.SelectionChanged(selectedtext);
        }
    }
    else if (event.keyCode == 38 || event.keyCode == 63232)
    {
        highlight = document.getElementById("DropDownActive");
        if (!highlight)
        {
            this.searchcurrentpos = this.searchItems.items.length - 1;
            highlight = document.getElementById(this.dropdownId + "_inner").firstChild.lastChild;
        }
        else 
        {
            highlight.removeAttribute("id");
            if (highlight.previousSibling)
            {
                this.searchcurrentpos -= 1;
                if (escape(highlight.previousSibling.firstChild.data) == "%A0")
                    highlight = highlight.previousSibling.previousSibling;
                else
                    highlight = highlight.previousSibling;
            }
        }

        if (highlight) 
        {
            highlight.setAttribute("id","DropDownActive");
            var res = document.getElementById(this.dropdownId);
            if (highlight.offsetTop < res.scrollTop)
                res.scrollTop = highlight.offsetTop;
        }
        
        if (!this.isIE)
            event.preventDefault();

        if (highlight)
            this.SelectionChanged(this._getSelectedText(this.searchcurrentpos));
    } 
    else if (event.keyCode == 27) 
    {
        highlight = document.getElementById("DropDownActive");
        if (highlight)
            highlight.removeAttribute("id");
        if (document.all)
            this.closeShim(document.getElementById(this.dropdownId));
        document.getElementById(this.dropdownId).style.display = "none";
    }
    else
        this.Start(event);
}

AjaxDropDown.prototype._getSelectedText = function(index)
{
    var ssize = this.searchItems.items.length;
    if (index < ssize)
        return this.searchItems.items[index];
    return null;
}

AjaxDropDown.prototype.SelectionChanged = function(contents)
{
    document.getElementById(this.anchorControlId).value = contents;
}

AjaxDropDown.prototype.Start = function(evt) 
{
    if (this.timer) 
        window.clearTimeout(this.timer);

    var keyCode = document.layers ? evt.which : document.all ? evt.keyCode : evt.keyCode;
    if (keyCode != 13)
    {
        var thisObj = this;
        this.timer = window.setTimeout(function() { thisObj.Search(); }, 200);
    }
}

AjaxDropDown.prototype.Search = function() 
{
    var query = document.getElementById(this.anchorControlId).value;
    if (this.lastQuery != query) 
    {     
        if (this.httpReq && this.httpReq.readyState < 4) 
            this.httpReq.abort();

        if (query == '') 
        {
            this.lastQuery = '';
            this.hideDropDown();
            return false;
        }

        if (window.XMLHttpRequest) 
        {
        } 
        else if (window.ActiveXObject) 
            this.httpReq = new ActiveXObject("Microsoft.XMLHTTP");

        var thisObj = this;
        this.httpReq.onreadystatechange = function () { thisObj.readyStateChange(); };
        this.httpReq.open("GET", this.url + encodeURIComponent(query));
        this.httpReq.setRequestHeader("If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT");
        this.lastQuery = query;
        this.httpReq.send(null);
    }
}

AjaxDropDown.prototype.readyStateChange = function() 
{
    if (this.httpReq.readyState == 4 && this.httpReq.responseText != "") 
    {     
        var inner = document.getElementById(this.dropdownId + "_inner");
        
        var xml = this.httpReq.responseXML.documentElement;
        this.searchItems = AjaxDropDown.GetItems(xml);
        this.searchcurrentpos = -1;
        var html = this.createList(this.searchItems);

        if (!this.uselist && this.searchItems.items.length > 0)
        {
            if (this.logged && this.isipuser == false)
            {
                html += "<div style='white-space: nowrap;'>&nbsp;</div>";
                if (document.all)
                    html += "<div style='width:200px; ";
                else
                    html += "<div style='white-space: nowrap; "
                html += "' onmouseover='" + this.instanceName + ".dropdownHover(this)' onclick='" + this.instanceName + ".dropdownClicked(this)'>" + this.turnoffMessage1 + "</div>";
                if (document.all)
                    html += "<div style='width:200px; ";
                else
                    html += "<div style='white-space: nowrap; "					
                html += "'>" + this.turnoffMessage2 + "</div>";
            }
        }
        
        if (!this.uselist)
            html += "</div>";
            
        inner.innerHTML = html;

        var ddown = document.getElementById(this.dropdownId);
        if (this.searchItems.items.length > 0)
        {
            ddown.style.display = "block";
            if (document.all)
                this.openShim(ddown);
        }
        else
        {
            ddown.style.display = "none";
            if (document.all)
                this.closeShim(ddown);
        }
    }
}

AjaxDropDown.GetItems = function(xml)
{
    var suggestions = xml.getElementsByTagName("suggestion");
    
    var itemsContainer = new Object();
    itemsContainer.items = new Array();
    itemsContainer.kinds = new Array();

    for(var i = 0; i < suggestions.length; i++)
    {
        var elementAttr = suggestions.item(i).attributes;
        var elementText = suggestions.item(i).firstChild.data;
        var elementKind = elementAttr.getNamedItem("kind").nodeValue;
        
        itemsContainer.kinds[i] = elementKind;
        if (elementKind != "0")
            itemsContainer.items[i] = elementText;
        else
            itemsContainer.items[i] = String(elementText).toLowerCase();
    }	

    return itemsContainer;
}

AjaxDropDown.GetStyle = function(kind)
{
    if (kind == "3")
        return "font-weight:bold";
    else if (kind != "0")
        return "font-style:italic";
    return "";
}

AjaxDropDown.prototype.createList = function(lst)
{
    var html = '';
    
    if (this.uselist)
        html = '<ul class="' + this.listclass + '">';
    else
        html = "<div class='DropDownResults'" + (document.all ? " style='width:200px'" : "") + ">";

    for (var i = 0; i < lst.items.length; ++i)
    {
        var mouseover = 'onmouseover="' + this.instanceName + '.dropdownHover(this, ' + i + ')"';
        var mouseclick = 'onclick="' + this.instanceName + '.dropdownClicked(this, ' + i + ')"';

        if (this.uselist)
        {
            var alink = '<a href="#"' + mouseclick + '>' + lst.items[i] + '</a>';

            html += '<li ' + mouseover + '>';

            var kind = lst.kinds[i];
            if (kind == "3")
                html += '<strong>' + alink + '</strong>';
            else if (kind != "0")
                html += '<em>' + alink + '</em>';
            else
                html += alink;

            html += '</li>';
        }
        else
        {
            var st = AjaxDropDown.GetStyle(lst.kinds[i]);
            if (document.all)
                html += "<div style='width:200px; ";
            else
                html += "<div style='white-space: nowrap; "
            html += st + "' " + mouseover + " " + mouseclick + ">" + lst.items[i] + "</div>";
        }
    }
    
    if (this.uselist)
        html += '</ul>';

    return html;
}

AjaxDropDown.prototype.dropdownHover = function(el, index)
{
    this.setHighlight(el);
    this.searchcurrentpos = index;
}

AjaxDropDown.prototype.dropdownClicked = function(el, index) 
{
    if (el.firstChild.data == this.turnoffMessage1)
    {
        this.Hide();
        if (this.TurnOff)				
            this.TurnOff();
    }
    else if (el.firstChild.data != this.turnoffMessage2)
    {
        this.setHighlight(el);
        return this.Clicked(this.searchItems.items[index]);
    }
    this.searchcurrentpos = index;
}

AjaxDropDown.prototype.Clicked = function(contents)
{
    document.getElementById(this.anchorControlId).value = contents;
    if (this.ondropdownclick)
        this.ondropdownclick();
}

//Creates a new shim for the dropdown
AjaxDropDown.prototype.createShim = function(dropdown)
{
    if (dropdown == null)
        return null;

    var shim = document.createElement("<iframe scrolling='no' frameborder='0' " +
                                      "style='position:absolute; top:0px; left:0px; display:none'></iframe>"); 
    shim.name = this.getShimId(dropdown);
    shim.id = this.getShimId(dropdown);

    if (dropdown.offsetParent == null || dropdown.offsetParent.id == "") 
        window.document.body.appendChild(shim);
    else 
        dropdown.offsetParent.appendChild(shim); 

    return shim;
}

//Creates an id for the shim based on the dropdown id
AjaxDropDown.prototype.getShimId = function(dropdown)
{
    if (dropdown.id == null)
        return "__shim";
    return "__shim" + dropdown.id;
}

//Returns the shim for a specific dropdown
AjaxDropDown.prototype.getShim = function(dropdown)
{
    return document.getElementById(this.getShimId(dropdown));
}
      
//Opens a shim, if no shim exists for the menu, one is created
AjaxDropDown.prototype.openShim = function(dropdown)
{
    if (dropdown==null) 
        return;

    var shim = this.getShim(dropdown);
    if (shim == null)
        shim = this.createShim(dropdown,this.getShimId(dropdown));

    //Change menu zIndex so shim can work with it
    dropdown.style.zIndex = 1000;

    var width = dropdown.offsetWidth;
    var height = dropdown.offsetHeight;

    shim.style.width = width;
    shim.style.height = height;
    shim.style.left = findPosX(dropdown) + "px";
    shim.style.top = findPosY(dropdown) + "px";
    shim.style.zIndex = dropdown.style.zIndex - 1;
    shim.style.position = "absolute";
    /*shim.style.display = "block";*/
}

//Closes the shim associated with the dropdown
AjaxDropDown.prototype.closeShim = function(dropdown)
{
    if (dropdown == null)
        return;

    var shim = this.getShim(dropdown);
    if (shim != null)
        shim.style.display = "none";
}
