/**
* DYNAX - DHTML and Ajax suite.
* @author Vladan Antic
* @date January 2007.
* @version 1.0.1
* @note this is a library of DHTML and AJAX components - it requires both prototype.js and dynamic.js files.
*/

var DYNAX = {
    version: '1.0.1'
}

// global variables
var DYNAX_dBoxIndex  = 0;
var DYNAX_dummyInd   = 0;
var DYNAX_dBoxActive = false;

DYNAX.Base = function() {
    // common variables...
    this.imagePath      = 'images/'; 
    this.iconPath       = 'images/icons/';
    this.iconEmpty      = 'empty.gif';
    this.image1         = '1.gif';
    this.elmIframe      = '<iframe id="dummyFrame" src="/blank.html" style="display: block; position: absolute; top: 0px; left: 0px; width: 0px; height: 0px; z-index: -1; filter: mask(); overflow: none;"></iframe>';
    this.diffX          = 0;
    this.diffY          = 0;
    this.body           = false;
}

DYNAX.Base.prototype = {
    
    setVar: function(vr, vl) {
        var cs = "this." + vr + " = ";
        cs += isString(vr) ? "'" + vl + "'" : vl;
        eval(cs);
    },

    setOption: function(vr, vl) {
        var cs = "this.options." + vr + " = ";
        cs += isString(vr) ? "'" + vl + "'" : vl;
        eval(cs);
    },

    iniLayer: function(id) {
        // get body element needed to set real position of this layer (by including scroll values)
        this.body = document.getElementsByTagName('body')[0];
        
        new Insertion.Top(this.body, '<div id="' + id + '"></div>');
        return $(id);
    },
    
    iniIframe: function(obj) {
        new Insertion.Before(obj, this.elmIframe);
        return $('dummyFrame');
    },

    setDummyLayer: function(ind) {
        ind = ind || false;
        var id = ind ? 'blurLayer' : 'dummyLayer';
        if (!$(id)){
            var dmy = this.iniLayer(id);
            dmy.style.width  = getDocumentWidth() - 20 + 'px';
            dmy.style.height = getDocumentHeight() - 5 + 'px';
//            if (ind) document.body.style.overflow = 'hidden';
            return dmy;
        } else return false;
    },
    
    unsetDummyLayer: function() {
        if ($('blurLayer')) Element.remove('blurLayer');
        if ($('dummyLayer')) Element.remove('dummyLayer');
//        document.body.style.overflow = 'auto';
    },
    
    buildParameterString: function(parameterList) {
        var ajaxParameters = parameterList || '';
        var re = new RegExp("(\\{[^,]*\\})", 'g'); // should retrieve each {} group
        var results = ajaxParameters.match(re);
        if (results != null) {
            for (var r=0; r<results.length; r++) {
                var nre = new RegExp(results[r], 'g');
                var field = $(results[r].substring(1, results[r].length-1));
                ajaxParameters = replaceWithValue(ajaxParameters, nre, field);
            }
        }
        return ajaxParameters;
    },
    
    attachEvent: function(element, event, listener, obj) {
        eval("element.on"+event+" = listener.bindAsEventListener(obj)");
    },
    
    detachEvent: function(element, event) {
        eval("element.on"+event+" = null");
    },
    
    
    /**
    * getCookie()
    * @param name - name of cookie.
    * @return - the value of a cookie.
    */  
    getCookie: function(name) { 
       var start = document.cookie.indexOf(name+"="); 
       var len = start+name.length+1; 
       if ((!start) && (name != document.cookie.substring(0,name.length))) return null; 
       if (start == -1) return null; 
       var end = document.cookie.indexOf(";",len); 
       if (end == -1) end = document.cookie.length; 
       return unescape(document.cookie.substring(len,end)); 
    },
    
    /**
    * setCookie()
    * @param name - name of cookie.
    * @param value - value of cookie
    * @param expires - timestamp of days
    * @param path - path for cookie
    * @param domain - cookie domain
    * @param secure - secure cookie (SSL)
    */  
    setCookie: function(name, value, expires, path, domain, secure) { 
        expires = expires * 60*60*24*1000;
        var today = new Date();
        var expires_date = new Date( today.getTime() + (expires) );
        var cookieString = name + "=" +escape(value) + 
           ( (expires) ? ";expires=" + expires_date.toGMTString() : "") + 
           ( (path) ? ";path=" + path : "") + 
           ( (domain) ? ";domain=" + domain : "") + 
           ( (secure) ? ";secure" : ""); 
        document.cookie = cookieString; 
    },
    
    /**
    * Dragging and mouse functions
    */  
    handleMouseDown: function(oEvent, objId) {
        if ($(objId)) {
            var oDiv = $(objId);
            this.diffX = oEvent.clientX - oDiv.offsetLeft;
            this.diffY = oEvent.clientY - oDiv.offsetTop;
            oDiv.style.cursor = 'move';
            
            this.attachEvent(document.body, 'mousemove', function(){this.handleMouseMove(oEvent, oDiv)}, this);
            this.attachEvent(document.body, 'mouseup', function(){this.handleMouseUp(oEvent, oDiv)}, this);
        }
    },
    
    handleMouseMove: function(oEvent, oDiv) {
        oDiv.style.left = oEvent.clientX - this.diffX + 'px';
        oDiv.style.top = oEvent.clientY - this.diffY + 'px';
    },
    
    handleMouseUp: function(oEvent, oDiv) {
        oDiv.style.cursor = 'default';
        this.detachEvent(document.body, 'mousemove', this);
        this.detachEvent(document.body, 'mouseup', this);
    },
    
    handleOver: function(elm, clss) {
        if ($(elm)){
            $(elm).className = clss;
        } else {
            elm.className = clss;
        }
    }
    
}


/**
* Calendar class.
* @author Vladan Antic.
* @date 2.2007.
* @version 1.0.
* @note calendar tool referenced on HTML element or created as layer; default date format: dd.mm.yyyy; forbiden dates format: yyyymmdd 
*/

