/* --------------------- Copyright Marcin Zadęcki - WSZYSTKIE PRAWA ZASTRZEŻONE --------------------- */
/* ---------- Wykorzystywanie całości lub fragmentów kodu wyłącznie za zgodą Marcin Zadęcki --------- */
Number.prototype.NaN0 = function() { return isNaN(this) ? 0 : this; }
function acAddEvent(e, fn)
{
    var old = this[e];
    if(old)
    {
        this[e] = function(e)
        {
            old();
            fn();
        };
    }
    else
        this[e] = fn;
};
function AutoComplete(sFormName, sInputName, aFieldNames, setFieldsFunc, clearFieldsFunc, progressAnimFunc)
{
    var oBrowser             = navigator.userAgent;
    this.MSIE                = false;
    if(oBrowser.indexOf('MSIE') >= 0 && oBrowser.indexOf('Opera') < 0) this.MSIE = true;
    this.FORM_NAME           = sFormName;
    this.FORM_FIELDS         = aFieldNames;
    this.setFieldsReadyState = setFieldsFunc;
    this.clearFieldsFunc     = clearFieldsFunc;
    this.progressAnimFunc    = progressAnimFunc;
    if(!this.OLD_ONSUBMIT_FUNC) this.OLD_ONSUBMIT_FUNC = document.forms[this.FORM_NAME].onsubmit;
    //init onload
    var oCopy = this;
    window.acAddEvent('onload', function() {
        document.forms[oCopy.FORM_NAME].elements[sInputName].setAttribute('autocomplete', 'off');
        oCopy.autoHide(sInputName);
        return;
    });
}
AutoComplete.prototype = {
     BOX_OFFSET_X            : 0
    ,BOX_OFFSET_Y            : -1
    ,SCROLL_LEAD             : 20
    ,MIN_LETTERS_LOOKUP      : 1
    ,AUTO_COMPLETE_SHOW_DELAY: 700
    ,CACHING                 : true
    ,EXTERNAL_FILE           : ''
    ,EXTERNAL_QS             : ''
    ,CSS_DIV_SELECTED        : 'optionDivSelected'
    ,CSS_DIV_NORMAL          : 'optionDiv'
    ,CSS_LETTERS             : 'letters'
    ,AUTO_COMPLETE_DIV       : 'auto_complete_div'
    ,AUTO_COMPLETE_IFRAME    : 'auto_complete_iframe'
    ,AUTO_COMPLETE_SRC_IFRAME: 'js/autocomplete-blank.html'
    ,DIVS_OBJ                : false
    ,IFRAME_OBJ              : false
    ,ACTIVE_INPUT_OBJ        : null
    ,ACTIVE_OPTION_OBJ       : null
    ,FIRST_OPTION_OBJ        : null
    ,LAST_OPTION_OBJ         : null
    ,OLD_ONSUBMIT_FUNC       : null
    ,OLD_ONCLICK_FUNC        : null
    ,CURRENT_LETTERS         : null
    ,TIMER_SHOW              : null
    ,CACHED                  : new Array()
    ,XH_OBJ                  : new Array()
    ,trim: function(str, mode)
    {
        if(mode == 'left')      return str.replace(/^\s*/, '');
        if(mode == 'right')     return str.replace(/\s*$/, '');
        if(mode == 'normalize') return this.GItrim(str.replace(/\s{2,}/g, ' '));
        return this.trim(this.trim(str, 'left'), 'right');
    }
    ,progressAnim: function(bool)
    {
        if(this.progressAnimFunc) this.progressAnimFunc(bool);
    }
    ,getTopPos: function(oInput)
    {
        var iTopPos = 0;
        if(oInput.offsetParent)
        {
            do
            {
                iTopPos += parseInt(oInput.offsetTop) || 0;
                iTopPos += (oInput.currentStyle ? parseInt(oInput.currentStyle.border).NaN0() : 0);
                oInput   = oInput.offsetParent;
            }
            while(oInput && oInput.tagName.toUpperCase() != 'BODY');
        }
        else if(oInput.y)
        {
            iTopPos  = parseInt(oInput.y);
            iTopPos += (oInput.currentStyle ? parseInt(oInput.currentStyle.border).NaN0() : 0);
        }
        return iTopPos;
    }
    ,getLeftPos: function(oInput)
    {
        var iLeftPos = 0;
        if(oInput.offsetParent)
        {
            do
            {
                iLeftPos += oInput.offsetLeft || 0;
                iLeftPos += (oInput.currentStyle ? parseInt(oInput.currentStyle.border).NaN0() : 0);
                oInput    = oInput.offsetParent;
            }
            while(oInput && oInput.tagName.toUpperCase() != 'BODY');
        }
        else if(oInput.x)
        {
            iLeftPos  = parseInt(oInput.x);
            iLeftPos += (oInput.currentStyle ? parseInt(oInput.currentStyle.border).NaN0() : 0);
        }
        return iLeftPos;
    }
    ,setBoxPosition: function(oInput)
    {
        this.DIVS_OBJ.style.top  = (this.getTopPos(oInput)+oInput.offsetHeight+this.BOX_OFFSET_Y)+'px';
        this.DIVS_OBJ.style.left = (this.getLeftPos(oInput)+this.BOX_OFFSET_X)+'px';
        if(this.IFRAME_OBJ)
        {
            this.IFRAME_OBJ.style.left = this.DIVS_OBJ.style.left;
            this.IFRAME_OBJ.style.top  = this.DIVS_OBJ.style.top;
        }		
    }
    ,hideBox: function()
    {
		if(this.DIVS_OBJ)   this.DIVS_OBJ.style.display   = 'none';	
		if(this.IFRAME_OBJ) this.IFRAME_OBJ.style.display = 'none';
    }
    ,autoHide: function(sInputName)
    {
        var oCopy                        = this;
        var oldOnClick                   = document.documentElement.onclick;
        document.documentElement.onclick = function(e) {
            if(oldOnClick) oldOnClick(e);
            e = (e) ? e : event;
            if(e.target)              oSource = e.target;
            else if(e.srcElement)     oSource = e.srcElement;
            if(oSource.nodeType == 3) oSource = oSource.parentNode; //defeat Safari bug
            if(oSource.name != sInputName)
            {
                oCopy.hideBox();
            }
        }
    }
    ,optionRollOver: function(oItem, bKeyBoard)
    {
        if(!oItem) return;
        if(this.ACTIVE_OPTION_OBJ) this.ACTIVE_OPTION_OBJ.className = this.CSS_DIV_NORMAL;
        oItem.className        = this.CSS_DIV_SELECTED;
        this.ACTIVE_OPTION_OBJ = oItem;
        if(bKeyBoard)
        {
            var iNewScrollTop = this.ACTIVE_OPTION_OBJ.offsetTop - this.DIVS_OBJ.offsetHeight + (this.ACTIVE_OPTION_OBJ.offsetHeight * 2);
            if(iNewScrollTop < 0) iNewScrollTop = 0;
            var iActiveRow       = Math.floor(this.ACTIVE_OPTION_OBJ.offsetTop / this.ACTIVE_OPTION_OBJ.offsetHeight) + 1;
            var iVisibleRows     = Math.floor(this.DIVS_OBJ.offsetHeight / this.ACTIVE_OPTION_OBJ.offsetHeight) - 1;
            var iVisibleRowFirst = Math.ceil(this.DIVS_OBJ.scrollTop / this.ACTIVE_OPTION_OBJ.offsetHeight) + 1;
            var iVisibleRowLast  = iVisibleRowFirst + iVisibleRows - 1;
            if(iActiveRow < iVisibleRowFirst || iActiveRow >= iVisibleRowLast)
                this.DIVS_OBJ.scrollTop = iNewScrollTop;
        }
        return;
    }
    ,onSetReadyState: function(obj)
    {
        obj.AC_OBJ.progressAnim(false);
        if(!obj.XH_OBJ.responseText) return;
        var aDbData = obj.XH_OBJ.responseText.split(String.fromCharCode(31));
        //Powinno być więcej pól z bazy niż do uzupełnienia
        if(aDbData.length < obj.AC_OBJ.FORM_FIELDS.length) return;
        obj.AC_OBJ.setFieldsReadyState(obj.AC_OBJ, aDbData);
        document.forms[obj.AC_OBJ.FORM_NAME].onsubmit = function() {
            if(obj.AC_OBJ.OLD_ONSUBMIT_FUNC) obj.AC_OBJ.OLD_ONSUBMIT_FUNC();
            return true;
        }
    }
    ,setFieldValues: function(obj, sAction)
    {
        this.hideBox();
        if(!obj) return;
        this.progressAnim(true);
        var oAjax           = new XHclient();
        oAjax.XH_XML_FORMAT = false;
        oAjax.sAction       = sAction;
        oAjax.id            = obj.id;
        oAjax.AC_OBJ        = this;
        oAjax.XHload(this.EXTERNAL_FILE, 'GET', this.EXTERNAL_QS.replace(/&amp;/ig, '&') + sAction + '=1&id=' + escape(obj.id) + '&tstamp=' + new Date().getTime(), this.onSetReadyState);
    }
    ,clearFieldValues: function()
    {
        this.clearFieldsFunc();
    }
    ,keyNavigation: function(e, sAction)
    {
        if(!this.DIVS_OBJ || this.DIVS_OBJ.style.display == 'none') return;
        e = (e) ? e : event;
        var iCharCode = (e.which) ? e.which : event.keyCode;
        //Up arrow
        if(iCharCode == 38)
        {
            if(!this.ACTIVE_OPTION_OBJ || !this.ACTIVE_OPTION_OBJ.previousSibling)
                this.optionRollOver(this.LAST_OPTION_OBJ, true);
            else
                this.optionRollOver(this.ACTIVE_OPTION_OBJ.previousSibling, true);
        }
        //Down arrow
        if(iCharCode == 40)
        {
            if(!this.ACTIVE_OPTION_OBJ || !this.ACTIVE_OPTION_OBJ.nextSibling)
                this.optionRollOver(this.FIRST_OPTION_OBJ, true);
            else
                this.optionRollOver(this.ACTIVE_OPTION_OBJ.nextSibling, true);
        }
        //Enter key
        if(iCharCode == 13)
        {
            document.forms[this.FORM_NAME].onsubmit = function() { return false; }
            if(this.ACTIVE_OPTION_OBJ && this.ACTIVE_OPTION_OBJ.className == this.CSS_DIV_SELECTED)
                this.setFieldValues(this.ACTIVE_OPTION_OBJ, sAction);
        }
        //Tab key
        if(iCharCode == 9)
        {
            this.hideBox();
        }
        //Escape key
        if(iCharCode == 27)
        {
            this.hideBox();
        }
    }
    ,buildOptionList: function(sAction, sLetters)
    {
        var oDiv;
        var aItems              = new Array();
        var oCopy               = this;
        this.DIVS_OBJ.innerHTML = '';
		this.FIRST_OPTION_OBJ   = null;
		this.LAST_OPTION_OBJ    = null;
        this.ACTIVE_OPTION_OBJ  = null;
        for(var i = 0; i < this.CACHED[sAction][sLetters + '_ac'].length; i++)
        {
            if(this.CACHED[sAction][sLetters + '_ac'][i].length <= 0) continue;
            aItems           = this.CACHED[sAction][sLetters + '_ac'][i].split(String.fromCharCode(31));
            if(aItems.length != 2 || !aItems[0] || !aItems[1]) continue;
            oDiv             = document.createElement('DIV');
            oDiv.className   = this.CSS_DIV_NORMAL;
            oDiv.id          = aItems[0];
            oDiv.value       = aItems[1];
            if(this.CSS_LETTERS)
            {
                var sUCase     = this.trim(sLetters.toUpperCase()).replace(/ /, '.*');
                var oRegExp    = new RegExp("(" + sUCase + ")");
                oDiv.innerHTML = aItems[1].replace(oRegExp, '<span class="' + this.CSS_LETTERS + '">$1</span>');
            }
            else
                oDiv.innerHTML = aItems[1];
            oDiv.onmouseover = function() { oCopy.optionRollOver(this, false); }
            oDiv.onclick     = function() { oCopy.setFieldValues(this, sAction); }
            oDiv.onmousedown = function() { oCopy.setFieldValues(this, sAction); }
            if(!this.FIRST_OPTION_OBJ) this.FIRST_OPTION_OBJ = oDiv;
            this.LAST_OPTION_OBJ = oDiv;
            this.DIVS_OBJ.appendChild(oDiv);
        }
        this.DIVS_OBJ.style.display = 'block';
        if(this.IFRAME_OBJ) this.IFRAME_OBJ.style.display = 'block';
        //Przewymiaruj div'y dla FF aby podświetlenie było dla całego rekordu jeżeli występują scrolle
        if(this.DIVS_OBJ.clientWidth < this.DIVS_OBJ.scrollWidth)
        {
            var iAddWidth = this.DIVS_OBJ.scrollWidth;
            for(var i = 0; i < this.DIVS_OBJ.childNodes.length; i++)
            {
                this.DIVS_OBJ.childNodes[i].style.width = iAddWidth + 'px';
            }
        }
        this.optionRollOver(this.FIRST_OPTION_OBJ, true);
        this.progressAnim(false);
    }
    ,buildBox: function(oInput, sAction)
    {
        this.DIVS_OBJ               = document.createElement('DIV');
        this.DIVS_OBJ.id            = this.AUTO_COMPLETE_DIV;	
        this.DIVS_OBJ.style.display = 'none';
        document.body.appendChild(this.DIVS_OBJ);
        if(this.MSIE && !this.IFRAME_OBJ)
        {
            this.IFRAME_OBJ               = document.createElement('IFRAME');
            this.IFRAME_OBJ.id            = this.AUTO_COMPLETE_IFRAME;
            this.IFRAME_OBJ.frameBorder   = '0';
            this.IFRAME_OBJ.src           = this.AUTO_COMPLETE_SRC_IFRAME;
            this.IFRAME_OBJ.style.width   = this.DIVS_OBJ.clientWidth + 'px';
            this.IFRAME_OBJ.style.height  = this.DIVS_OBJ.clientHeight + 'px';
            this.IFRAME_OBJ.style.display = 'none';
            document.body.appendChild(this.IFRAME_OBJ);
        }
        var oCopy = this;
        //OnKeyDown
        var oldOnKeyDown        = document.body.onkeydown;
        document.body.onkeydown = function(e) { oldOnKeyDown; oCopy.keyNavigation(e, sAction); }
        //OnResize
        var oldOnResize = window.onresize;
        window.onresize = function() { if(oldOnResize) oldOnResize; oCopy.setBoxPosition(oInput); }
        this.setBoxPosition(oInput);
    }
    ,onShowReadyState: function(obj)
    {
        var aDbData = obj.XH_OBJ.responseText.split(String.fromCharCode(30));
        if(!obj.XH_OBJ.responseText || aDbData.length <= 0)
        {
            obj.AC_OBJ.progressAnim(false);
            obj.AC_OBJ.hideBox();
            return;
        }
        obj.AC_OBJ.CACHED[obj.sAction][obj.sLetters + '_ac'] = aDbData;
        if(obj.AC_OBJ.CURRENT_LETTERS == obj.sLetters)
        {
            obj.AC_OBJ.buildOptionList(obj.sAction, obj.sLetters);
        }
    }
    ,doShow: function(sAction, sLetters, sAddGetVars)
    {
        if(!sAddGetVars) sAddGetVars = '';
        window.clearTimeout(this.TIMER_SHOW);
        var iXhIndex                        = this.XH_OBJ.length;
        this.XH_OBJ[iXhIndex]               = new XHclient();
        this.XH_OBJ[iXhIndex].XH_XML_FORMAT = false;
        this.XH_OBJ[iXhIndex].sAction       = sAction;
        this.XH_OBJ[iXhIndex].sLetters      = sLetters;
        this.XH_OBJ[iXhIndex].AC_OBJ        = this;
        this.XH_OBJ[iXhIndex].XHload(this.EXTERNAL_FILE, 'GET', this.EXTERNAL_QS.replace(/&amp;/ig, '&') + sAddGetVars + sAction+'=1&letters=' + sLetters.replace(' ', '+') + '&tstamp=' + new Date().getTime(), this.onShowReadyState);
    }
    ,show: function(oInput, sAction, e, sAddGetVars)
    {
        if(!sAddGetVars) sAddGetVars = '';
        if(this.TIMER_SHOW) window.clearTimeout(this.TIMER_SHOW);
        e             = (e) ? e : event;
        var iCharCode = (e.which) ? e.which : event.keyCode;
        //Do not continue if...
        if(iCharCode == 9   //tab (alt+tab)
        || iCharCode == 13  //enter
        || iCharCode == 16  //shift(tab+shift)
        || iCharCode == 17  //ctrl, alt right
        || iCharCode == 18  //alt left
        || iCharCode == 19  //pause/break
        || iCharCode == 20  //caps lock
        || iCharCode == 27  //esc
        || iCharCode == 33  //page up
        || iCharCode == 34  //page down
        || iCharCode == 35  //end
        || iCharCode == 36  //home
        || iCharCode == 37  //arrow left
        || iCharCode == 39  //arrow right
        || iCharCode == 38  //arrow up
        || iCharCode == 40  //arrow down
        || iCharCode == 44  //print screen
        || iCharCode == 91  //start win menu
        || iCharCode == 92  //start win menu
        || iCharCode == 93  //right click win menu
        || iCharCode == 144 //num lock
        || iCharCode == 145 //scroll lock
        || iCharCode == 226 //macro
        )
        {
            return;
        }
        this.hideBox();
        this.progressAnim(false);
        this.clearFieldValues();
        var sLetters = oInput.value;
        if(sLetters.length < this.MIN_LETTERS_LOOKUP)
            return;
        this.progressAnim(true);
        if(!this.CACHED[sAction]) this.CACHED[sAction] = new Array();
        this.CURRENT_LETTERS  = sLetters;
        this.ACTIVE_INPUT_OBJ = oInput;
        this.buildBox(oInput, sAction);
        var oCopy                   = this;
        this.DIVS_OBJ.onselectstart = function() { oCopy.hideBox(); }
        if(this.CACHING && this.CACHED[sAction][sLetters + '_ac'])
        {
            this.buildOptionList(sAction, sLetters);
        }
        else
        {
            if(this.AUTO_COMPLETE_SHOW_DELAY == 0)
                this.doShow(sAction, sLetters, sAddGetVars);
            else
                this.TIMER_SHOW = window.setTimeout(function() { oCopy.doShow(sAction, sLetters, sAddGetVars); }, this.AUTO_COMPLETE_SHOW_DELAY);
        }
    }
}
