// debug
function _printObject(obj) {var str = ''; for (var i in obj) str += i + ':' + obj[i] + ' '; alert(str)}

function Capicity(amount) {
    this.getCapicity = function() {return amount}
}

function InputDescriptor(did, iid, type) {
    this.getDId = function() {return did}
    this.getIId = function() {return iid}
    this.getType = function() {return type}
}

function html_decode(s) {
    // used to decode symbols like &auml; in filling of selects
    var span = document.createElement('SPAN');
    span.innerHTML = s;
    return span.innerHTML;  

}
function html_encode(s) {
    // used to encode symbols like &auml; in picking data from inputs
    var chars = ['&auml;','&Auml;', '&Ouml;', '&ouml;', '&Ouml;', '&Uuml;', '&uuml;', '&szlig;'];
    var charsTo = ['%26auml;','%26Auml;', '%26Ouml;', '%26ouml;', '%26Ouml;', '%26Uuml;', '%26uuml;', '%26szlig;'];
    var result = s.replace(/&/g,"%26");
    for (var i= 0;i <chars.length; i++)
    {
        result = result.replace(new RegExp(html_decode(chars[i]),'g'),charsTo[i]);
    }
    return result;

}
function text_line_breack(s, size) {
    // breack in some lines long strings
    var chars = ['.'];
    var result = '';
    var i = 0;
    var sub = ' ';
    var find = false;
    while (i <= s.length)
    {
        find = false
        sub = s.substr(i, size);
        if ((i + size) < s.length)
        {
            if (sub.lastIndexOf(' ') != -1)
            {
                sub = s.substr(i, sub.lastIndexOf(' '));
                i = i + sub.lastIndexOf(' ') + 1;
            }
            else
            {
                for (var j= 0;j <chars.length; j++)
                {
                    if (sub.lastIndexOf(chars[j]) != -1)
                    {
                        find = true;
                        sub = sub.substr(0, sub.lastIndexOf(chars[j]) + 1);
                        i = i + sub.lastIndexOf(chars[j]) + 1;
                        sub =sub + ' ';
                        break;
                    }
                }
                sub += ' ';
                if (!find) i = i+ size;
            }
        }
        else
        {
            i = s.length + 1;
        }
        result += sub;

    }
    return result;

}
function FormController(inputDescriptors) {

    var processUpdate;
    var processClear;

    // public functions

    this.onUpdateInputs = false;

    this.updateInputs = function(data) {
        if (!data) return;
        if (!inputDescriptors) return;
        for (var i in inputDescriptors) {
            var ind = inputDescriptors[i];
            var value = data[ind.getDId()] || data.attributes[ind.getDId()];
            if (value) {
                processUpdate(ind.getType(), ind.getIId(), value);
            }
        }
        if (this.onUpdateInputs) this.onUpdateInputs(data);
    }

    this.onClearInputs = false;

    this.clearInputs = function() {
        if (!inputDescriptors) return;
        for (var i in inputDescriptors) {
            var ind = inputDescriptors[i];
            processClear(ind.getType(), ind.getIId());
        }
        if (this.onClearInputs) this.onClearInputs();
    }

    // private functions

    var processUpdateInput = function(iId, dataValue) {
        var inputElement = document.getElementById(iId);
        if (inputElement) inputElement.value = html_decode(dataValue);
    }

    var processUpdateElement = function(iId, dataValue) {
        var element = document.getElementById(iId);
        if (element) element.innerHTML = dataValue;
    }

    var processUpdateSelect = function(iId, selectItems) {
        var selectElement = document.getElementById(iId);
        if (selectElement && selectElement.options) {
            selectElement.options.length = 0;
            for (var i in selectItems) {
                if (selectItems[i].selected) {
                    selectElement.options[selectElement.options.length] = new Option(html_decode(selectItems[i].label), selectItems[i].value, null, true);
                } else {
                    selectElement.options[selectElement.options.length] = new Option(html_decode(selectItems[i].label), selectItems[i].value);
                }
            }
        }
    }

    processUpdate = function(type, iId, dataValue) {
        if (type == 'input') {
            processUpdateInput(iId, dataValue);
        } else if (type == 'select') {
            processUpdateSelect(iId, dataValue);
        } else if (type == 'element') {
            processUpdateElement(iId, dataValue);
        }
    }

    var processClearInput = function(iId) {
        var inputElement = document.getElementById(iId);
        if (inputElement) inputElement.value = '';
    }

    var processClearElement = function(iId) {
        var element = document.getElementById(iId);
        if (element) element.innerHTML = '';
    }

    var processClearSelect = function(iId) {
        var selectElement = document.getElementById(iId);
        if (selectElement) {
            var s = selectElement.options[0];
            if (s) selectElement.value = s.value;
        }
    }

    processClear = function (type, iId) {
        if (type == 'input') {
            processClearInput(iId);
        } else if (type == 'select') {
            processClearSelect(iId);
        } else if (type == 'element') {
            processClearElement(iId);
        }
    }

}

function InputDescriptor2(dataId, input, inputId, type, paramName, sendEmpty, onSendParam) {
    this.dataId = dataId;
    this.input = input;
    this.inputId = inputId;
    this.type = type;
    this.paramName = paramName;
    this.sendEmpty = sendEmpty;
    this.onSendParam = onSendParam; // should be a function(value) that return value as string 
}