DYNAX.Calendar = Class.create();
DYNAX.Calendar.prototype = Object.extend(new DYNAX.Base(), {

    initialize: function(cal_id, options, forbiden) {
        if (!cal_id) return false;
        
        this.id       = cal_id;
        this.forbiden = forbiden || false;
        
        this.calendar        = false;
        this.targetDate      = false;
        this.dummyLayer      = false;
        this.dummyFrame      = false;
        this.today           = new Date();
        this.caleYear        = false;
        this.caleMonth       = false;
        this.labels          = false;
        
        options = options || new Array();
        this.setOptions(options);
        
        switch (this.options.language){
            case 'de': // germany (deutsch)
                var days    = (this.options.dayNames == 'short') ? ['Mo','Di','Mi','Do','Fr','Sa','So'] : ['Mon','Die','Mit','Don','Fre','Sam','Son'];
                var months  = (this.options.monthNames == 'short') ? ['Jan','Feb','Mar','Apr','Mai','Jun','Jul','Aug','Sep','Okt','Nov','Dez'] : ['Januar','Februar','März','April','Mai','Juni','Juli','August','September','Oktober','November','Dezember'];
                this.labels = {
                    days: days,
                    months: months,
                    nextYear: 'Next Year',
                    nextMonth: 'Next Month',
                    prevYear: 'Previous Year',
                    prevMonth: 'Previous Month',
                    today: 'Heute',
                    deleteDate: 'Delete Date',
                    closeCalendar: 'Close Calendar'
                };
                break;
            case 'fr': // french
                var days    = (this.options.dayNames == 'short') ? ['Lu','Ma','Me','Je','Ve','Sa','Di'] : ['Lun','Mar','Mer','Jeu','Ven','Sam','Dim'];
                var months  = (this.options.monthNames == 'short') ? ['Jan','Fev','Mar','Avr','Mai','Jun','Jul','Aou','Sep','Oct','Nov','Dec'] : ['Janvier','Février','Mars','Avril','Mai','Juin','Juillet','Août','Septembre','Octobre','Novembre','Décembre'];
                this.labels = {
                    days: days,
                    months: months,
                    nextYear: 'Next Year',
                    nextMonth: 'Next Month',
                    prevYear: 'Previous Year',
                    prevMonth: 'Previous Month',
                    today: 'Aujourd',
                    deleteDate: 'Delete Date',
                    closeCalendar: 'Close Calendar'
                };
                break;
            case 'it': // italian
                var days    = (this.options.dayNames == 'short') ? ['Lu','Ma','Me','Gi','Ve','Sa','Do'] : ['Lun','Mar','Mer','Gio','Ven','Sab','Dom'];
                var months  = (this.options.monthNames == 'short') ? ['Gen','Feb','Mar','Apr','Mag','Giu','Lugl','Ago','Set','Ott','Nov','Dic'] : ['Gennaio','Febbraio','Marzo','Aprile','Maggio','Giugno','Luglio','Agosto','Settembre','Ottobre','Novembre','Dicembre'];
                this.labels = {
                    days: days,
                    months: months,
                    nextYear: 'Next Year',
                    nextMonth: 'Next Month',
                    prevYear: 'Previous Year',
                    prevMonth: 'Previous Month',
                    today: 'Oggi &egrave; il',
                    deleteDate: 'Delete Date',
                    closeCalendar: 'Close Calendar'
                };
                break;
            case 'sr': // srpski
                var days    = (this.options.dayNames == 'short') ? ['Po', 'Ut', 'Sr', '&#268;e', 'Pe', 'Su', 'Ne'] : ['Ponedeljak', 'Utorak', 'Sreda', '&#268;etvrtak', 'Petak', 'Subota', 'Nedelja'];
                var months  = (this.options.monthNames == 'short') ? ['Jan', 'Feb', 'Mar', 'Apr', 'Maj', 'Jun', 'Jul', 'Avg', 'Sep', 'Okt', 'Nov', 'Dec'] : ['Januar', 'Februar', 'Mart', 'April', 'Maj', 'Juni', 'Juli', 'Avgust', 'Septembar', 'Oktobar', 'Novembar', 'Decembar'];
                this.labels = {
                    days: days,
                    months: months,
                    nextYear: 'Slede&#263;a Godina',
                    nextMonth: 'Slede&#263;i Mesec',
                    prevYear: 'Predhodna Godina',
                    prevMonth: 'Predhodni Mesec',
                    today: 'Danas',
                    deleteDate: 'Brisanje Datuma',
                    closeCalendar: 'Zatvori Kalendar'
                };
                break;
            default: // english
                var days    = (this.options.dayNames == 'short') ? ['Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su'] : ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];
                var months  = (this.options.monthNames == 'short') ? ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] : ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
                this.labels = {
                    days: days,
                    months: months,
                    nextYear: 'Next Year',
                    nextMonth: 'Next Month',
                    prevYear: 'Previous Year',
                    prevMonth: 'Previous Month',
                    today: 'Today',
                    deleteDate: 'Delete Date',
                    closeCalendar: 'Close Calendar'
                };
        };
    },
        
    setOptions: function(options) {
        this.options = Object.extend({
            width: options.width ? options.width : 160,
            targetElem: options.target ? $(options.target) : false,
            separator: options.separator ? options.separator : '.',
            format: options.format ? options.format : false,
            language: options.language ? options.language : 'en',
            dayNames: options.dayNames ? options.dayNames : 'short',
            monthNames: options.monthNames ? options.monthNames : 'long',
            onChangeFunction: options.onChangeFunction ? options.onChangeFunction : false,
            postFunction: options.postFunction ? options.postFunction : false
        }, options || {});
        
        if (this.options.targetElem){
            // get indexes from default format - dd.mm.yyyy
            var dd_idx = 0;
            var mm_idx = 3;
            var yy_idx = 6;
            
            if (this.options.format){
                dd_idx = this.options.format.indexOf('dd');
                mm_idx = this.options.format.indexOf('mm');
                yy_idx = this.options.format.indexOf('yyyy');
            }
            var day = this.options.targetElem.value.substr(dd_idx, 2);
            var month = this.options.targetElem.value.substr(mm_idx, 2);
            var year = this.options.targetElem.value.substr(yy_idx, 4);
            
            if (year != '' && month != '' && day != '') 
                this.targetDate = {year: year, month: month, day: day};
        }
    },
        
    setForbiden: function(forbiden) {
        this.forbiden = forbiden || false;
    },
    
    setDate: function(year, month, day) {
        this.targetDate = {year: year, month: month, day: day};
    },
    
    getYear: function() {
        var year = null;
        if (this.caleYear)
            year = this.caleYear.value;
        else if (this.targetDate)
            year = this.targetDate.year;
        else
            year = this.today.getFullYear();
        return this.padZero(year);
    },
    
    getMonth: function() {
        var month = null;
        if (this.caleMonth)
            month = this.caleMonth.value;
        else if (this.targetDate)
            month = this.targetDate.month;
        else
            month = this.today.getMonth() + 1;
        return this.padZero(month);
    },
    
    display: function (obj) {
        var elmPos = false;
        
        if (obj){ // indicate popUp calendar
            this.calendar = this.iniLayer(this.id);
            elmPos = getPosition(obj);
            
            this.calendar.style.top  = elmPos.y + this.body.scrollTop + 'px';
            this.calendar.style.left = elmPos.x + this.body.scrollLeft + obj.offsetWidth + 2 + 'px';
            this.calendar.style.width = this.options.width + 'px';
            this.calendar.style.position = 'absolute';
            this.calendar.style.zIndex = 1000;

            this.dummyLayer = this.setDummyLayer();
            this.attachEvent(this.dummyLayer, 'click', this.closeCalendar, this);
            
            if (isIE) this.dummyFrame = this.iniIframe(this.calendar);
        
        } else if ($(this.id)){ // reference to the HTML object or to previosully generated object
            this.calendar = $(this.id);
            
        } else if (!this.calendar) return false;

        this.calendar.style.width = this.options.width + 'px';
        this.calendar.className = 'calendar';

        if (this.targetDate){
            this.makeCalendar(this.targetDate.year, this.targetDate.month, this.targetDate.day);
        } else {
            this.makeCalendar();
        }
    },
    
    makeCalendar: function (year, month, day) {
        year  = year || this.today.getFullYear();
        month = month || this.today.getMonth() + 1;
        
        var out = '';

        // calendar navigation (months, years, icons...)
        out += '<table border="0" cellPadding="0" cellSpacing="1" align="center">';
        out += '<tr>';
        out += '<td width="99%" align="center">';
        
        var listOfMonths = '<select id="' + this.id + 'Month" class="calendar_field">';
        for (var i=0; i<12; i++){
            listOfMonths += '<option value="' + (i + 1) + '"';
            if (i == (month - 1)) listOfMonths += "selected";
            listOfMonths += '>' + this.labels.months[i] + '</option>';
        }
        listOfMonths += '</select>';
        out += listOfMonths + '&nbsp;';
        
        out += '<input id="' + this.id + 'Year" value="' + year + '" maxlength="4" class="calendar_field" style="width: 36px" >';
        out += '</td>';
        if (this.dummyLayer){
            out += '<td valign="middle"><img src="images/icons/close.gif" id="' + this.id + 'Close" style="cursor: pointer" title="' + this.labels.closeCalendar + '" />';
            out += '</tr>';
        }
        out += '</table>';
        
        out += '<table border="0" cellPadding="1" cellSpacing="0">';
        out += '<tr>';
        out += '<td class="calendar_navi"><img src="images/icons/prev.gif" id="' + this.id + 'PrevYear" style="cursor: pointer;" title="' + this.labels.prevYear + '" /></td>';
        out += '<td class="calendar_navi"><img src="images/icons/left.gif" id="' + this.id + 'PrevMonth" style="cursor: pointer;" title="' + this.labels.prevMonth + '" /></td>';
        out += '<td class="calendar_navi" width="50%" align="center"><div id="' + this.id + 'Today" style="cursor: pointer;">' + this.labels.today + '</div></td>';
        out += '<td class="calendar_navi" width="30%" align="center"><img src="images/icons/delete.gif" id="' + this.id + 'Delete" style="cursor: pointer;" title="' + this.labels.deleteDate + '" /></td>';
        out += '<td class="calendar_navi"><img src="images/icons/right.gif" id="' + this.id + 'NextMonth" style="cursor: pointer;" title="' + this.labels.nextMonth + '" /></td>';
        out += '<td class="calendar_navi"><img src="images/icons/next.gif" id="' + this.id + 'NextYear" style="cursor: pointer;" title="' + this.labels.nextYear + '" /></td>';
        out += '</tr>';
        out += '</table>';
        
        var cale_navi = document.createElement('div');
        cale_navi.className = 'calendar_headline';
        cale_navi.innerHTML = out;
        cale_navi.style.textAlign = 'center';

        this.caleDays = document.createElement('div');
        this.caleDays.id = this.id + 'Days';

        this.calendar.appendChild(cale_navi);
        this.calendar.appendChild(this.caleDays);
        
        this.caleMonth = $(this.id + 'Month');
        this.caleYear  = $(this.id + 'Year');
        
        this.attachEvent(this.caleMonth, 'change', function(){this.changeMonth()}, this);
        this.attachEvent(this.caleYear, 'blur', function(event){this.changeYear(event, 0)}, this);
        this.attachEvent(this.caleYear, 'keyup', function(event){this.changeYear(event, 1)}, this);
        this.attachEvent($(this.id + 'Close'), 'click', function(){this.closeCalendar()}, this);
        
        this.attachEvent($(this.id + 'PrevYear'), 'click', function(){this.naviCalendar(-1, 0)}, this);
        this.attachEvent($(this.id + 'PrevMonth'), 'click', function(){this.naviCalendar(0, -1)}, this);
        this.attachEvent($(this.id + 'Today'), 'click', function(){this.setToday()}, this);
        this.attachEvent($(this.id + 'Delete'), 'click', function(){this.clearDate()}, this);
        this.attachEvent($(this.id + 'NextMonth'), 'click', function(){this.naviCalendar(0, 1)}, this);
        this.attachEvent($(this.id + 'NextYear'), 'click', function(){this.naviCalendar(1, 0)}, this);
        
        this.renderDaysOfMonth(year, month);
        
        if (this.dummyFrame) {
            this.dummyFrame.style.top = this.calendar.offsetTop + 'px';
            this.dummyFrame.style.left = this.calendar.offsetLeft + 'px';
            this.dummyFrame.style.width = this.calendar.offsetWidth;
            this.dummyFrame.style.height = this.calendar.offsetHeight;
            this.dummyFrame.style.display = "block";
            this.dummyFrame.style.zIndex = 900;
        }
    },
    
    renderDaysOfMonth: function(year, month) {
        var daysInMonth = this.getDaysInMonth(year, month);
        var currDay = new Date(year, month - 1, 1);
        var out = '';
        
        // calendar days...
        out += '<table width="100%" border="0" cellPadding="1" cellSpacing="0">';
        out += '<tr align="center">';

        var span  = '';
        var _span = '';
        
        for (var i=0; i<7; i++){
            if (i == 6){
                span  = '<span class="calendar_sunday">';
                _span = '</span>';
            }
            out += '<td class="calendar_head" width="14%">' + span + this.labels.days[i] + _span + '</td>';
        }
        out += '</tr>';
        out += '<tr>';
        
        var dayInWeek = currDay.getDay();
        if (dayInWeek == 0) dayInWeek = 7;
        
        // first, fill blank cells...
        for (var i=1; i<dayInWeek; i++)
            out += '<td align="center" class="calendar_day">&nbsp;</td>';

        _span = '</span>';
        var currPrefix = '';
  
        // then, fill days of the month...
        for (var i=1; i<=daysInMonth; i++){
            currDay.setDate(i);
            
            if (currDay.getDay() == 0){
                span  = '<span class="calendar_sunday">';
            } else {
                span  = '<span class="calendar_day">';
            }
            
            if (currDay.getFullYear() == this.today.getFullYear() && currDay.getMonth() == this.today.getMonth() && currDay.getDate() == this.today.getDate()){
                currPrefix = 'current_';
            } else {
                currPrefix = '';
            }
            
            var actionString = 'true';
            var mouseOver    = 'true';
            var classSfx     = 'out';
            
            if (this.forbiden){
                var frbDate = parseInt(currDay.getFullYear() + this.padZero(currDay.getMonth()+1) + this.padZero(currDay.getDate()));
                for (var j=0; j<this.forbiden.length; j++){
                    if (frbDate >= parseInt(this.forbiden[j].from) && frbDate <= parseInt(this.forbiden[j].to)){
                        actionString = '';
                        mouseOver    = '';
                        classSfx     = 'out_';
                    }
                }
                
            }
                    
            out += '<td id="' + this.id + 'Day_' + i + '" align="center" class="calendar_' + currPrefix + classSfx + '" actionString="' + actionString + '" mouseOver="' + mouseOver + '" currPrefix="' + currPrefix + '">' + span + i + _span + '</td>';
            
            if (currDay.getDay() == 0){
                out += '</tr><tr>';
            }
        }
        
        out += '</tr>';
        out += '</table>';
        
        this.caleDays.innerHTML = out;
        
        // attach day events...
        window.ref = this;
        
        for (var i=1; i<=daysInMonth; i++){
            var day = $(this.id + 'Day_' + i);
            if (day.getAttribute('actionString') != '') {
                eval("day.onclick = function(){window.ref.chooseDay(" + i + ")}");
            }
            if (day.getAttribute('mouseOver') != '') {
                var cssOver = day.getAttribute('currPrefix') + 'over';
                var cssOut  = day.getAttribute('currPrefix') + 'out';
                eval("day.onmouseover = function(){window.ref.mouseHandle(this,  '" + cssOver + "')}");
                eval("day.onmouseout  = function(){window.ref.mouseHandle(this,  '" + cssOut + "')}");
            }
        }
    },

    closeCalendar: function() {
        this.unsetDummyLayer();
        Element.remove(this.id);
        if (this.dummyFrame) Element.remove(this.dummyFrame);
        this.dummyLayer = false;
        this.dummyFrame = false;
    },

    chooseDay: function(day){
        var year  = this.caleYear.value;
        var month = this.caleMonth.value;
        var selDate = (this.options.format) ? this.formatDate(year, month, day) : this.makeDefaultDate(year, month, day);
        
        if (this.options.targetElem) this.options.targetElem.value = selDate;
        if (this.options.postFunction) this.options.postFunction();
        
        if (this.dummyLayer)
            this.closeCalendar();
    },
    
    changeYear: function(e, ind){
        var year  = parseInt(this.caleYear.value);
        var month = parseInt(this.caleMonth.value);
        var key = 0;
        
        if (this.options.onChangeFunction) this.options.onChangeFunction();
        
        if (e.keyCode) { key = e.keyCode; }
        
        if (ind == 0 || (ind == 1 && key == 13)) {
            if (year >= 1900 && year < 2100){
                this.renderDaysOfMonth(year, month);
            } else {
                this.caleYear.value = this.today.getFullYear();
            }
        }
    },
    
    changeMonth: function(){
        var year  = parseInt(this.caleYear.value);
        var month = parseInt(this.caleMonth.value);
        
        if (this.options.onChangeFunction) this.options.onChangeFunction();
        
        this.renderDaysOfMonth(year, month);
    },
    
    naviCalendar: function(yy, mm){
        var year  = parseInt(this.caleYear.value);
        var month = parseInt(this.caleMonth.value);
        
        if ((month == 1 && mm < 0 && year == 1900) || (month == 12 && mm > 0 && year == 2099) || (yy < 0 && year == 1900) || (yy > 0 && year == 2099)){
            return false;
        }

        if (month == 1 && mm < 0){
            month = 12;
            yy = -1;
        } else if (month == 12 && mm > 0){
            month = 1;
            yy = 1;
        } else if (mm != 0) {
            month += mm;
        }
        
        year += yy;
        
        this.caleYear.value = year;
        this.caleMonth.value = month;
        
        if (this.options.onChangeFunction) this.options.onChangeFunction();

        this.renderDaysOfMonth(year, month);
    },
    
    setToday: function(){
        var year  = this.today.getFullYear();
        var month = this.today.getMonth() + 1;
        var day   = this.today.getDate();
        var selDate = (this.options.format) ? this.formatDate(year, month, day) : this.makeDefaultDate(year, month, day);
        
        this.caleYear.value = year;
        this.caleMonth.value = month;
        
        if (this.options.onChangeFunction) this.options.onChangeFunction();
        
        this.renderDaysOfMonth(year, month);
        
        if (this.options.targetElem) this.options.targetElem.value = selDate;
        if (this.options.postFunction) this.options.postFunction();
        
    },
    
    clearDate: function(){
        if (this.options.targetElem)
            this.options.targetElem.value = '';
    },
    
    makeDefaultDate: function(year, month, day){        
        day   = this.padZero(day);
        month = this.padZero(month);
        
        return (day + this.options.separator + month + this.options.separator + year);
    },
    
    formatDate: function(year, month, day){
        day   = this.padZero(day);
        month = this.padZero(month);
        
        var date_ = this.options.format;
        date_ = date_.replace(/dd/g, day);
        date_ = date_.replace(/mm/g, month);
        date_ = date_.replace(/yyyy/g, year);
        
        return date_;
    },
    
    getDaysInMonth: function(year, month){      
        var daysInMonthArray = [31,28,31,30,31,30,31,31,30,31,30,31];
        var daysInMonth = daysInMonthArray[month-1];
        if (daysInMonth == 28){
            if (this.isLeapYear(year))daysInMonth = 29;
        }
        return daysInMonth/1;
    },
    
    isLeapYear: function(inputYear) {
        if (inputYear%400==0||(inputYear%4==0&&inputYear%100!=0)) return true;
        return false;       
    },
    
    padZero: function(x) {
        x = (x < 10) ? '0' + x : '' + x;
        return x;
    },
    
    mouseHandle: function (elm, pfx) {
        elm.className = 'calendar_' + pfx;
    }

});


/**
* ContextMenu class.
* @author Vladan Antic.
* @date 1.2007.
* @version 2.0.
* @note context menu are based on list of hidden fields which contains menu/items description
*/

DYNAX.ContextMenu = Class.create();
DYNAX.ContextMenu.prototype = Object.extend(new DYNAX.Base(), {

    initialize: function(e, elm, options, obj) {
        if (!elm) return false;
        
        this.cmEvent = e;
        this.cmItems = document.getElementsByName(elm); // get all items (hidden fields) of a context menu
        this.cmObject = obj;
        
        this.id = 'contextMenu';
        this.refToElement = false;
        
        options = options || new Array();
        this.setOptions(options);
        
        this.contextMenu();
    },
        
    setOptions: function(options) {
        this.options = Object.extend({
            width: options.width ? options.width : 160,
            closeEvent: options.closeEvent ? options.closeEvent : 'click',
            orientation: options.orientation ? options.orientation : 'down',
            className: options.className ? options.className : 'contextMenu'
        }, options || {});
    },
        
    contextMenu: function() {
        var pxCor  = isOpera ? 4 : 2;
        var top_c  = 0;
        var left_c = 0;
        
        if ($('contextMenu')) Element.remove('contextMenu');
            
        // make context menu if there are cmItems...
        if (this.cmItems.length > 0) {
            var cm_div = this.iniLayer(this.id);
            var cm_main = document.createElement('div');
            cm_main.className   = 'main';
            cm_main.style.width = this.options.width;
            
            for (i=0; i<this.cmItems.length; i++) {
                var div = document.createElement('div');
                cm_icon   = this.cmItems[i].getAttribute('icon');
                cm_text   = (this.cmItems[i].getAttribute('label')) ? this.cmItems[i].getAttribute('label') : "Context Menu";
                cm_action = this.cmItems[i].getAttribute('actions');
                cm_sep    = this.cmItems[i].getAttribute('sep');
                if (cm_action) {
                    div.className   = 'item';
                    div.setAttribute('onclick', cm_action, 0);
                    div.setAttribute('onmouseover', "this.className = 'over';", 0);
                    div.setAttribute('onmouseout', "this.className = 'item';", 0);
                    
                    ico = new Image(16, 16); 
                    if (cm_icon) {
                        ico.src   = this.iconPath + cm_icon;
                    } else {
                        ico.src   = this.iconPath + this.iconEmpty; 
                    }
                    ico.align = 'absmiddle';
                    div.appendChild(ico);
                } else {
                    div.className = 'text';
                }
                div.innerHTML += '&nbsp;' + cm_text;
                cm_main.appendChild(div);
                
                if (cm_sep) {
                    var sep = document.createElement('DIV');
                    sep.className = 'sep';
                    sep.innerHTML = '<img src="' + this.imagePath + this.image1 + '">';
                    cm_main.appendChild(sep);
                }
            }
            
            if (isIE) cm_main.innerHTML += this.elmIframe;
            cm_div.appendChild(cm_main);
            
            if (this.cmObject != null) {
                // get position of given element...
                var elmPos = getPosition(this.cmObject);
                if (this.options.orientation == 'down') { 
                    top_c  = elmPos.y + this.cmObject.offsetHeight + pxCor;
                    left_c = elmPos.x;
                } else {
                    top_c  = elmPos.y;
                    left_c = elmPos.x + this.cmObject.offsetWidth + 2;
                }
            } else {
                top_c  = Event.pointerY(this.cmEvent) - 2;
                left_c = Event.pointerX(this.cmEvent) - 2;
            }
            
            oX = left_c + cm_div.offsetWidth;
            oW = getWindowWidth();
            
            cm_div.style.padding  = '1px';
            cm_div.style.top  = top_c + this.body.scrollTop + 'px';
            cm_div.style.left = left_c + this.body.scrollLeft + 'px';
            
            // left this.options.orientation if cM is out of screen
            if (oX > oW)
                cm_div.style.left = left_c - (oX - oW) - 24 + 'px';
                
            cm_div.style.visibility = 'visible';
            
            var dmy = this.setDummyLayer();
            this.attachEvent(dmy, this.options.closeEvent, this.closeContextMenu, this);
            this.attachEvent(cm_div, 'mouseup', this.closeContextMenu, this);      
        }
    },
    
    closeContextMenu: function() {
        this.unsetDummyLayer();
        $('contextMenu').style.display = 'none';
    }
});