function FormController2(descriptors) {

    var _ind = descriptors;
    if (!_ind) _ind = [];

    // public functions

    this.onUpdateInputs = false;

    this.onClearInputs = false;

    this.setDescriptors = function(descriptors) {
        _ind = descriptors;
        if (!_ind) _ind = [];
    }

    this.getDescriptors = function() {
        return _ind;
    }

    this.addDescriptor = function(descriptor) {
        if (!_ind) _ind = [];
        _ind.push(descriptor);
    }

    this.updateInputs = function(data) {
        if (!data) return;
        for (var i = 0; i < _ind.length; i++) {
            var ind = _ind[i];
            var value = data[ind.dataId] || (data.attributes && data.attributes[ind.dataId]);
            if (typeof value != 'undefined') {
                var input = ind.input;
                if (!input) input = document.getElementById(ind.inputId);
                if (input) {
                    if (ind.type == 'input') input.value = html_decode(value);
                    else if (ind.type == 'element') input.innerHTML = value;
                    else if (ind.type == 'checkbox') input.checked = value;
                    else if (ind.type == 'select') {
                        if (input.options) {
                            while(input.options.length > 0) input.remove(0);
                            for (var j in value) {
                                if (value[j].selected) input.options[input.options.length] = new Option(html_decode(value[j].label), value[j].value, null, true);
                                else input.options[input.options.length] = new Option(html_decode(value[j].label), value[j].value);
                            }
                        }
                    } else if (ind.type == 'pagination') {if (input.setKeys) input.setKeys(value)}
                }
            }
        }
        if (this.onUpdateInputs) this.onUpdateInputs(data);
    }

    this.clearInputs = function() {
        for (var i = 0; i < _ind.length; i++) {
            var ind = _ind[i];
            var input = ind.input;
            if (!input) input = document.getElementById(ind.inputId);
            if (input) {
                if (ind.type == 'input') input.value = '';
                else if (ind.type == 'element') input.innerHTML = '';
                else if (ind.type == 'select') {if (input.options) input.selectedIndex = 0}
                else if (ind.type == 'checkbox') input.checked = false;
                else if (ind.type == 'pagination') {if (input.setKeys) input.setKeys([])}
            }
        }
        if (this.onClearInputs) this.onClearInputs();
    }

    this.getParameters = function() {
        var params = '';
        for (var i = 0; i < _ind.length; i++) {
            var ind = _ind[i];
            var sendEmpty = typeof ind.sendEmpty != 'undefined' ? ind.sendEmpty : false;
            if (!ind.paramName) continue;
            var input = ind.input;
            if (!input) input = document.getElementById(ind.inputId);
            if (input) {
                var value = '';
                if (ind.type == 'input') value = html_encode(input.value);
                else if (ind.type == 'element') value = html_encode(input.innerHTML);
                else if (ind.type == 'select') {if (input.options) value = input.value}
                else if (ind.type == 'checkbox') value = input.checked;
                else if (ind.type == 'pagination') {if (input.getKeys) {value = input.getKeys()}}
                if (!value && !sendEmpty) continue;
                if (params) params += '&'
                params += ind.paramName + '=' + (ind.onSendParam ? ind.onSendParam(value) : value);
            }
        }
        return params;
    }

}

function Pagination(pageSize) {

    var _keys = false;
    var _currPage = 1;
    var getPagesCount;
    var getItemsCount;
    var isPreviousEnabled;
    var isNextEnabled;
    var getPageKeys;

    // public functions

    this.onUpdatePage = false;

    this.setKeys = function (keys) {
        _keys = keys;
        if (this.onUpdatePage) this.onUpdatePage(getPageKeys(), _currPage, getPagesCount(), getItemsCount(), isPreviousEnabled(), isNextEnabled());
    }

    this.getKeys = function() {
        return _keys;
    }

    this.nextPage = function() {
        if (_currPage + 1 > getPagesCount()) return;
        _currPage++;
        if (this.onUpdatePage) this.onUpdatePage(getPageKeys(), _currPage, getPagesCount(), getItemsCount(), isPreviousEnabled(), isNextEnabled());
    }

    this.previousPage = function() {
        if (_currPage - 2 < 0) return;
        _currPage--;
        if (this.onUpdatePage) this.onUpdatePage(getPageKeys(), _currPage, getPagesCount(), getItemsCount(), isPreviousEnabled(), isNextEnabled());
    }

    this.setPage = function(page) {
        _currPage = page;
        if (_currPage - 1 < 0 || _currPage > getPagesCount()) {
            _currPage = 1;
        }
    }

    // private functions

    getPagesCount = function() {
        return Math.max(Math.ceil(_keys.length / pageSize), 1);
    }

    getPageKeys = function() {
        if (!_keys) return new Array();
        if (_currPage - 1 < 0 || _currPage > getPagesCount()) {
            _currPage = 1;
        }
        var startIndex = (_currPage - 1) * pageSize;
        var endIndex = _currPage * pageSize - 1;
        if (endIndex > _keys.length - 1) {
            endIndex = _keys.length - 1;
        }
        var pageKeys = new Array();
        for (var i = 0; i < endIndex - startIndex + 1; i++) {
            pageKeys[pageKeys.length] = _keys[startIndex + i];
        }
        return pageKeys;
    }

    getItemsCount = function() {
        return (_keys) ? _keys.length : 0;
    }

    isPreviousEnabled = function() {
        return (_currPage > 1);
    }

    isNextEnabled = function() {
        return (_currPage < getPagesCount());
    }

}

function Mutex(timeout) {

    var locked = null;

    this.isLocked = function() {
        if (!locked) return false;
        if (new Date().getTime() - locked < timeout) return true;
        locked = null;
        return true;
    }

    this.lock = function() {
        locked = new Date().getTime();
    }

    this.unlock = function() {
        locked = null;
    }
    
}


var global_date_format = 'ISO'; // 'OLD_GERMAN', 'USA'
function formatDate(date) {
    var year = date.getFullYear();
    var month = date.getMonth() + 1;
    var day = date.getDate();
    var date_format = global_date_format ? global_date_format : 'ISO';
    if (date_format == 'ISO') return '' + year + '-' + (month < 10 ? '0' + month : month) + '-' + (day < 10 ? '0' + day : day);
    if (date_format == 'OLD_GERMAN') return '' + (day < 10 ? '0' + day : day) + '.' + (month < 10 ? '0' + month : month) + '.' + year;
    if (date_format == 'USA') return '' + (month < 10 ? '0' + month : month) + '/' + (day < 10 ? '0' + day : day) + '/' + year;
    return date.toDateString();
}
function parseDate(datestr) {
    var date_format = global_date_format ? global_date_format : 'ISO';
    if (date_format == 'ISO')
    {
       var year = datestr.substring(0,4);
       year = year * 1;
       var month = datestr.substring(5,7);
       month = month * 1 - 1;
       var day = datestr.substring(8,10);
       day = day * 1;
       var date = new Date();
       date.setFullYear(year);
       date.setMonth(month);
       date.setDate(day);
       return date;
    }
    if (date_format == 'OLD_GERMAN')
    {
       var year = datestr.substring(6,10);
       year = year * 1;
       var month = datestr.substring(3,5);
       month = month * 1 - 1;
       var day = datestr.substring(0,2);
       day = day * 1;
       var date = new Date();
       date.setFullYear(year);
       date.setMonth(month);
       date.setDate(day);
       return date;
    }
    if (date_format == 'USA')
    {
       var year = datestr.substring(6,10);
       year = year * 1;
       var month = datestr.substring(0,2);
       month = month * 1 - 1;
       var day = datestr.substring(3,5);
       day = day * 1;
       var date = new Date();
       date.setFullYear(year);
       date.setMonth(month);
       date.setDate(day);
       return date;
    }
    return Date.parse(datestr);
}