/**
* AjaxDataGrid class.
* @author Vladan Antic.
* @date Jan-Feb 2007.
* @version 1.0.
* @note AjaxDataGrid class is based on gridState variables instanced by using php class DataGrid; datagrid.inc.php is required.
* @version 1.1.
* @note this version creates header by using THEAD rows as template, grid rows by using TBODY row as template and, optional, page navigation.
* @version 1.2.
* @note supported array content into a cell of datagrid.
* @version 2.0.
* @note improved rendering of grid rows - included buffering, different attributes and inner content maintenance.
*       a field description MUST BE in format: (*field:name*) or (*:name*) or with attributes: (*:name|truncate:40|suffix:...|empty:"none"*)
* @version 2.1.
* @note made posibility to reload datagrid and switch to Base/Extedned mode preview.
*/

DYNAX.AjaxDataGrid = Class.create();
DYNAX.AjaxDataGrid.prototype = Object.extend(new DYNAX.Base(), {

    initialize: function(id, state, url, options) {
        this.id = id;
        this.state = state;
        this.ajaxUrl = url;
        
        this.grid = false;
        this.xml = null;
        this.iconSortAsc  = "sort_asc.gif";
        this.iconSortDesc = "sort_desc.gif";
        this.pageSizes = new Array(10, 20, 50, 100);
        this.z = 0; // zebra style indicator...
        this.fieldRegExp = /[(*][*)]/;
        this.head_rows_len = false;
        
        options = options || new Array();
        this.setOptions(options);
        
        // get extendedMode...
        if (this.options.extendedMode){
            this.cookieName = this.id + 'extendedMode';
            var cookieValue = this.getCookie(this.cookieName);
            this.extendedMode = (cookieValue && cookieValue == 'true') ? true : false;
        }

        this.setState('pagination', (this.options.pagination) ? 1 : 0);
        
        if (this.options.searchField){
            this.search = $(this.id + '_' + this.options.searchField);
            this.searchIcon = $(this.id + '_' + this.options.searchField + '_icon');
            this.attachEvent(this.search, 'keydown', function(e){this.searchData(e, 'K')}, this);
            this.attachEvent(this.searchIcon, 'click', function(e){this.searchData(e, 'M')}, this);
        }
        
        // initialize and create datagrid
        this.initDataGrid();
        this.createHeader();
        this.makeDataGrid();
        this.createNavigation();
    },
    
    initDataGrid: function() {
        // initialize grid, head and body properties...
        if (!this.grid){
            this.grid = $(this.id);
            this.grid.className = this.options.classGrid;
            this.grid.parentNode.className = this.options.classGrid + '_frame';
            this.grid.border = 0;
            this.grid.cellPadding = 0;
            this.grid.cellSpacing = 0;
        }

        // define thead and tbody elements
        this.thead      = this.grid.getElementsByTagName('thead')[0];   
        this.head_rows  = this.thead.getElementsByTagName('tr');
        if (!this.head_rows_len) this.head_rows_len = this.head_rows.length;
        
        this.tbody      = this.grid.getElementsByTagName('tbody')[0];   
        this.tbody.rows[0].style.display = 'none'; // 1st row is used as template - don't show it, just...
        // get cell attributes of a row
        this.item_props = this.tbody.rows[0].getElementsByTagName('td');
        this.row_template = this.getRowTemplate(this.tbody.rows[0]);
        
        // save extendedMode
        this.setCookie(this.cookieName, this.extendedMode, 100000);
    },
    
    setOptions: function(options) {
        this.options = Object.extend({
            keyField: options.keyField ? options.keyField : "",
            keyInd: options.keyInd ? options.keyInd : "###",
            searchField: options.searchField ? options.searchField : false,
            emptyContent: options.emptyContent ? options.emptyContent : "&nbsp;",
            rowHeight: options.rowHeight ? options.rowHeight : 20,
            headerHeight: options.headerHeight ? options.headerHeight : 22,
            showRowSelection: options.showRowSelection ? options.showRowSelection : false,
            showOrderNumber: options.showOrderNumber ? options.showOrderNumber : false,
            pagination: options.pagination ? options.pagination : true,
            classGrid: options.classGrid ? options.classGrid : "",
            classOver: options.classOver ? options.classOver : "",
            classEven: options.classEven ? options.classEven : "",
            postFunction: options.postFunction ? options.postFunction : false,
            extendedMode: options.extendedMode ? options.extendedMode : false,
            outVar: options.outVar ? options.outVar : false
        }, options || {});
        
        // make regular expression of keyField
        this.keyRegExp = new RegExp(this.options.keyInd, "g");
        
        // don't show the message...
        if ($(this.id + '_message')){
            this.message = $(this.id + '_message');
            this.message.style.display = 'none';
        }
    },
    
    getRowTemplate: function(row) {
        if (!row) return null;
        var cells = row.getElementsByTagName('td');
        if (!cells) return null;

        var count = 0;
        var row_template = new Array();
        
        for (var i=0; i<cells.length; i++){
            
            if (this.extendedMode || !cells[i].getAttribute('extendedMode')){
                // get xml tags used 4 advanced content in a cell: items, tables, etc...
                var xml_tags = cells[i].getElementsByTagName('xml');
                
                if (xml_tags.length == 0){ // there is only HTML content in a cell
                    var inner_xml_ = false;
                    
                    // get template content and attributes...
                    var inner_html_ = this.splitInnerHTML(cells[i].innerHTML);
                    
                } else { // there is only XML tags in a cell
                    var inner_html_ = false;
                    var inner_xml_ = new Array();
                    
                    // get template content and attributes for each XML tag..
                    for (var j=0; j<xml_tags.length; j++){
                        var xml_inner_html_ = this.splitInnerHTML(xml_tags[j].innerHTML);
                        
                        inner_xml_[j] = {
                            foreach: xml_tags[j].getAttribute('foreach'),
                            from: xml_tags[j].getAttribute('from'),
                            innerHTML_: xml_inner_html_
                        };
                    }
                }
    
                row_template[count++] = {
                    width: cells[i].getAttribute('width'),
                    height: cells[i].getAttribute('height'),
                    align: cells[i].getAttribute('align'),
                    valign: cells[i].getAttribute('valign'),
                    className: cells[i].getAttribute('class'),
                    innerHTML_: inner_html_,
                    innerXML_: inner_xml_
                };
            }
        }
        cells = null;
        return row_template;
    },
    
    createHeader: function() {
        var head_props = Array();
        var indShowOrderNumber = false;
        var indShowRowSelection = false;
        var grid_width = 0;
        
        // !!! don't clear template rows
        while (this.thead.rows.length > this.head_rows_len){
            this.thead.rows[this.thead.rows.length - 1].parentNode.removeChild(this.thead.rows[this.thead.rows.length - 1]);    
        }

        // scan all thead rows used as templates...
        for (n=0; n<this.head_rows_len; n++){
            head_props[n] = this.head_rows[n].getElementsByTagName("td");
            this.head_rows[n].style.display = 'none';
        }

        // ...and create real header items
        for (n=0; n<this.head_rows_len; n++){
            var row          = this.thead.insertRow(-1);
            row.style.width  = '100%';
            row.style.height = this.options.headerHeight + 'px';
            
            if (this.options.showOrderNumber){
                if (!indShowOrderNumber){
                    var cell = row.insertCell(-1);
                    cell.style.textAlign = 'center';
                    cell.rowSpan   = this.head_rows_len;
                    if (this.options.outVar){
                        var cell_cont = '<img src="' + this.iconPath + 'grid_settings.gif" title="Datagrid Settings" class="icon" onclick="new DYNAX.ContextMenu(event, \'' + this.id + 'CM\', {orientation: \'right\'}, this)" />';
                        cell_cont += "<input type=\"hidden\" name=\"" + this.id + "CM\" label=\"Reload\" icon=\"refresh.gif\" actions=\"" + this.options.outVar + ".makeDataGrid()\" sep=\"1\"/>";
                        cell_cont += "<input type=\"hidden\" name=\"" + this.id + "CM\" label=\"Base Mode\" icon=\"";
                        cell_cont += this.extendedMode ? "empty.gif" : "checked.gif";
                        cell_cont += "\" actions=\"" + this.options.outVar + ".extendedMode = false; " + this.options.outVar + ".initDataGrid(); " + this.options.outVar + ".createHeader(); " + this.options.outVar + ".makeDataGrid()\" />";
                        
                        if (this.options.extendedMode) {
                            cell_cont += "<input type=\"hidden\" name=\"" + this.id + "CM\" label=\"Extended Mode\" icon=\"";
                            cell_cont += this.extendedMode ? "checked.gif" : "empty.gif";
                            cell_cont += "\" actions=\"" + this.options.outVar + ".extendedMode = true; " + this.options.outVar + ".initDataGrid(); " + this.options.outVar + ".createHeader(); " + this.options.outVar + ".makeDataGrid()\" />";
                        }
                    } else {
                        cell_cont = '#';
                    }
                    cell.innerHTML = cell_cont;
                    indShowOrderNumber = true;
                }
            }
            if (this.options.showRowSelection){
                if (!indShowRowSelection){
                    var cell = row.insertCell(-1);
                    cell.rowSpan   = this.head_rows_len;
                    cell.innerHTML = "<img id=\""+this.id+"_selectAll\" src=\""+this.iconPath+"select_all.gif\" class=\"icon\" title=\"Select Grid Rows\" border=\"0\" align=\"absmiddle\" /><img id=\""+this.id+"_deselectAll\" src=\""+this.iconPath+"deselect_all.gif\" class=\"icon\" title=\"Deselect Grid Rows\" border=\"0\" align=\"absmiddle\" />";
                    indShowRowSelection = true;
                }
            }
            
            for (i=0; i<head_props[n].length; i++){
                
                if (this.extendedMode || !head_props[n][i].getAttribute('extendedMode')){
                    var cell = document.createElement('td');
                    cell.style.textAlign = head_props[n][i].getAttribute('align');
                    cell.colSpan   = head_props[n][i].getAttribute('colSpan');
                    cell.rowSpan   = head_props[n][i].getAttribute('rowSpan');
                    cell.noWrap    = (head_props[n][i].getAttribute('nowrap') != null) ? true : false;
                    if (head_props[n][i].getAttribute('height')) cell.style.height = head_props[n][i].getAttribute('height') + 'px';
                    if (head_props[n][i].getAttribute('width')){
                        cell.style.width = head_props[n][i].getAttribute('width') + 'px';
                        grid_width += (n == 0) ? parseInt(head_props[n][i].getAttribute('width')) : 0;
                    }
                    cell.innerHTML = head_props[n][i].innerHTML;
                    
                    var sort_exp = head_props[n][i].getAttribute('sortExpression');
                    
                    if (sort_exp){
                        cell.id = this.id + "_col_" + sort_exp;
                        eval("var f = function() {this.sortDataGrid('" + sort_exp + "', '" + this.getState('sort_ord') + "')}");
                        this.attachEvent(cell, 'click', f, this);
                        
                        eval("var f = function(e) {this.handleOver('" + cell.id + "', '" + this.options.classGrid + '_head_over' + "')}");
                        this.attachEvent(cell, 'mouseover', f, this);
                        eval("var f = function(e) {this.handleOver('" + cell.id + "', null)}");
                        this.attachEvent(cell, 'mouseout', f, this);
                        
                        var sort_ico  = "<img src=\""+this.iconPath;
                        sort_ico += (this.getState('sort_ord') == 'asc') ? this.iconSortDesc : this.iconSortAsc;
                        sort_ico += "\" align=\"absmiddle\" ";
                        sort_ico += (sort_exp == this.getState('sort')) ? "/>" : "style=\"visibility: hidden;\" />";
                        cell.innerHTML += sort_ico;
                    }
                    
                    row.appendChild(cell);
                }
            }
        }
        // actions to (de)select grid rows...
        if (this.options.showRowSelection){
            this.attachEvent($(this.id + '_selectAll'), 'click', function(){this.selectGridRows(1)}, this);
            this.attachEvent($(this.id + '_deselectAll'), 'click', function(){this.selectGridRows(0)}, this);
        }
                
        this.grid.style.width = grid_width + 'px';
    },
    
    createNavigation: function() {
        if (!this.getState('pagination')) return false;
        
        // render datagrid navigation...
        var grid_navi = document.createElement('table');
        grid_navi.id = this.id + '_navigation';
        grid_navi.border = 0;
        grid_navi.cellPadding = 1;
        grid_navi.cellSpacing = 0;

        var row = grid_navi.insertRow(-1);
        
        // page sizes...
        var cell = row.insertCell(-1);
        cell.className = this.options.classGrid;
        cell.style.padding = '0 20 0 5';
        var page_sizes = "<select id=\""+this.id+"_page_size\" class=\"field\" style=\"width: 50px\">\n";
        for (i=0; i<this.pageSizes.length; i++){
            page_sizes += "<option value=\""+this.pageSizes[i]+"\"";
            page_sizes += (this.pageSizes[i] == this.getState('page_size')) ? " selected>" : ">";
            page_sizes += this.pageSizes[i]+"</option>\n";
        }
        cell.innerHTML = "Rows: " + page_sizes;
        
        // 1st and previous page icons...
        var cell = row.insertCell(-1);
        if (isMoz) cell.style.padding = '0 0 2 0';
        cell.innerHTML = "<img id=\""+this.id+"_frst_page\" src=\""+this.iconPath+"first.gif\" class=\"icon\" align=\"absmiddle\" title=\"First page\">&nbsp;<img id=\""+this.id+"_prev_page\" src=\""+this.iconPath+"prev.gif\" class=\"icon\" align=\"absmiddle\" title=\"Previous page\">";

        // go to page field...
        var cell = row.insertCell(-1);
        cell.className = this.options.classGrid;
        cell.style.padding = '0 15 0 15';
        cell.innerHTML = "Page: <input id=\""+this.id+"_curr_page\" type=\"text\" class=\"field\" value="+this.getState('curr_page')+" style=\"width: 40px;\"> of <span id=\""+this.id+"_totl_page\">"+this.getState('last_page')+"</span>&nbsp;<img id=\""+this.id+"_goto_page\" src=\""+this.iconPath+"go.gif\" class=\"icon\" align=\"absmiddle\" title=\"Go to page\">";

        // next and last page icons...
        var cell = row.insertCell(-1);
        if (isMoz) cell.style.padding = '0 0 2 0';
        cell.innerHTML = "<img id=\""+this.id+"_next_page\" src=\""+this.iconPath+"next.gif\" class=\"icon\" align=\"absmiddle\" title=\"Next page\">&nbsp;<img id=\""+this.id+"_last_page\" src=\""+this.iconPath+"last.gif\" class=\"icon\" align=\"absmiddle\" title=\"Last page\">";

        this.grid.parentNode.appendChild(grid_navi);
        
        // define page navi elements as global - needed to set after rows rendering
        this.pageSize = $(this.id + '_page_size');
        this.frstPage = $(this.id + '_frst_page');
        this.prevPage = $(this.id + '_prev_page');
        this.nextPage = $(this.id + '_next_page');
        this.lastPage = $(this.id + '_last_page');
        this.totlPage = $(this.id + '_totl_page');
        this.gotoPage = $(this.id + '_goto_page');
        this.currPage = $(this.id + '_curr_page');
    },
    
    makeDataGrid: function() {
        // set zebra style here - each page in the same style beginning from the 1st row...
        if (this.options.classEven != "") this.z = 1;

        var prms = this.options.parameters;
        prms += '&grid_id=' + this.id;
        prms += '&pagination=' + this.getState('pagination');
        prms += '&page_size=' + this.getState('page_size');
        prms += '&curr_page=' + this.getState('curr_page');
        prms += '&last_page=' + this.getState('last_page');
        prms += '&search=' + this.getState('search');
        prms += '&sort=' + this.getState('sort');
        prms += '&sort_ord=' + this.getState('sort_ord');

        // get ajax request...
        var ajax = new Ajax.Request(
            this.ajaxUrl, {
                method: 'post', 
                parameters: prms,
                onComplete: this.setResult.bind(this)
            });
    },
    
    setResult: function(request) {
        // grab xml of options
        this.xml = request.responseXML;
        var respNode = this.xml.getElementsByTagName("response")[0];
        var items = respNode.getElementsByTagName("item");
        
        this.clearDataRows();
        
        if (items.length < 1){
            this.grid.style.display = 'none';
            if ($(this.id + '_navigation')) $(this.id + '_navigation').style.display = 'none';
            if (this.message) this.message.style.display = 'block';
            return false;
        } else {
            this.grid.style.display = 'block';
            if ($(this.id + '_navigation')) $(this.id + '_navigation').style.display = 'block';
            if (this.message) this.message.style.display = 'none';
        }
        
        // fill data rows...
        for (var i=0; i<items.length; i++) {
            this.fillDataRow(items[i]);
        }
        
        // update actions of the page navigation with a new values
        var curr_page = Number(respNode.getElementsByTagName("curr_page")[0].firstChild.nodeValue);
        var last_page = Number(respNode.getElementsByTagName("last_page")[0].firstChild.nodeValue);
        prev_page = (curr_page > 1) ? curr_page - 1 : 1;
        next_page = (curr_page < last_page) ? curr_page + 1 : last_page;
        
        this.currPage.value = curr_page;
        this.totlPage.innerHTML = last_page;
        
        this.attachEvent(this.pageSize, 'change', function(){this.pageNavi(1, this.pageSize.options[this.pageSize.selectedIndex].value)}, this);
        this.attachEvent(this.frstPage, 'click', function(){this.pageNavi(1)}, this);
        this.attachEvent(this.prevPage, 'click', function(){this.pageNavi(prev_page)}, this);
        this.attachEvent(this.nextPage, 'click', function(){this.pageNavi(next_page)}, this);
        this.attachEvent(this.lastPage, 'click', function(){this.pageNavi(last_page)}, this);
        this.attachEvent(this.gotoPage, 'click', function(){this.pageNavi()}, this);
        this.attachEvent(this.currPage, 'keydown', this.keyNavi, this);
        
        if (this.options.postFunction)
            this.options.postFunction();
    },
    
    clearDataRows: function() {
        // !!! don't clear the 1st row - it is used as template row
        while (this.tbody.rows.length > 1){
            this.tbody.rows[this.tbody.rows.length - 1].parentNode.removeChild(this.tbody.rows[this.tbody.rows.length - 1]);    
        }
    },
    
    fillDataRow: function(item) {
        var row = this.tbody.insertRow(-1);
        this.z *= -1;
        
        // set row styles...
        row.style.height = this.options.rowHeight;
        row.classOver    = this.options.classOver;
        row.classEven    = this.options.classEven;
        row.zebra        = this.z;
        row.onmouseover  = this.mouseOver;
        row.onmouseout   = this.mouseOut;
        row.className    = this.z > 0 ? this.options.classEven : null;
        
        // fill cells with order number and/or checkBoxes...
        if (this.options.showOrderNumber){
            var cell = row.insertCell(-1);
            cell.className = this.options.classGrid + '_column';
            cell.style.textAlign = 'right';
            cell.innerHTML = item.getElementsByTagName('nr')[0].firstChild.nodeValue + '.';
        }
        if (this.options.showRowSelection){
            var cell = row.insertCell(-1);
            cell.className = this.options.classGrid + '_column';
            cell.style.textAlign = 'center';
            cell.innerHTML = "<input type=\"checkbox\" name=\"" + this.id + "_row[" + item.getElementsByTagName(this.options.keyField)[0].firstChild.nodeValue + "]\">";
        }
        
        // fill cells defined in row template...
        for (var i=0; i<this.row_template.length; i++) {

            // make a real content by using row template...
            if (this.row_template[i].innerHTML_){
                var in_cell = this.makeInnerHTML(this.row_template[i].innerHTML_, item, item.getElementsByTagName(this.options.keyField)[0].firstChild.nodeValue);
                
            // make a content by getting XML array...
            } else if (this.row_template[i].innerXML_){
                var inner_xml_ = this.row_template[i].innerXML_;
                var in_cell    = "";
                
                for (var j=0; j<inner_xml_.length; j++){
                    
                    if (inner_xml_[j].foreach){
                        var xml_items = item.getElementsByTagName(inner_xml_[j].from)[0].getElementsByTagName(inner_xml_[j].from+'item');

                        // get a content for each XML node...
                        for (var n=0; n<xml_items.length; n++){
                            in_cell += this.makeInnerHTML(inner_xml_[j].innerHTML_, xml_items[n], item.getElementsByTagName(this.options.keyField)[0].firstChild.nodeValue);
                        }
                    } else {
                        in_cell += this.makeInnerHTML(inner_xml_[j].innerHTML_, item, item.getElementsByTagName(this.options.keyField)[0].firstChild.nodeValue);
                    }
                }
            }
            
            // create a new cell and styles of its...
            var cell = row.insertCell(-1);
            cell.style.width = this.row_template[i]['width'];
            cell.style.height = this.row_template[i]['height'];
            cell.style.textAlign = this.row_template[i]['align'];
            cell.style.verticalAlign = this.row_template[i]['valign'];
            cell.className = this.row_template[i]['className'];
            cell.innerHTML = (in_cell.length == 0) ? "&nbsp;" : in_cell;
        }
    },
    
    splitInnerHTML: function(inner_html) {
        if (!inner_html) return null;
        var inner_html_ = inner_html.split(this.fieldRegExp);

        // create a field mask (field name, truncate size, suffix, empty/default content, ...) for each "field" set...
        for (var i=0; i<inner_html_.length; i++){
            
            if (inner_html_[i].indexOf(':') == 0){
                var field_mask = new Array();
                var field_ = inner_html_[i].split('|');
                
                for (var n=0; n<field_.length; n++){
                    var tmp_arr = field_[n].split(':');
                    var sign    = isString(tmp_arr[1]) ? '"' : '';
                    if (tmp_arr[0] == '') tmp_arr[0] = 'field';
                    if (!tmp_arr[1]) tmp_arr[1] = true;
                    var fm_string = "field_mask." + tmp_arr[0] + " = " + sign + tmp_arr[1] + sign;
                    eval(fm_string.replace(/""/g, '"'));
                }
                inner_html_[i] = field_mask;
            }
        }
        return inner_html_;
    },
    
    makeInnerHTML: function(inner_html_, item, key_field) {
        if (!inner_html_ || !item) return null;
        var inner_html = "";

        for (var i=0; i<inner_html_.length; i++){
            
            // dataField replacement...
            if (isArray(inner_html_[i])){
                var cont = "";
                if (inner_html_[i].field && item.getElementsByTagName(inner_html_[i].field)[0]) cont = item.getElementsByTagName(inner_html_[i].field)[0].firstChild.nodeValue;
                if (trimString(cont) == ""){
                    cont = (inner_html_[i].empty) ? inner_html_[i].empty : this.options.emptyContent;
                } else {
                    if (inner_html_[i].truncate) cont = truncateString(cont, parseInt(inner_html_[i].truncate), inner_html_[i].suffix);
                }
                if (inner_html_[i].encode) cont = encodeHtml(cont);
                
                inner_html += cont;
            
            // keyField replacement...
            } else {
                inner_html += inner_html_[i].replace(this.keyRegExp, key_field);
            }
        }

        return inner_html;
    },

    sortDataGrid: function(sort, sort_ord) {
        var buf_sort = this.getState('sort');
        var buf_sort_ord = this.getState('sort_ord');
        
        if (sort != buf_sort){
            var cur_ico = $(this.id + "_col_" + buf_sort).getElementsByTagName("img")[0];
            cur_ico.style.visibility = 'hidden';
            sort_ord = 'desc';
        }
        
        var sort_elm = $(this.id + "_col_" + sort);
        var ico = sort_elm.getElementsByTagName("img")[0];
        var sort_ico = this.iconPath;
        sort_ico += (sort_ord == 'asc') ? this.iconSortAsc : this.iconSortDesc; 
        ico.src   = sort_ico; 
        ico.style.visibility = 'visible';
        
        sort_ord = (sort_ord == 'asc') ? 'desc' : 'asc';
        eval("var f = function() {this.sortDataGrid('" + sort + "', '" + sort_ord + "')}");
        this.attachEvent(sort_elm, 'click', f, this);
        
        this.setState('curr_page', 1);
        this.setState('sort', sort);
        this.setState('sort_ord', sort_ord);
        
        this.makeDataGrid();
    },
    
    pageNavi: function(curr_page, page_size) {
        curr_page = curr_page || this.currPage.value;
        this.setState('curr_page', curr_page);
        if (page_size) this.setState('page_size', page_size);
        
        this.makeDataGrid();
    },

    searchData: function(e, tpe) {
        if (tpe == 'M'){
            this.setState('curr_page', 1);
            this.setState('search', encodeEscChr(this.search.value));
            this.makeDataGrid();
        } else {
            var key = 0;
            if (e.keyCode) { key = e.keyCode; }
            else if (typeof(e.which) != 'undefined') { key = e.which; }
    
            // enter
            if (key == 13) {
                this.setState('curr_page', 1);
                this.setState('search', encodeEscChr(this.search.value));
                this.makeDataGrid();
                return false;
            }
        }
    },

    keyNavi: function(e) {
        var key = 0;
        if (e.keyCode) { key = e.keyCode; }
        else if (typeof(e.which) != 'undefined') { key = e.which; }

        // enter
        if (key == 13) {
            this.pageNavi($F(this.currPage));
        }
    },
    
    setState: function(nme, val, mke) {
        mke = mke || false;
        this.state[nme] = val;
        if (mke) { this.makeDataGrid() };
    },
    
    getState: function(nme) {
        return this.state[nme];
    },
    
    mouseOver: function() {
        this.className = this.classOver;
    },
    
    mouseOut: function() {
        this.className = this.zebra > 0 ? this.classEven : null;
    },
    
    selectGridRows: function(ind) {
        if (this.options.showRowSelection){
            this.tbody      = this.grid.getElementsByTagName('tbody')[0];   
            var elms = this.tbody.getElementsByTagName('input');
            var row_pfx = this.id + '_row';
            
            for(var i=0; i<elms.length; i++) {
                elm = elms[i];
                if (elm.type == "checkbox" && elm.name != null && elm.name.indexOf(row_pfx) >= 0){
                    elm.checked = (ind == 1) ? true : false;
                }
            }
        }
    }
    
});


/**
* DialogBox class.
* @author Vladan Antic.
* @date 1.2007.
* @version 1.1.
* @note 
*/

DYNAX.DialogBox = Class.create();
DYNAX.DialogBox.prototype = Object.extend(new DYNAX.Base(), {

    initialize: function(title, options) {

        ++DYNAX_dBoxIndex;
        this.title    = title || '';
        this.name     = 'dialogBox';
        this.id       = this.name + DYNAX_dBoxIndex;
        this.buttons  = Array();
        
        options = options || new Array();
        this.setOptions(options);
    },

    setOptions: function(options) {
        this.options = Object.extend({
            saveState: options.saveState ? options.saveState : true,
            blurScreen: options.blurScreen ? options.blurScreen : false,
            draggable: options.draggable ? options.draggable : false,
            minimize: options.minimize ? options.minimize : false,
            className: options.className ? options.className : 'dialogBox',
            left: options.left ? options.left : null,
            top: options.top ? options.top : null,
            width: options.width ? options.width : null,
            height: options.height ? options.height : null
        }, options || {});
    },
    
    addButton: function(lbl, act, wd) {
        wd = wd || 65;
        this.buttons[this.buttons.length] = '<input type="button" class="buttons" value="' + lbl + '" onclick="' + act + '" style="width:' + wd + 'px;" />';
    },
  
    display: function(content) {
        content = content || '';
        
        // create dialogBox layer...
        window.ref2this = this;
        var dBox = this.iniLayer(this.id);
        dBox.index = this.index;
        dBox.className = this.options.className;
        dBox.onmousedown = function(){ window.ref2this.setActive(this) };

        var out = '';
        out += '<table id="' + this.id + 'Table" width="120" border="0" cellPadding="2" cellSpacing="1">';
        out += '<tr>';
        out += '<td id="' + this.id + 'Head" height="19" class="head" nowrap>';
        out += '<div id="' + this.id + 'Title" class="title"></div>';
        out += '<div class="icons">';
        if (this.options.minimize)
            out += '<img id="' + this.id + 'Minimize" src="' + this.iconPath + 'minimize.gif" style="padding-right: 2px; cursor: pointer;">';
        out += '<img id="' + this.id + 'Close" src="' + this.iconPath + 'close.gif" style="cursor: pointer;">';
        out += '</td>';
        out += '</tr>';
        out += '<tr>';
        out += '<td height="1" align="left" valign="top" class="main">';
        out += '<div id="' + this.id + 'Main"></div>';
        out += '<div id="' + this.id + 'Buttons" align="right" style="padding-top: 5px;"></div>';
        out += '</td>';
        out += '</tr>';
        out += '</table>';
        if (isIE) out += this.elmIframe;
        
        dBox.innerHTML = out;
        
        // attach actions to icons...
        if ($(this.id + 'Minimize')) this.attachEvent($(this.id + 'Minimize'), 'click', function(){this.minimizeBox()}, this);
        this.attachEvent($(this.id + 'Close'), 'click', function(){this.closeBox()}, this);

        // set dragging...
        if (this.options.draggable){
            var dBoxHead = $(this.id + 'Head');
            dBoxHead.style.padding = '0 2 0 0';
            dBoxHead.style.cursor = 'move';
            this.attachEvent(dBoxHead, 'mousedown', function(event){this.handleMouseDown(event, this.id)}, this);
            this.attachEvent(dBoxHead, 'mouseup', function(){this.setState(this.id)}, this);
        }

        // fill dialogBox with a real content...
        $(this.id + 'Title').innerHTML = this.title;
        $(this.id + 'Main').innerHTML = content;
        
        var btns = '';
        for (i=0; i<this.buttons.length; i++)
            btns += this.buttons[i];
        $(this.id + 'Buttons').innerHTML = btns;
        
        var d_wd  = this.options.width || getElementWidth(this.id);
        var d_hi  = this.options.height || Element.getHeight(this.id);
        var y_new = Math.round(getWindowHeight()/2 + getWindowYOffset() - d_hi/2 - 30);
        if (y_new < 0) y_new = 1;
        
        // save state of the panel...
        if (this.options.saveState){
            var state = '';
            var cookieName = 'cookie_' + this.id;
            var cookieValue = this.getCookie(cookieName);
            if (cookieValue) state = cookieValue.split(';');
            this.options.top  = state[0] || this.options.top;
            this.options.left = state[1] || this.options.left;
        }

        $(this.id).style.left = (this.options.left || (getWindowWidth()/2 - d_wd/2)) + 'px';
        $(this.id).style.top  = (this.options.top || y_new) + 'px';
        $(this.id).style.visibility = 'visible';
        $(this.id + 'Table').style.width = d_wd + 'px';
        
        // set the box as active...
        this.setActive(dBox);
        
        // if dummyLayer...
        if (this.options.blurScreen){
            DYNAX_dummyInd++;
            this.setDummyLayer(this.options.blurScreen);
        }
    },
  
    setActive: function(obj) {
        var idx = obj.id.replace(/[^0-9]/g, '');
        if (DYNAX_dBoxActive){
            var i = DYNAX_dBoxActive.id.replace(/[^0-9]/g, '');
            if ($(this.name + i)) {
                $(this.name + i + 'Head').className = "head_";
                $(this.name + i).style.zIndex    = "100";
            }
        }
        if ($(this.name + idx)) {
            $(this.name + idx + 'Head').className = "head";
            $(this.name + idx).style.zIndex    = "101";
        }
        
        DYNAX_dBoxActive = obj;
    },
    
    minimizeBox: function() {
        iObj = $(this.id + 'Minimize');
        if (iObj.src.indexOf('minimize') >= 0) {
            $(this.id + 'Main').style.display = "none";
            $(this.id + 'Buttons').style.display = "none";
            iObj.src = iObj.src.replace('minimize','maximize'); 
        } else {            
            $(this.id + 'Main').style.display = "block";
            $(this.id + 'Buttons').style.display = "block";
            iObj.src = iObj.src.replace('maximize','minimize'); 
        }
    },
    
    closeBox: function() {
        Element.remove(this.id);
        if (--DYNAX_dummyInd < 1) this.unsetDummyLayer();
    },
    
    setState: function() {
        var top  = $(this.id).offsetTop;
        var left = $(this.id).offsetLeft;
        if (this.options.saveState) this.setCookie('cookie_' + this.id, top + ';' + left, 100000);
    }
});