function populateParams(src, params) {
    var patterns = new Array(/\#\{1\}/,/\#\{2\}/,/\#\{3\}/,/\#\{4\}/,/\#\{5\}/,/\#\{6\}/,/\#\{7\}/,/\#\{8\}/,/\#\{9\}/);
    for (var i = 0; i < params.length; i++) {
        var pattern = patterns[i] || '';
        src = src.replace(pattern, params[i]);
    }
    return src;
}

function DHTMLHelper() {
    this.getOffset = function(element) {
        var valueT = 0, valueL = 0;
        do {
          valueT += element.offsetTop  || 0;
          valueL += element.offsetLeft || 0;
          element = element.offsetParent;
        } while (element);
        return [valueL, valueT];
    }
    this.setStyle = function(element, style) {
        for (var name in style) {
            var value = style[name];
            if (name == 'float' || name == 'cssFloat') name = (typeof element.style.styleFloat != 'undefined') ? 'styleFloat' : 'cssFloat';
            element.style[name] = value;
        }
    }
    this.getStyle = function(element, name) {
        return element.style[name];
    }
    this.setAttribute = function(element, attribute) {
        for (var name in attribute) element[name] = attribute[name];
    }
    this.getAttribute = function(element, name) {
        return element[name];
    }
    this.createElement = function(name, attribute, style) {
        var element = document.createElement(name);
        if (attribute) this.setAttribute(element, attribute);
        if (style) this.setStyle(element, style);
        return element;
    }

     this.createRadioInput  =  function(name, attribute, style){
          var element = false;
          try {
                 element = document.createElement("<input name='"+name+"' type='radio' />");
               } catch (e) {
                   element = document.createElement("input");
                   element.setAttribute("name", name);
                   element.setAttribute("type", "radio");
               }
          finally{
              if (attribute) this.setAttribute(element, attribute);
              if (style) this.setStyle(element, style);

          }
            return element;
        }

}
var _DH = new DHTMLHelper();

function DHTMLCommonComponents() {
    this.createShadowBorder = function(styleClass, borderStyle, content) {
        var table = _DH.createElement('table', {className:styleClass,cellPadding:0,cellSpacing:0}, null);
        if (borderStyle) _DH.setStyle(table, borderStyle);
        var tbody = _DH.createElement('tbody', null, null);
        var rt1 = _DH.createElement('tr', null, null);
        rt1.appendChild(_DH.createElement('td', {className:'lt'}, null));
        rt1.appendChild(_DH.createElement('td', {className:'t'}, null));
        rt1.appendChild(_DH.createElement('td', {className:'rt'}, null));
        var rt2 = _DH.createElement('tr', null, null);
        rt2.appendChild(_DH.createElement('td', {className:'lm'}, null));
        var td = _DH.createElement('td', {className:'m'}, null);
        if (content) td.appendChild(content);
        rt2.appendChild(td);
        rt2.appendChild(_DH.createElement('td', {className:'rm'}, null));
        var rt3 = _DH.createElement('tr', null, null);
        rt3.appendChild(_DH.createElement('td', {className:'lb'}, null));
        rt3.appendChild(_DH.createElement('td', {className:'b'}, null));
        rt3.appendChild(_DH.createElement('td', {className:'rb'}, null));
        tbody.appendChild(rt1);
        tbody.appendChild(rt2);
        tbody.appendChild(rt3);
        table.appendChild(tbody);
        return table;
    }

    this.createButton2 = function(borderStyleClass, borderStyle, onclick, title, titleStyleClass, titleStyle, iconImage, iconImageStyleClass, iconImageStyle) {
        var table = _DH.createElement('table', {cellPadding:1,cellSpacing:0,width:'100%'}, null);
        if (titleStyleClass) _DH.setAttribute(table, {className:titleStyleClass});
        if (titleStyle) _DH.setStyle(table, titleStyle);
        if (onclick) {
            _DH.setAttribute(table, {onclick:onclick});
            _DH.setStyle(table, {cursor:'pointer'});
        }
        var tbody = _DH.createElement('tbody', null, null);
        var tr = _DH.createElement('tr', null, null);
        if (iconImage) {
            var td1 = _DH.createElement('td', null, null);
            var img = _DH.createElement('img', {src:iconImage}, null);
            if (iconImageStyleClass) _DH.setAttribute(img, {className:iconImageStyleClass});
            if (iconImageStyle) _DH.setStyle(img, iconImageStyle);
            td1.appendChild(img);
            tr.appendChild(td1);
        }
        var td2 = _DH.createElement('td', {width:'90%'}, {textAlign:'center'});
        if (title) td2.innerHTML = title;
        tr.appendChild(td2);
        tbody.appendChild(tr)
        table.appendChild(tbody);
        return this.createShadowBorder(borderStyleClass, borderStyle, table);
    }


    this.createButton = function(styleClass, style, onclick, title, titleStyleClass, titleStyle, iconImage, iconImageStyleClass, iconImageStyle) {
        var div = document.createElement('div');
        div.style.clear = 'both';
        var content = '';
        content += '<table cellpadding="0" cellspacing="0" ';
        if (styleClass) content += 'class="' + styleClass + '" ';
        if (style) content += 'style="' + style + '" ';
        content += '>';
        content += '<tr><td class="lt"></td><td class="t"></td><td class="rt"></td></tr>';
        content += '<tr><td class="lm"></td><td ';
        if (onclick) content += 'onclick="' + onclick + '" style="cursor:pointer;"';
        content += '>';
        content += '<table cellpadding="0" cellspacing="1" width="100%" ';
        if (titleStyleClass) content += 'class="' + titleStyleClass + '" ';
        if (titleStyle) content += 'style="' + titleStyle + '" ';
        content += '>';
        content += '<tr>';
        if (iconImage) {
            content += '<td><img src="' + iconImage + '" ';
            if (iconImageStyleClass) content += 'class="' + iconImageStyleClass + '" ';
            if (iconImageStyle) content += 'style="' + iconImageStyle + '" ';
            content += '/></td>';
        }
        content += '<td width="90%" align="center">' + (title ? title : '') + '</td></tr></table>';
        content += '</td><td class="rm"></td></tr><tr><td class="lb"></td><td class="b"></td><td class="rb"></td></tr></table>';
        div.innerHTML = content;
        return div;
    }
    this.createDialogFrame = function(styleCalss, width, height, title, titleStyleClass, iconImage, iconImageStyleClass, content) {
        var root = _DH.createElement('div');
        if (styleCalss) _DH.setAttribute(root, {className:styleCalss});
        if (width) _DH.setStyle(root, {width:width});
        if (height) _DH.setStyle(root, {height:height});
        var _close = function() {_DH.setStyle(root, {display:'none'})}
        var _onmousedown = function(event) {
            if (!event) event = window.event;
            _dhtml_frame_dx = event.clientX - parseInt(root.style.left);
            _dhtml_frame_dy = event.clientY - parseInt(root.style.top);
            _dhtml_frame_old_onmousemove = document.onmousemove;
            document.onmousemove = function(event) {
                if (!event) event = window.event;
                var x = event.clientX - _dhtml_frame_dx;
                var y = event.clientY - _dhtml_frame_dy;
                _DH.setStyle(root, {left:x+'px',top:y+'px'});
                return false;
             }
        }
        var _onmouseup = function(event) {document.onmousemove = _dhtml_frame_old_onmousemove;}
        root.appendChild(_DH.createElement('div', {onmousedown:_onmousedown, onmouseup:_onmouseup}, {height:'10px', fontSize:0}));
        var titleBar = _DH.createElement('div', {onmousedown:_onmousedown, onmouseup:_onmouseup}, {clear:'both', height:'16px'});
        if (titleStyleClass) _DH.setAttribute(titleBar, {className:titleStyleClass});
        var col1 = _DH.createElement('span', null, {cssFloat:'left', styleFloat:'left', marginLeft:'6px'});
        if (title) col1.innerHTML = title;
        titleBar.appendChild(col1);
        if (iconImage) {
            var col2 = _DH.createElement('span', null, {cssFloat:'right',styleFloat:'right',width:'16px'});
            var img = _DH.createElement('img', {src:iconImage,onclick:_close}, {cursor:'pointer'});
            if (iconImageStyleClass) _DH.setAttribute({className:iconImageStyleClass});
            col2.appendChild(img);
            titleBar.appendChild(col2);
        }
        root.appendChild(titleBar);
        var c = _DH.createElement('div', null, {clear:'both'});
        if (content) c.appendChild(content);
        root.appendChild(c);
        return root;
    }

    this.createSimpleFrame = function(styleCalss, width, height, content) {
        var root = _DH.createElement('div');
        if (styleCalss) _DH.setAttribute(root, {className:styleCalss});
        if (width) _DH.setStyle(root, {width:width});
        if (height) _DH.setStyle(root, {height:height});
         /*
        var _close = function() {_DH.setStyle(root, {display:'none'})}

        var _onmousedown = function(event) {
            if (!event) event = window.event;
            _dhtml_frame_dx = event.clientX - parseInt(root.style.left);
            _dhtml_frame_dy = event.clientY - parseInt(root.style.top);
            _dhtml_frame_old_onmousemove = document.onmousemove;
            document.onmousemove = function(event) {
                if (!event) event = window.event;
                var x = event.clientX - _dhtml_frame_dx;
                var y = event.clientY - _dhtml_frame_dy;
                _DH.setStyle(root, {left:x+'px',top:y+'px'});
                return false;
             }
        }
        var _onmouseup = function(event) {document.onmousemove = _dhtml_frame_old_onmousemove;}
        root.appendChild(_DH.createElement('div', {onmousedown:_onmousedown, onmouseup:_onmouseup}, {height:'10px', fontSize:0}));
        var titleBar = _DH.createElement('div', {onmousedown:_onmousedown, onmouseup:_onmouseup}, {clear:'both', height:'16px'});
        if (titleStyleClass) _DH.setAttribute(titleBar, {className:titleStyleClass});
        var col1 = _DH.createElement('span', null, {cssFloat:'left', styleFloat:'left', marginLeft:'6px'});
        if (title) col1.innerHTML = title;
        titleBar.appendChild(col1);
        if (iconImage) {
            var col2 = _DH.createElement('span', null, {cssFloat:'right',styleFloat:'right',width:'16px'});
            var img = _DH.createElement('img', {src:iconImage,onclick:_close}, {cursor:'pointer'});
            if (iconImageStyleClass) _DH.setAttribute({className:iconImageStyleClass});
            col2.appendChild(img);
            titleBar.appendChild(col2);
        }
        root.appendChild(titleBar);  */
        var c = _DH.createElement('div', null, {clear:'both'});
        if (content) c.appendChild(content);
        root.appendChild(c);
        return root;
    }

    /*
     * DHTML block component
     *
     * coniguration object:
     * {
     *    opened: block initial state [true (default) / false]
     *    title: 'the block title'
     *    openImgSrc: 'open button image src'
     *    closeImgSrc: 'close button image src'
     *    blockAttr: {... block attributes ...}
     *    blockStyle: {... block styles ...}
     *    titleRowAttr: {... title row attributes ...}
     *    titleRowStyle: {... title row styles ...}
     *    titleAttr: {... title attributes ...}
     *    titleStyle: {... title styles ...}
     *    imgAttr: {... title image attributes ...}
     *    imgStyles: {... title image styles ...}
     * }
     *
     * function open() - open block
     *
     * function close() - close block
     *
     * function createComponent(content) - returns DHTML block with cpecified content
     */
    this.createBlock = function(cfg) {
        var _block; var _img; var _content; var _close; var _open;
        if (!cfg) cfg = {};
        if (!cfg.openImgSrc) cfg.openImgSrc = '';
        if (!cfg.closeImgSrc) cfg.closeImgSrc = '';
        if (cfg.opened == undefined) cfg.opened = true;
        _open = function() {
            if (_img) _DH.setAttribute(_img, {src: cfg.closeImgSrc, onclick: _close});
            if (_content) _DH.setStyle(_content, {display:'block'})
        }
        _close = function() {
            if (_img) _DH.setAttribute(_img, {src: cfg.openImgSrc, onclick: _open});
            if (_content) _DH.setStyle(_content, {display:'none'})
        }

        this.open = function() {_open()}

        this.close = function() {_close()}

        this.createComponent = function(content) {
            if (_block) return _block;
            _content = content;
            var _block = _DH.createElement('div', null, {clear:'both'});
            if (cfg.blockAttr) _DH.setAttribute(_block, cfg.blockAttr); if (cfg.blockStyle) _DH.setStyle(_block, cfg.blockStyle);
            var vsp = _DH.createElement('div', null, {height:'10px', fontSize:0});
            var titlebar = _DH.createElement('div', null, {height:'16px'});
            if (cfg.titleRowAttr) _DH.setAttribute(titlebar, cfg.titleRowAttr); if (cfg.titleRowStyle) _DH.setStyle(titlebar, cfg.titleRowStyle);
            var title = _DH.createElement('span', null, {cssFloat:'left',marginLeft:'6px'});
            if (cfg.title) _DH.setAttribute(title, {innerHTML: cfg.title});
            if (cfg.titleAttr) _DH.setAttribute(title, cfg.titleAttr); if (cfg.titleStyle) _DH.setStyle(title, cfg.titleStyle);
            var sw = _DH.createElement('span', null, {cssFloat:'right',width:'16px'});
            _img = _DH.createElement('img', {onclick: this.open}, {cursor:'pointer',width:'16px',height:'16px'});
            if (cfg.imgAttr) _DH.setAttribute(_img, cfg.imgAttr); if (cfg.imgStyles) _DH.setStyle(_img, cfg.imgStyles);
            _block.appendChild(vsp); _block.appendChild(titlebar);
            if (_content) _block.appendChild(_content);
            titlebar.appendChild(title); titlebar.appendChild(sw); sw.appendChild(_img);
            if (cfg.opened) _open();
            else _close();
            return _block;
        }


   }

    /*
     * DHTML list component
     *
     * coniguration object:
     * {
     *    columns: array of columnd descriptors {width:'...', title: '...', onclick: function()}
     *    onCheckAll: function(boolean)
     *    onCheck: function(boolean, id)
     *    onNextPage: function()
     *    onPreviousePage: function()
     *    info: global info descriptor {image:'...', onMouseOver: function(element, id), onMouseOut: function()}
     *    prevImgSrcE: 'previous button enabled image src'
     *    prevImgSrcD: 'previous button disabled image src'
     *    nextImgSrcE: 'next button enabled image src'
     *    nextImgSrcD: 'next button disabled image src'
     *    titleRowAttr: {... title row attributes ...}
     *    titleRowStyle: {... title row styles ...}
     *    titleCellAttr: {... title cell attributes ...}
     *    titleCellStyle: {... title cell styles ...}
     *    listBoxAttr: { ... list box attributes ...}
     *    listBoxStyle: { ... list box styles ...}
     *    dataBoxAttr: { ... data box attributes ...}
     *    dataBoxStyle: { ... data box styles ...}
     *    dataRowAttr: { ... data box attributes ...}
     *    dataRowStyle: { ... data row styles ...}
     *    dataCellAttr: { ... data cell attributes ...}
     *    dataCellStyle: { ... data cell styles ...}
     *    statusRowAttr: { ... status row attributes ...}
     *    statusRowStyle: { ... status row styles ...}
     *    statusCellAttr: { ... status cell attributes ...}
     *    statusCellStyle: { ... status cell styles ...}
     *    prevImgAttr: { ... previous button image attributes ...}
     *    prevImgStyle: { ... previous button image styles ...}
     *    nextImgAttr: { ... newxt button image attributes ...}
     *    nextImgStyle: { ... next button image styles ...}
     * }
     *
     * function setData(array of row data objects {
     *     id:'...',
     *     indent: 'indent level, default 0',
     *     checked: boolean,
     *     info descriptor {image:'...', onMouseOver: function(element, id), onMouseOut: function()}
     *     cells: array of strings});
     */
    this.createList = function(cfg) {
        if (!cfg) {
            cfg = {columns:{}};
        }
        var _indent_step = 23;

        var _content = false;
        var _list_box = false;
        var _page = false;
        var _pages = false;
        var _items = false;
        var _img_prev = false;
        var _img_next = false;
        var _img_prev_src_e = cfg.prevImgSrcE ? cfg.prevImgSrcE : '';
        var _img_prev_src_d = cfg.prevImgSrcD ? cfg.prevImgSrcD : '';
        var _img_next_src_e = cfg.nextImgSrcE ? cfg.nextImgSrcE : '';
        var _img_next_src_d = cfg.nextImgSrcD ? cfg.nextImgSrcD : '';
        var _check_all_input = false;

        this.setSelectAll = function(b) {
            if (_check_all_input) {
                _check_all_input.checked = b;
                _check_all_input.defaultChecked = b;
            }
        }

        this.setData = function(data) {
            if (_list_box) {
                while (_list_box.childNodes.length > 0) _list_box.removeChild(_list_box.childNodes[0]);
                if (data.length == 0) return;
                var rows = _DH.createElement('div', null, {clear:'both'});
                if (cfg.dataBoxAttr) _DH.setAttribute(rows, cfg.dataBoxAttr); if (cfg.dataBoxStyle) _DH.setStyle(rows, cfg.dataBoxStyle);
                for (var i in data) {
                    var rowData = data[i];  
                    var indent = rowData.indent ? (_indent_step * parseInt(rowData.indent)) : 0;
                    var row = _DH.createElement('div', null, {clear:'both',height:'20px',textAlign:'left'});
                    if (cfg.dataRowAttr) _DH.setAttribute(row, cfg.dataRowAttr); if (cfg.dataRowStyle) _DH.setStyle(row, cfg.dataRowStyle);
                    if (indent > 0) {
                        row.appendChild(_DH.createElement('span', {innerHTML:'&nbsp;'}, {cssFloat:'left',width:indent+'px',display:'block'}));
                    }
                    if (cfg.onCheckAll || cfg.onCheck) {
                        var holder = _DH.createElement('span', null, {cssFloat:'left',width:'16px'});
                        if (cfg.dataCellAttr) _DH.setAttribute(holder, cfg.dataCellAttr); if (cfg.dataCellStyle) _DH.setStyle(holder, cfg.dataCellStyle);
                        if (cfg.onCheck) {
                            var check_input = false ;
                            var boxType = 'checkbox';

                             if(cfg.singleSelection) {
                                boxType = 'radio'; //radio
                                check_input = _DH.createRadioInput('radio_name',null,null);
                              } else
                                 check_input = _DH.createElement('input', {type:'checkbox'}, null);
                               //check_input.onclick = function(event) {if (!event) event=window.event; if (cfg.onCheck) cfg.onCheck((event.target || event.srcElement).checked, (event.target || event.srcElement).row_id)};

                                check_input.onclick = function(event) {
                                    if (!event) event=window.event;
                                    if (cfg.onCheck) cfg.onCheck((event.target || event.srcElement).checked, (event.target || event.srcElement).row_id)
                                 };

                                check_input.row_id = rowData.id;
                                check_input.id ='row_id_'+ rowData.id;

                             if(boxType == 'radio'){


                              }else{
                               check_input.checked = rowData.checked;
                               check_input.defaultChecked = rowData.checked; // IE trick
                              }
                            holder.appendChild(check_input);
                        } 
                        row.appendChild(holder);
                    }
                    if (cfg.columns) {
                        for (var j = 0; j < cfg.columns.length; j++) {
                            var column = cfg.columns[j];
                            var width = parseInt(column.width);
                            if (j == 0) width -= indent;
                            var cellData = rowData.cells[j];
                            var paddinTopSize = '2px';
                            if(navigator.appName=="Microsoft Internet Explorer") {
                                 paddinTopSize = '0px';
                            }
                            if (typeof cellData == 'string' && cellData.substring(0, 1) != '<') {
                                cellData = _DH.createElement('span', {innerHTML:cellData}, {padding:'2px',paddingLeft:'4px',width:width-6+'px',overflow:'hidden',whiteSpace:'nowrap'});
                            } else {
                                cellData = _DH.createElement('span', {innerHTML:cellData}, null);
                            }
                            var holder = _DH.createElement('span', null, {cssFloat:'left',width:width,overflow:'hidden', paddingTop:paddinTopSize,whiteSpace:'nowrap'});
                            holder.appendChild(cellData);
                            if (cfg.dataCellAttr) _DH.setAttribute(holder, cfg.dataCellAttr); if (cfg.dataCellStyle) _DH.setStyle(holder, cfg.dataCellStyle);
                            row.appendChild(holder);
                        }
                    }
                    var info = rowData.info || cfg.info;
                    if (info) {
                        var holder = _DH.createElement('span', null, {cssFloat:'right',width:'16px'});
                        var img = _DH.createElement('img', null, {cursor:'pointer',width:'16px',height:'16px'});
                        if (info.image) img.src = info.image;
                        if (info.onMouseOver) {
                            img.onmouseoverhandler = info.onMouseOver;
                            img.onmouseover = function(event) {if (!event) event=window.event; var e = (event.target || event.srcElement); e.onmouseoverhandler(e, e.row_id)};
                            img.row_id = rowData.id;
                        }
                        if (info.onMouseOut) {
                            img.onmouseouthandler = info.onMouseOut; 
                            img.onmouseout = function(event) {if (!event) event=window.event; var e = (event.target || event.srcElement); e.onmouseouthandler()};
                        }
                        holder.appendChild(img); row.appendChild(holder);
                    }
                    rows.appendChild(row);
                }
                _list_box.appendChild(rows);
            }
        }

        this.setData2 = function(data) {   // row height = 40px
            if (_list_box) {
                while (_list_box.childNodes.length > 0) _list_box.removeChild(_list_box.childNodes[0]);
                if (data.length == 0) return;
                var rows = _DH.createElement('div', null, {clear:'both'});
                if (cfg.dataBoxAttr) _DH.setAttribute(rows, cfg.dataBoxAttr); if (cfg.dataBoxStyle) _DH.setStyle(rows, cfg.dataBoxStyle);
                for (var i in data) {
                    var rowData = data[i];
                    var indent = rowData.indent ? (_indent_step * parseInt(rowData.indent)) : 0;
                    var row = _DH.createElement('div', null, {clear:'both',height:'60px',textAlign:'left'});
                    if (cfg.dataRowAttr) _DH.setAttribute(row, cfg.dataRowAttr); if (cfg.dataRowStyle) _DH.setStyle(row, cfg.dataRowStyle);
                    if (indent > 0) {
                        row.appendChild(_DH.createElement('span', {innerHTML:'&nbsp;'}, {cssFloat:'left',width:indent+'px',display:'block'}));
                    }
                    if (cfg.onCheckAll || cfg.onCheck) {
                        var holder = _DH.createElement('span', null, {cssFloat:'left',width:'16px'});
                        if (cfg.dataCellAttr) _DH.setAttribute(holder, cfg.dataCellAttr); if (cfg.dataCellStyle) _DH.setStyle(holder, cfg.dataCellStyle);
                        if (cfg.onCheck) {
                            var check_input = _DH.createElement('input', {type:'checkbox'}, null);
                            check_input.onclick = function(event) {if (!event) event=window.event; if (cfg.onCheck) cfg.onCheck((event.target || event.srcElement).checked, (event.target || event.srcElement).row_id)};
                            check_input.row_id = rowData.id;
                            check_input.checked = rowData.checked;
                            check_input.defaultChecked = rowData.checked; // IE trick
                            holder.appendChild(check_input);
                        }
                        row.appendChild(holder);
                    }
                    if (cfg.columns) {
                        for (var j = 0; j < cfg.columns.length; j++) {
                            var column = cfg.columns[j];
                            var width = parseInt(column.width);
                            if (j == 0) width -= indent;
                            var cellData = rowData.cells[j];
                            if (typeof cellData == 'string' && cellData.substring(0, 1) != '<') {
                                cellData = _DH.createElement('div', {innerHTML:cellData}, {height :'100%',padding:'2px',paddingLeft:'4px',width:width-6+'px',overflow:'hidden'});
                            } else {
                                cellData = _DH.createElement('span', {innerHTML:cellData}, null);
                            }
                            var holder = _DH.createElement('div', null, {height :'100%', cssFloat:'left',width:width,overflow:'hidden'});
                            holder.appendChild(cellData);
                            if (cfg.dataCellAttr) _DH.setAttribute(holder, cfg.dataCellAttr); if (cfg.dataCellStyle) _DH.setStyle(holder, cfg.dataCellStyle);
                            row.appendChild(holder);
                        }
                    }
                    var info = rowData.info || cfg.info;
                    if (info) {
                        var holder = _DH.createElement('span', null, {padding:'5px',cssFloat:'right',width:'16px'});
                        var img = _DH.createElement('img', null, {cursor:'pointer',width:'16px',height:'16px'});
                        if (info.image) img.src = info.image;
                        if (info.onMouseOver) {
                            img.onmouseoverhandler = info.onMouseOver;
                            img.onmouseover = function(event) {if (!event) event=window.event; var e = (event.target || event.srcElement); e.onmouseoverhandler(e, e.row_id)};
                            img.row_id = rowData.id;
                        }
                        if (info.onMouseOut) {
                            img.onmouseouthandler = info.onMouseOut;
                            img.onmouseout = function(event) {if (!event) event=window.event; var e = (event.target || event.srcElement); e.onmouseouthandler()};
                        }
                        holder.appendChild(img); row.appendChild(holder);
                    }
                    rows.appendChild(row);
                }
                _list_box .style.height ='240px';
                _list_box.appendChild(rows);
            }
        }

        this.setStatus = function(page, pages, items, prevEnabled, nextEnabled) {
            if (_page) _page.innerHTML = page;
            if (_pages) _pages.innerHTML = pages;
            if (_items) _items.innerHTML = items;
            if (_img_next) {
                _img_next.src = nextEnabled ? _img_next_src_e : _img_next_src_d;
                _img_next.onclick = (nextEnabled && cfg.onNextPage) ? cfg.onNextPage : null;
                _DH.setStyle(_img_next, {cursor:(nextEnabled ? 'pointer' : 'auto')});
            }
            if (_img_prev) {
                _img_prev.src = prevEnabled ? _img_prev_src_e : _img_prev_src_d;
                _img_prev.onclick = (prevEnabled && cfg.onPreviousePage) ? cfg.onPreviousePage : null;
                _DH.setStyle(_img_prev, {cursor:(prevEnabled ? 'pointer' : 'auto')});
            }
        }

        this.createComponent = function() {
            if (_content) return _content;
            _content = _DH.createElement('div', null, {clear:'both'});
            var title_box = _DH.createElement('div', null, {clear:'both',height:'18px',textAlign:'left'});
            if (cfg.titleRowAttr) _DH.setAttribute(title_box, cfg.titleRowAttr); if (cfg.titleRowStyle) _DH.setStyle(title_box, cfg.titleRowStyle);
            if (cfg.onCheckAll || cfg.onCheck) {
                var holder = _DH.createElement('span', null, {cssFloat:'left',width:'16px',paddingLeft:'1px'});
                if (cfg.titleCellAttr) _DH.setAttribute(holder, cfg.titleCellAttr); if (cfg.titleCellStyle) _DH.setStyle(holder, cfg.titleCellStyle);
                if (cfg.onCheckAll) {
                    _check_all_input = _DH.createElement('input', {type:'checkbox'}, null);
                    _check_all_input.onclick = function(event) {if (!event) event=window.event; if (cfg.onCheckAll) cfg.onCheckAll((event.target || event.srcElement).checked)};
                    holder.appendChild(_check_all_input);
                }
                title_box.appendChild(holder);
            }
            if (cfg.columns) {
                for (var i in cfg.columns) {
                    var column = cfg.columns[i];
                    var width = parseInt(column.width);
                    var holder = _DH.createElement('span', null, {cssFloat:'left',width:width+'px',overflow:'hidden',whiteSpace:'nowrap'});
                    holder.appendChild(_DH.createElement('span', {innerHTML:column.title}, {width:width-6+'px',padding:'2px',paddingLeft:'4px',overflow:'hidden',whiteSpace:'nowrap'}));
                    if (cfg.titleCellAttr) _DH.setAttribute(holder, cfg.titleCellAttr); if (cfg.titleCellStyle) _DH.setStyle(holder, cfg.titleCellStyle);
                    if (column.onclick) {_DH.setAttribute(holder, {onclick: column.onclick}); _DH.setStyle(holder, {cursor: 'pointer'})}
                    title_box.appendChild(holder);
                }
            }
            _list_box = _DH.createElement('div', null, {clear:'both',marginTop:'3px',height:'105px'});
            if (cfg.listBoxAttr) _DH.setAttribute(_list_box, cfg.listBoxAttr); if (cfg.listBoxStyle) _DH.setStyle(_list_box, cfg.listBoxStyle);
            var list_pagger = _DH.createElement('div', null, {clear:'both',marginTop:'3px',height:'16px'});
            if (cfg.statusRowAttr) _DH.setAttribute(list_pagger, cfg.statusRowAttr); if (cfg.statusRowStyle) _DH.setStyle(list_pagger, cfg.statusRowStyle);
            var pages = _DH.createElement('span', null, {cssFloat:'left',styleFloat:'left'});
            if (cfg.statusCellAttr) _DH.setAttribute(pages, cfg.statusCellAttr); if (cfg.statusCellStyle) _DH.setStyle(pages, cfg.statusCellStyle);
            _page = _DH.createElement('span', null, null);
            _pages = _DH.createElement('span', null, null);
            _items = _DH.createElement('span', null, null);
            pages.appendChild(_page);
            pages.appendChild(_DH.createElement('span', {innerHTML:'/'}, {marginLeft:'5px',marginRight:'5px'}));
            pages.appendChild(_pages);
            pages.appendChild(_DH.createElement('span', {innerHTML:'('}, {marginLeft:'5px'}));
            pages.appendChild(_items);
            pages.appendChild(_DH.createElement('span', {innerHTML:')'}, null));
            list_pagger.appendChild(pages);
            var butdown = _DH.createElement('span', null, {cssFloat:'right',width:'16px'});
            if (cfg.statusCellAttr) _DH.setAttribute(butdown, cfg.statusCellAttr); if (cfg.statusCellStyle) _DH.setStyle(butdown, cfg.statusCellStyle);
            _img_next = _DH.createElement('img', {src:_img_next_src_d}, {width:'16px',height:'16px'});
            if (cfg.nextImgAttr) _DH.setAttribute(_img_next, cfg.nextImgAttr); if (cfg.nextImgStyle) _DH.setStyle(_img_next, cfg.nextImgStyle);
            butdown.appendChild(_img_next);
            var butup = _DH.createElement('span', null, {cssFloat:'right',width:'16px'});
            if (cfg.statusCellAttr) _DH.setAttribute(butup, cfg.statusCellAttr); if (cfg.statusCellStyle) _DH.setStyle(butup, cfg.statusCellStyle);
            _img_prev = _DH.createElement('img', {src:_img_prev_src_d}, {width:'16px',height:'16px'});
            if (cfg.prevImgAttr) _DH.setAttribute(_img_prev, cfg.prevImgAttr); if (cfg.prevImgStyle) _DH.setStyle(_img_prev, cfg.prevImgStyle);
            butup.appendChild(_img_prev);
            list_pagger.appendChild(butdown); list_pagger.appendChild(butup);
            _content.appendChild(title_box);
            _content.appendChild(_list_box);
            _content.appendChild(list_pagger);
            return _content;
        }

    }

}
var _DCC = new DHTMLCommonComponents();

function DHTMLCommonComponentsLoader () {
    var _components_queue = new Array();
    this.add = function(createMethod) {_components_queue[_components_queue.length] = createMethod}
    window.onload = function() {for (var i in _components_queue) _components_queue[i]()}
}
var _DCCL = new DHTMLCommonComponentsLoader();













// todo move to the divs script
function QualificationInfo(frameClass, innerClass, labelClass, valueClass, nameLabel, categoryLabel, descriptionLabel, width, height) {

    var qualif_info = false;
	var name_element_id = 'dhtml_qualif_info_qname';
	var category_element_id = 'dhtml_qualif_info_qcategory';
	var description_element_id = 'dhtml_qualif_info_qdescription';


	var getTop = function(baseObj) {
		var dy = baseObj.offsetTop;
		while((baseObj = baseObj.offsetParent) != null) dy += baseObj.offsetTop;
		return dy;
	}

	var getLeft = function(baseObj) {
		var dx = baseObj.offsetLeft;
		while((baseObj = baseObj.offsetParent) != null) dx += baseObj.offsetLeft;
		return dx;
	}

    var createQualifInfo = function() {
        qualif_info = document.createElement('DIV');
        qualif_info.id = 'dhtml_qualif_info';
        qualif_info.className = frameClass;
        qualif_info.style.zIndex = 500;
        qualif_info.style.position = 'absolute';
        qualif_info.style.display = 'none';
        qualif_info.style.width = width;
        qualif_info.style.height = height;
        qualif_info.style.padding = '3px';

        var d1 = document.createElement('DIV');
        d1.className = innerClass;
        d1.style.padding = '3px';

        var inlineTable = '';
		inlineTable += '<table cellpadding="3" cellspacing="0" width="100%">';
		inlineTable += '<tr valign="top"><td width="40%" class="'+labelClass+'">'+nameLabel+'</td><td id="'+name_element_id+'" width="60%" class="'+valueClass+'"></td></tr>';
		inlineTable += '<tr valign="top"><td width="40%" class="'+labelClass+'">'+categoryLabel+'</td><td id="'+category_element_id+'" width="60%" class="'+valueClass+'"></td></tr>';
		inlineTable += '<tr valign="top"><td width="40%" class="'+labelClass+'">'+descriptionLabel+'</td><td id="'+description_element_id+'" width="60%" class="'+valueClass+'"></td></tr>';
		inlineTable += '</table>';

        d1.innerHTML = inlineTable;
        qualif_info.appendChild(d1);

        document.body.appendChild(qualif_info);
    }

    this.setPosition = function(baseObj) {
        if (!qualif_info) {
            qualif_info = document.getElementById('dhtml_qualif_info');
			if (!qualif_info) {
				createQualifInfo();
			}
        }
		qualif_info.style.top = getTop(baseObj) + baseObj.offsetHeight + 2 + 'px';
		qualif_info.style.left = getLeft(baseObj) + 'px';
	}

    this.show = function(nameValue, categoryValue, descriptionValue) {
        if (!qualif_info) {
            qualif_info = document.getElementById('dhtml_qualif_info');
			if (!qualif_info) {
				createQualifInfo();
			}
        }
		document.getElementById(name_element_id).innerHTML = nameValue;
		document.getElementById(category_element_id).innerHTML = categoryValue;
		document.getElementById(description_element_id).innerHTML = descriptionValue;
		qualif_info.style.display = 'block';
    }

	this.hide = function() {
		if (qualif_info) {
			qualif_info.style.display = 'none';
		}
	}
}