/**
* DynamicList class.
* @author Vladan Antic.
* @date 1.2007.
* @version 1.1.
* @note
*/

DYNAX.DynamicList = Class.create();
DYNAX.DynamicList.prototype = Object.extend(new DYNAX.Base(), {

    initialize: function(url, options) {
        this.ajaxUrl = url;
        this.xml = null;
        
        this.id      = 'dynamicList';
        this.idItem  = 'dlOption';
        this.currentIndex = 0;
        this.listLength   = 0;
        this.suggestList  = new Array();
        this.currentLetters = new Array();
        
        this.setOptions(options);
        
        this.dynList = this.iniLayer(this.id);
        if (isIE) this.iniIframe($(this.id));
        
        this.dynList.className = this.options.className;
        this.hidePopup();

        this.options.sourceElem.setAttribute("autocomplete", "off");
        this.attachEvent(this.options.sourceElem, this.options.eventField, this.makeList, this);
        this.attachEvent(this.options.sourceElem, this.options.eventPopup, this.keyNavi, this);
        this.attachEvent(this.options.sourceElem, 'blur', this.emptyField, this);
    },
    
    setOptions: function(options) {
        this.options = Object.extend({
            sourceElem: $(options.source),
            targetElem: options.target ? $(options.target) : false,
            eventField: options.eventField ? options.eventField : 'keyup',
            className: options.className ? options.className : 'dynamicList',
            eventPopup: 'keydown',
            appendSeparator: options.appendSeparator || '#',
            appendValue: evalBoolean(options.appendValue),
            fillSource: options.fillSource ? options.fillSource : 'selection',
            minChars: options.minChars ? options.minChars : 1,
            maxItems: options.maxItems ? options.maxItems : 0,
            maxHeight: options.maxHeight ? options.maxHeight : 198
        }, options || {});
        
        this.cssOption = 'option';
        this.cssOver   = 'over';
    },
    
    makeList: function(e) {
        var key = 0;
        if (e.keyCode) { key = e.keyCode; }
        else if (typeof(e.which)!= 'undefined') { key = e.which; }

        var fieldLength = $F(this.options.sourceElem).length;

        if (fieldLength == 0 || fieldLength < this.options.minChars){
            this.dynList.innerHTML = '';
            this.hidePopup();
            statusMessage();
                        
        } else if (key != 38 && key != 40 && key != 13 && key != 9 && key != 27 && key != 37 && key != 39 && key != 17 && key != 18) {
            this.setProgressStyle();
            
            var prms = arrayToParameterString(this.buildParameterString(this.options.parameters).split(','));
            if (this.options.maxItems > 0) prms += '&maxItems=' + this.options.maxItems;
            prms += '&utfDecode=no';
            
            // get ajax request...
            var ajax = new Ajax.Request(
                this.ajaxUrl, {
                    method: 'post', 
                    parameters: prms,
                    onComplete: this.setResult.bind(this)
                });
        }
    },
    
    setResult: function(request) {
        this.xml = request.responseXML;
        this.dynList.innerHTML = '';
        this.hidePopup();

        this.listLength   = 0;
        this.currentIndex = 0;
        
        // grab xml of options...
        var respNode = this.xml.getElementsByTagName("response")[0];
        var items = respNode.getElementsByTagName("item");
        
        for (var i=0; i<items.length; i++) {
            var div = document.createElement("div");
            div.id = this.idItem + i;
            div.index = i;
            div.className = this.cssOption;
            div.onmouseover = this.handleOver.bindAsEventListener(this);
            div.onclick = this.handleClick.bindAsEventListener(this);
            if (this.options.targetElem)
                div.value = items[i].getElementsByTagName("value")[0].firstChild.nodeValue;
            div.innerHTML = items[i].getElementsByTagName("name")[0].firstChild.nodeValue;
            this.dynList.appendChild(div);
            
            // if number of max items is defined...
            if (this.options.maxItems > 0 && (i + 1) >= this.options.maxItems){
                i++;
                var div = document.createElement("div");
                div.className = this.cssOption;
                div.innerHTML = "-- more...";
                this.dynList.appendChild(div);
                break;
            }
        }
        
        this.listLength = i;
        
        if (this.listLength > 0){
            $(this.idItem + this.currentIndex).className = this.cssOver;
            Element.show(this.id);
            this.setPopupStyles();
        }
        
        statusMessage(respNode.getElementsByTagName("status")[0].firstChild.nodeValue);
    },
    
    keyNavi: function(e) {
        var key = 0;
        if (e.keyCode) { key = e.keyCode; }
        else if (typeof(e.which) != 'undefined') { key = e.which; }

        //up arrow
        if (key == 38) {
            if (this.currentIndex > 0) {
                $(this.idItem + this.currentIndex).className = this.cssOption;
                this.currentIndex--;
                $(this.idItem + this.currentIndex).className = this.cssOver        
                $(this.idItem + this.currentIndex).scrollIntoView(false);
            }
        
        //down arrow
        } else if (key == 40) {
            if (this.currentIndex < this.listLength - 1) {
                $(this.idItem + this.currentIndex).className = this.cssOption;
                this.currentIndex++;
                $(this.idItem + this.currentIndex).className = this.cssOver        
                $(this.idItem + this.currentIndex).scrollIntoView(false);
            }
        
        //enter
        } else if (key == 13 && this.dynList.style.display != 'none') {
            this.fillField($(this.idItem + this.currentIndex));
            Event.stop(e);
            this.executePostFunction();
            
        //tab
        } else if (key == 9) {
            this.hidePopup();
            
        //escape
        } else if (key == 27) {
            this.hidePopup();
            Event.stop(e);
        }
    },
    
    executePostFunction: function() {
        if (this.options.postFunction) {
            this.options.postFunction(this.xml);
        }
    },
    
    hidePopup: function() {
        this.resetProgressStyle();
        if ($(this.id)) {
            this.detachEvent(document.documentElement, 'click');
            Element.hide(this.id);
        }
        if (isIE && $('dummyFrame')) $('dummyFrame').style.display = "none";
    },
    
    setProgressStyle: function() {
        if (this.options.progressStyle != null) {
          Element.addClassName(this.options.sourceElem, this.options.progressStyle);
        }
    },
    
    resetProgressStyle: function() {
        if (this.options.progressStyle != null) {
          Element.removeClassName(this.options.sourceElem, this.options.progressStyle);
        }
    },
    
    fillField: function(selection) {
        if (this.options.fillSource == "selection") this.options.sourceElem.value = decodeHtml(selection.innerHTML);
        if (this.options.targetElem) {
            // fill source with target value (id, ...) to make a search...
            if (this.options.fillSource == "target") this.options.sourceElem.value = selection.value;
            if (this.options.appendValue == "false") {
                this.options.targetElem.value = selection.value;
            } else {
                if (this.options.targetElem.value.length > 0)
                    this.options.targetElem.value += this.options.appendSeparator;
                this.options.targetElem.value += selection.value;
            }
        }
        this.hidePopup();
    },
    
    emptyField: function() {
        if (this.options.sourceElem.value == "" || this.listLength < 1) {
            if (this.options.targetElem) this.options.targetElem.value = "";
            statusMessage();
        }
    },
    
    handleClick: function(e) {
        this.fillField(Event.element(e));
        this.executePostFunction();
    },
    
    handleOver: function(e) {
        $(this.idItem + this.currentIndex).className = this.cssOption;
        this.currentIndex = Event.element(e).index;
        $(this.idItem + this.currentIndex).className = this.cssOver;
    },
    
    setPopupStyles: function() {
        var elmPos = getPosition(this.options.sourceElem);
        var pxTop   = isOpera ? 5 : 0;
        var pxLeft  = isOpera ? 3 : isIE ? 1 : 0;
        
        if (this.dynList.offsetHeight < this.options.maxHeight) {
            this.dynList.style.overflow = 'hidden';
        } else if (isMoz) {
            this.dynList.style.maxHeight = this.options.maxHeight + 'px';
            this.dynList.style.overflow = '-moz-scrollbars-vertical';
        } else {
            this.dynList.style.height = this.options.maxHeight + 'px';
            if (isOpera) {
                this.dynList.style.overflow = 'auto';
            } else {
                this.dynList.style.overflowY = 'auto';
            }
        }
        
        this.dynList.scrollTop = 0;
        this.dynList.style.top = (elmPos.y + this.options.sourceElem.offsetHeight + pxTop + this.body.scrollTop) + "px";
        this.dynList.style.left = elmPos.x + pxLeft + this.body.scrollLeft + "px";
        
        if (isIE) {
            this.dynList.style.width = this.options.sourceElem.offsetWidth + "px";
        } else {
            this.dynList.style.minWidth = this.options.sourceElem.offsetWidth + "px";
        }
        
        if (isIE) {
            dmyF = $('dummyFrame');
            dmyF.style.top = (elmPos.y + this.options.sourceElem.offsetHeight) + "px";
            dmyF.style.left = elmPos.x + "px";
            dmyF.style.width = this.dynList.offsetWidth;
            dmyF.style.height = this.dynList.offsetHeight;
            dmyF.style.display = "block";
            dmyF.style.zIndex = 90;
        }
        this.attachEvent(document.documentElement, 'click', this.hidePopup, this);
    }
});

/**
* InfoPanel class.
* @author Vladan Antic.
* @date 1.2007.
* @version 1.0.
* @note 
*/

DYNAX.InfoPanel = Class.create();
DYNAX.InfoPanel.prototype = Object.extend(new DYNAX.Base(), {

    initialize: function(id, options) {
        this.id = id;
        this.iconUp   = "up.gif";
        this.iconDown = "down.gif";

        this.infoPanels  = new Array();
        this.cookieNames = new Array();
        this.currExpandedPanel = false;
        this.expandedPanel = false;
        
        this.setOptions(options);
        
        $(this.id).style.width = this.options.panelWidth + 'px';
//        if (this.options.panelHeight) $(this.id).style.height = this.options.panelHeight + 'px';
    },
    
    setOptions: function(options) {
        this.options = Object.extend({
            panelWidth: options.panelWidth ? options.panelWidth : 200,
//            panelHeight: options.panelHeight ? options.panelHeight : 0,
            onlyOnePanel: options.onlyOnePanel ? options.onlyOnePanel : false,
            saveState: options.saveState ? options.saveState : true,
            classPanel: options.classPanel ? options.classPanel : 'infoPanel'
        }, options || {});
    },
    
    
    addPanel: function(id, state, width){
        var i = this.infoPanels.length;
        this.infoPanels[i] = [id, state, width];
    },

    infoPanel: function(){
        // get all panels...
        for(var no=0; no<this.infoPanels.length; no++){
            var panelId    = this.infoPanels[no][0];
            var panelState = this.infoPanels[no][1];
            var panelWidth = this.infoPanels[no][2];
            
            var tmpDiv     = $(panelId);
            var panelTitle = $(panelId).getAttribute("panelTitle"); 
            var content    = tmpDiv.innerHTML;
            tmpDiv.className  = this.options.classPanel;
            tmpDiv.innerHTML  = "";
            if (panelWidth) tmpDiv.style.width = panelWidth;
            
            // create content of a panel...
            var contDiv = document.createElement('DIV');
            contDiv.id  = this.id + 'Content' + no;
            contDiv.className = 'content';
            contDiv.innerHTML = content;

            // create topBar of a panel...
            var topBar = document.createElement('DIV');
            topBar.id  = this.id + 'TopBar' + no;
            topBar.className = "topBar";
            topBar.style.position = 'relative';
            window.ref2Panel = this;
            topBar.onclick = function(){ window.ref2Panel.showHideContent(this) };

            var span = document.createElement('SPAN');              
            span.innerHTML = panelTitle;
            topBar.appendChild(span);
            
            var img = document.createElement('IMG');
            img.id = this.id + 'Icon' + no;
            
            // save state of the panel...
            if (this.options.saveState){
                var cookieName = 'cookie_' + panelId;
                var cookieValue = this.getCookie(cookieName);
                if (cookieValue) panelState = (cookieValue == 1) ? true : false;
                this.cookieNames[this.cookieNames.length] = cookieName;
            }
            if (this.options.onlyOnePanel && this.currExpandedPanel) panelState = false;
            
            // show/hide panel initially...
            if (panelState){
                this.currExpandedPanel = topBar;
                contDiv.style.display = 'block';
                img.src = this.iconPath + this.iconUp;
            } else {
                contDiv.style.display = 'none';
                img.src = this.iconPath + this.iconDown;
            }
            topBar.appendChild(img);
            
            tmpDiv.appendChild(topBar);
            tmpDiv.appendChild(contDiv);
        }
    },
    
    showHideContent: function(iObj){
        var img = iObj.getElementsByTagName('IMG')[0];
        var numericId = img.id.replace(/[^0-9]/g, '');
        var obj = document.getElementById(this.id + 'Content' + numericId);
        var state = '';
        
        if (img.src.toLowerCase().indexOf('up') >= 0){ // hide content...
            this.currExpandedPanel = false;
            img.src = img.src.replace('up','down');
            obj.style.display = 'none';
            state = '0';
        } else { // show content...
            if (iObj){
                if (this.currExpandedPanel && this.options.onlyOnePanel) this.showHideContent(this.currExpandedPanel);
                this.currExpandedPanel = iObj;  
            }
            img.src = img.src.replace('down','up');
            obj.style.display = 'block';
            state = '1';
        }   
        if (this.cookieNames[numericId]) this.setCookie(this.cookieNames[numericId], state, 100000);

        return true;    
    }
});


/**
* MessageBox class.
* @author Vladan Antic.
* @date 2.2007.
* @version 1.1.
* @note messageBox will display a message in alert, error, info or warning style
*       this tool is based on DYNAX.DialogBox class
*/

DYNAX.MessageBox = Class.create();
DYNAX.MessageBox.prototype = Object.extend(new DYNAX.Base(), {

    initialize: function(message, type, options) {
        message = message || '';
        type = type || 'A';
        
        this.dbox = false;
        
        options = options || new Array();
        this.setOptions(options);

        var title  = '';
        var icon = '';
        var style = '';
        
        switch (type) {
        case 'E': 
            title  = 'Error';
            icon = 'message_error.gif';
            style = 'style="color: #dd1100;"';
            break; 
        case 'I': 
            title  = 'Information';
            icon = 'message_info.gif';
            break; 
        case 'W': 
            title  = 'Warning';
            icon = 'message_warning.gif';
            break;
        default : 
            title  = 'Alert';
            icon = 'message_alert.gif';
            break; 
        }
        
        if (options.title != '') title = options.title;
        
        var out = '';
        out += '<table width="' + this.options.width + '" border="0" cellPadding="0" cellSpacing="0">';
        out += '<td height="70" align="left"><div id="messageBoxText"' + style + '>' + message + '</div>';
        out += '<div id="messageBoxIcon"><img src="' + this.imagePath + icon + '" border="0"></div>';
        out += '</td>';
        out += '</tr>';
        out += '<tr>';
        out += '<td align="center"><input type="button" id="messageButton" class="button"  onmouseover="setStyle(this, \'button_over\');" onmouseout="setStyle(this, \'button\');" value="OK"></td>';
        out += '</tr>';
        out += '</table>';

        if (title != '') title = 'Alert';
        
        this.dbox = new DYNAX.DialogBox(title, this.options);
        this.dbox.display(out);
        
        this.attachEvent($('messageButton'), 'click', this.closeMessage, this);
    },
        
    setOptions: function(options) {
        this.options = Object.extend({
            left: options.left ? options.left : null,
            top: options.top ? options.top : null,
            width: options.width ? options.width : 400,
            height: options.height ? options.height : null
        }, options || {});
    },
    
    closeMessage: function(){
        if (this.dbox)
            this.dbox.closeBox()    
    }

});
