﻿// JScript File
var objList = new Object();

// todo: TableEdit should be shown/hidden and moved/sized to appear over the cell

function text2inputvalue(input, text){
    var tmp = input.value;
    input.value = text;
    var ret = input.value;
    input.value = tmp;
    return ret;
}

function Exec(funct, params)
{
    if (funct)
    try {
        if (typeof(funct) == "string")
            eval(funct + "(params);");
        else if (typeof(funct) == "function")
            (funct)(params);
    } catch (err) { OnError(err); }
}


function disableCtrl(ctrl, disable)
{
    if(Browser() == "ie")
    {
        if(ctrl.disabled == null) return;
    	ctrl.disabled = disable;
    }
    else if(Browser() == "ff")
    {
        if(ctrl.setAttribute == null) return;
        if (!disable)
            ctrl.removeAttribute("disabled");
        else
            ctrl.setAttribute("disabled", "disabled");
    }


	if (disable)
		ctrl.tabInd = ctrl.tabIndex;
	else
		ctrl.tabIndex = ctrl.tabInd;

    for(var i=0; ctrl.childNodes && i<ctrl.childNodes.length; i++)
        disableCtrl(ctrl.childNodes[i], disable);
}

var inpType = { None:0, Text:1, Select:2, Check:3, Textarea:4, Datetime:5, Money:6, DDEx:7, tinyMCE:8 }

function inputType(input)
{
    var tag = ("" + input.tagName).toUpperCase();
    var typ = ("" + input.getAttribute("type")).toUpperCase();
    var edt = ("" + input.getAttribute("cnEditType")).toUpperCase();

    if(edt == "TINYMCE")  return inpType.tinyMCE;
    if(tag == "TEXTAREA") return inpType.Textarea;
    if(tag == "SELECT")   return inpType.Select;
    if(edt == "DDEX")     return inpType.DDEx;
    if(tag != "INPUT")    return inpType.None;
    if(edt == "MONEY")    return inpType.Money;
    if(edt == "DATETIME") return inpType.Datetime;
    if(typ == "TEXT")     return inpType.Text;
    if(typ == "CHECKBOX") return inpType.Check;
	return inpType.None;
}

function checkTag(obj, tag) // Use for debug
{
    if(("" + obj.tagName).toUpperCase() == tag.toUpperCase())
        return true;
    
    alert("Error: wrong object come");
    return false;
}


function Quote(str)
{
    return str.replace(/&/g, "&amp;").replace(/>/g, "&gt;").replace(/</g, "&lt;");;
}





function ClearInput(input)
{
    if(input == null) return;
    if(input.getAttribute("type") && input.getAttribute("type").toUpperCase() == "CHECKBOX")
        input.checked = false;
    else
        try{ input.value = input.getAttribute("cnDefVal") ? input.getAttribute("cnDefVal") : "";} catch(ex) { try{input.innerHTML = "";} catch(ex){} } 
}




//----------------------------------------------------- Transport staff ----------------------------------------------------

var Progress;
var webServiceCalls = 0;
var TryToSendBatch = null;
var theBatch = new Array();
var resFunct = new Array();

function CustServerCall(cmdCode, objName, args, onRes)
{
    resFunct.push(onRes);
    ServerCall("Custom", "Custom", Hash("cmdCode", cmdCode, "objName", objName, "args", args, "onRes", resFunct.length - 1));
}

//=== DON'T CALL THE FOLLOWING FUNCTION FROM OUTSIDE OF PAT!!! ===================
function ServerCall(cmdCode, objName, args)
{
	theBatch.push(Hash("cmdCode", cmdCode, "objName", objName, "args", args));
	window.clearTimeout(TryToSendBatch);
	TryToSendBatch = window.setTimeout(SendBatch, 1);
}
//================================================================================

function SendBatch()
{
    if (theBatch.length == 0) return;
	Tables.BatchCallWebService(theBatch, OnSendBatchRes, OnServiceError);
	theBatch.length = 0;
    if (Progress && ++webServiceCalls == 1) Progress.Show(true);
}

function OnSendBatchRes(res)
{
	if (res != null)
	{
		for (var i = 0; i < res.length; i++)
			if(res[i].cmdCode == "Custom") try { resFunct[res[i]["args"].onRes](res[i]); } catch(err) {OnError("Defined function failed: " + err);}
			else if (objList[res[i]["objName"]]) try { objList[res[i]["objName"]].OnServiceRes(res[i]); } catch (err) { OnError(err); }
		if(Progress && --webServiceCalls == 0 && theBatch.length == 0) Progress.Show(false);
	}
}

function OnServiceError(error)
{
    if (error != null) OnError(error._message); // + "<br>" + error._stackTrace);
    if(Progress && --webServiceCalls == 0) Progress.Show(false);
}


//--------------------------------------------------------------------------------------------------------------------------


//  Error handler
var OnErrorCustom = null, cntn = true;
function OnError(errorText) {
    var errTxt = $get("ErrorText");
    var errWnd = typeof(placeHolderID) != "undefined" && placeHolderID != null ? $find(placeHolderID) : null;
    if(OnErrorCustom) try { eval("cntn = " + OnErrorCustom + "(errorText);"); } catch(err) {}
    if(cntn) { if (errWnd && errTxt) {errTxt.innerHTML = errorText; errWnd.show();} else alert(errorText); }
    return false;
}



function DataChangeNotify(List, params)
{
    var names  = (List != null && List != "" ? List.replace(/\s/g, "").split(",") : new Array());
    for(var i=0; i<names.length; i++)
        if(objList[names[i]]) objList[names[i]].OnDataChangeNotification(params);
}

function RowChangeNotify(List, params)
{
    var names  = (List != null && List != "" ? List.replace(/\s/g, "").split(",") : new Array());
    for(var i=0; i<names.length; i++)
    {
        var parts = names[i].split("/");
        var paramsCurr = CloneHash(params);
        if(parts.length > 1) paramsCurr = AddHash(paramsCurr, "rowidname", parts[1]);
        if(objList[parts[0]]) objList[parts[0]].OnRowChangeNotification(paramsCurr);
    }
}

//------------------------------------------------ Table Editor ------------------------------------------------
//--------------------------------------------------------------------------------------------------------------

function TableInit(name, args)
{
    if(args == null) args = new Object();
    objList[name] = new TableEditor(name, args);
}

function TableRefresh(name, args)
{
    if(objList[name]) 
    {
        objList[name].currentPage = 1;
        objList[name].LoadData(args);
    }
}

function TableRefreshRow(name, rowid)
{
    if(objList[name]) objList[name].RefreshRow(rowid);
}

function TableSetCurRow(name, rowid)
{
    if(objList[name]) objList[name].SetCurRow(rowid);
}

function TableSort(name, sNames)
{
    if(objList[name]) objList[name].Sort(sNames);
}

function TableGetRowsCnt(name)
{
    return objList[name].rowsTotal != null ? objList[name].rowsTotal : 0;
}

function TableSetCurPage(name, page)
{
    if(objList[name] && objList[name].SetCurPage(page)) objList[name].LoadData();
}

function TableSelectRow(name, rowid, sel)
{
    if(objList[name]) objList[name].SelectRow(rowid, sel);
}

function TableSelectAllRows(name, sel)
{
    if(objList[name]) 
        if(sel) objList[name].SelectAllRows(); else objList[name].ClearAllSelection();
}

function TableSetRowsPerPage(name, rowsnum)
{
    if(objList[name] && objList[name].SetPageSize(rowsnum)) objList[name].LoadData();
}

function TableDelRow(name, row, confirm) 
{
    if(objList[name]) objList[name].DelRow(row, confirm);
}

function TableMakeInsert(name)
{
    if(objList[name]) objList[name].InsertRow();
}

function TableMakeInsertEF(name)
{
    if(objList[name]) objList[name].InsertRowEF();
}

function TableClearEF(name)
{
    if(objList[name]) objList[name].ClearEF();
}

function TableShowEF(name, show)
{
    if(objList[name]) objList[name].ShowEF(show);
}

function TableGetCurRowID(name)
{
    if(objList[name]) return objList[name].GetCurrentRowID();
}

function TableGetSelRows(name)
{
    if(objList[name]) return objList[name].GetSelRows();
}

function TableGetArgs(name)
{
    if(objList[name]) return objList[name].args;
}

function TableHideShowCol(name, n, b) {
    if (objList[name]) return objList[name].HideShowCol(n, b);
}

function TableGetCurRowValueByColumn(tableName, columnName) //ask MI
{
    if(objList[tableName]) return objList[tableName].GetCurRowValueByColumn(columnName);
}
function TableGetDataValue(tableName, columnName, rowID)
{
    if(objList[tableName]) return objList[tableName].GetDataValue(columnName, rowID);
}
function TableLock(name, lock, lockIns)
{
    if(objList[name]) objList[name].LockTable(lock, lockIns);
}
function TableBodyLockState(name)
{
    if(objList[name]) return objList[name].LockedBody;
}
function TableInsLockState(name)
{
    if(objList[name]) return objList[name].LockedInsR;
}
function TableEndEdit(name)
{
    if(objList[name] && objList[name].EndEdit) return objList[name].EndEdit(objList[name].theEditor, null, null);
}
//should be removed
function DisableTable(name, disable, disableIns)
{
    if(objList[name]) objList[name].LockTable(disable, disableIns);
}

function TableEditor(name, args)
{
    var self = this;

    self.name = name;
    self.args = args;

    self.colDefs = new Array();

    self.TableRows = new Array();

    self.curRow = null;
    self.pagesCount = 1;
    
    self.selRowsId = new Object();

    self.topDiv = $get(self.name);
    self.topPager = $get(self.name + "TopPager");
    self.botPager = $get(self.name + "BottomPager");
    self.rowsPP = $get(self.name + "RowsPP");
    self.tabPattern = $get(self.name + "Table");
    self.headRow = $get(self.name + "Header");
    self.gotoPage = $get(self.name + "GoToPage");
    self.rowsCnt = $get(self.name + "RowsCnt");

    if(self.topDiv == null) return;
    if(self.headRow) self.headRow.className = (self.topDiv.getAttribute("TableHeadCss") ? self.topDiv.getAttribute("TableHeadCss") : "def_tablehead_css");
    self.tabPattern.style.display = "none";

    self.tableHolders = new Array();
    for(var i = 1; ; i++)
    {
        var th = $get(self.name + "_TableHolder" + i);
        if(th == null) break;
        self.tableHolders.push(th);
    }
    if(self.tableHolders.length == 0) {
        var tc = document.createElement("div");
        self.tableHolders.push(tc);
        tc.id = self.name + "_TableHolder1";
        tc.style.margin = "0px"; // the developer is not aware that this div will be created so it should have no visual impact.
        tc.style.border = "0px";
        tc.style.padding = "0px";
        self.topDiv.insertBefore(tc, self.tabPattern);
    }
    self.insRowHolder = $get(self.name + "_InsRowHolder");
    
    self.GetSelRows = function ()
    {
        return self.selRowsId;
    }
    
    self.SetCurPage = function (page)
        {
            if(page == self.currentPage) return false;
            if(page && (!ValidateInt(page) || page < 1 || objList[name].pagesCount < page)) return OnError(self.name + ": Invalid page number");
            self.currentPage = page;
            return true;
        }

    self.SetPageSize = function (size)
        {
            if(size == self.PageSize) return false;
            if (size && (!ValidateInt(size) || size < 1)) return OnError(self.name + ": Invalid page size");
            self.currentPage = 1;
            self.PageSize = size;
            self.RowsCnt = (self.PageSize == null ? null : self.PageSize * self.tableHolders.length); 
            return true;
        }
    self.SetPageSize(self.topDiv.getAttribute("PageSize"));

    self.DataChangeNotifyList = self.topDiv.getAttribute("DataChangeNotifyList");
    self.RowChangeNotifyList = self.topDiv.getAttribute("RowChangeNotifyList");
    
    self.delConfirm = self.topDiv.getAttribute("delConfirm")?self.topDiv.getAttribute("delConfirm"):"";
    self.onDataArrived = self.topDiv.getAttribute("OnDataArrived");
    self.onTableLoad = self.topDiv.getAttribute("OnTableLoad");
    self.onRowLoad = self.topDiv.getAttribute("OnRowLoad");
    self.onTableSet = self.topDiv.getAttribute("OnTableSet");
    self.onSelRow = self.topDiv.getAttribute("onSelRow");
    self.onRowSelected = self.topDiv.getAttribute("onRowSelected");
    self.onSelRowsChanged = self.topDiv.getAttribute("onSelRowsChanged");
    self.onNewRow = self.topDiv.getAttribute("onNewRow");
    self.pagerFunction = self.topDiv.getAttribute("PagerFunction");
    self.pagerText = self.topDiv.getAttribute("pagerText");
    self.endEdit = self.topDiv.getAttribute("EndEdit");
    self.onEndEdit = self.topDiv.getAttribute("onEndEdit");
    self.onDelRow = self.topDiv.getAttribute("onDelRow");
    self.onBeforeDelRow = self.topDiv.getAttribute("onBeforeDelRow");
    self.addRow =  self.topDiv.getAttribute("AddRow");
    self.onAddRow = self.topDiv.getAttribute("onAddRow");
    self.MaxRows = self.topDiv.getAttribute("MaxRows");
    self.RefreshRowOnChange = self.topDiv.getAttribute("RefreshRowOnChange");

    self.DbRowId = (self.topDiv.getAttribute("DbRowId") ? self.topDiv.getAttribute("DbRowId") : "id");

    self.OneClickEdit = (self.topDiv.getAttribute("OneClickEdit") == "True" ? true : false);

    self.ReadOnly = (self.topDiv.getAttribute("ReadOnly") ? self.topDiv.getAttribute("ReadOnly") : "False");
    self.DeleteMode = (self.topDiv.getAttribute("DeleteMode") ? self.topDiv.getAttribute("DeleteMode") : "True");
    self.LockedBody = false;
    self.LockedInsR = false;

    self.MultiColumnsSorting = (self.topDiv.getAttribute("MultiColumnsSorting") ? self.topDiv.getAttribute("MultiColumnsSorting") : "False");

//    self.tabPattern.className = "def_table_css ";
//    if (self.topDiv.getAttribute("TableCss"))
//        self.tabPattern.className += self.topDiv.getAttribute("TableCss");
    self.tabPattern.className = (self.topDiv.getAttribute("TableCss") ? self.topDiv.getAttribute("TableCss") : "def_table_css");

    self.RowCss = (self.topDiv.getAttribute("RowCss") ? self.topDiv.getAttribute("RowCss") : "def_row_css");
    self.SelRowCss = (self.topDiv.getAttribute("SelRowCss") ? self.topDiv.getAttribute("SelRowCss") : "def_selrow_css");
    self.MouseOverRowCss = (self.topDiv.getAttribute("MouseOverRowCss") ? self.topDiv.getAttribute("MouseOverRowCss") : "def_mouseoverrow_css"); 
    self.RowTip = self.topDiv.getAttribute("RowTip");
    self.RowBackColor = self.topDiv.getAttribute("RowBackColor");
    self.OddRowBackColor = (self.topDiv.getAttribute("OddRowBackColor") ? self.topDiv.getAttribute("OddRowBackColor") : "");
    
    self.OnRowMouseOver = self.topDiv.getAttribute("OnRowMouseOver");
    self.OnRowMouseOut = self.topDiv.getAttribute("OnRowMouseOut");

    self.PagerCss = (self.topDiv.getAttribute("PagerCss") ? self.topDiv.getAttribute("PagerCss") : "def_pager_css");
    self.SelPagerCss = (self.topDiv.getAttribute("SelPagerCss") ? self.topDiv.getAttribute("SelPagerCss") : "def_selpager_css");
    self.PagerSepCss = (self.topDiv.getAttribute("PagerSepCss") ? self.topDiv.getAttribute("PagerSepCss") : "def_pagersep_css");
    self.TopPagerCss = (self.topDiv.getAttribute("TopPagerCss") ? self.topDiv.getAttribute("TopPagerCss") : "def_toppager_css");
    self.BotPagerCss = (self.topDiv.getAttribute("BotPagerCss") ? self.topDiv.getAttribute("BotPagerCss") : "def_botpager_css");

    self.TextAreaCss = (self.topDiv.getAttribute("TextAreaCss") ? self.topDiv.getAttribute("TextAreaCss") : "def_textarea_css");

    self.ReadonlyBy  = self.topDiv.getAttribute("ReadonlyBy");
    self.ReadonlyCss = (self.topDiv.getAttribute("ReadonlyCss") ? self.topDiv.getAttribute("ReadonlyCss") : "def_readonly_cell_css");

    self.multSel = (self.topDiv.getAttribute("multSel") == "False" ? false : true);

    self.SortNames = "";
    var t = document.createElement("TABLE");
    self.rowPattern = t.insertRow(-1);
    self.rowPattern.className = self.RowCss;

    for(var k = 0; k < self.headRow.cells.length; k++)
    {
        var r = self.headRow;
        self.rowPattern.insertCell(-1).setAttribute("columnIndex", k);
        r.cells[k].setAttribute("columnIndex", k);
        self.colDefs[k] = new Object();
        self.colDefs[k].cnIndex        = k;
        self.colDefs[k].cnTitle        = r.cells[k].innerHTML;
        self.colDefs[k].cnTip          = r.cells[k].getAttribute("cnTip");
        self.colDefs[k].cnWordWrap     = r.cells[k].getAttribute("cnWordWrap");
        self.colDefs[k].cnSorting      = r.cells[k].getAttribute("cnSorting");
        self.colDefs[k].cnTitleCss     = r.cells[k].getAttribute("cnTitleCss");
        self.colDefs[k].cnEditType     = r.cells[k].getAttribute("cnEditType");
        self.colDefs[k].cnCellCss      = r.cells[k].getAttribute("cnCellCss");
        self.colDefs[k].cnDefVal       = r.cells[k].getAttribute("cnDefVal");
        self.colDefs[k].cnDBName       = r.cells[k].getAttribute("cnDBName");
        self.colDefs[k].cnMaxLen       = r.cells[k].getAttribute("cnMaxLen");
        self.colDefs[k].cnValidate     = r.cells[k].getAttribute("cnValidate");
        self.colDefs[k].cnFormat       = r.cells[k].getAttribute("cnFormat");
        self.colDefs[k].cnImpCss       = r.cells[k].getAttribute("cnImpCss");
        self.colDefs[k].cnRelTableName = r.cells[k].getAttribute("cnRelTableName");
        self.colDefs[k].cnRelBackColor = r.cells[k].getAttribute("cnRelBackColor");
        self.colDefs[k].cnRelShowInPD  = r.cells[k].getAttribute("cnRelShowInPD");
        self.colDefs[k].cnBackColor    = r.cells[k].getAttribute("cnBackColor");
        self.colDefs[k].cnCellTemplFnc = r.cells[k].getAttribute("cnCellTemplateFunction");
        self.colDefs[k].cnCellTemplIH  = r.cells[k].innerHTML;
        self.colDefs[k].cnReadonly     = r.cells[k].getAttribute("cnReadonly");
        self.colDefs[k].cnReadonlyBy   = r.cells[k].getAttribute("cnReadonlyBy");
        self.colDefs[k].cnRelNamesStr  = r.cells[k].getAttribute("cnRelNames");
        self.colDefs[k].cnRelValuesStr = r.cells[k].getAttribute("cnRelValues");
        self.colDefs[k].cnRelColorsStr = r.cells[k].getAttribute("cnRelColors");
        self.colDefs[k].cnCustomValue  = r.cells[k].getAttribute("cnCustomValue");
        self.colDefs[k].cnInEditForm   = (r.cells[k].getAttribute("InEditForm") != "False");
        self.colDefs[k].RefreshTableOnChange = r.cells[k].getAttribute("RefreshTableOnChange");
        //------------------------------- special Auto Complete attributes -----------------------------------//
        // standart sttributes will be used by Auto Complete: cnRelTableName, cnRelNames, cnRelColors, cnRelBackColor
        self.colDefs[k].cnMaxOpts = r.cells[k].getAttribute("cnMaxOpts");
        self.colDefs[k].cnColumn  = r.cells[k].getAttribute("cnColumn");
        self.colDefs[k].divW      = r.cells[k].getAttribute("divW");
        self.colDefs[k].divH      = r.cells[k].getAttribute("divH");
        //----------------------------------------------------------------------------------------------------//
        self.colDefs[k].cnRelNames = null;
        self.colDefs[k].cnRelValues    = null;
        self.colDefs[k].cnRelColors    = null;
        self.colDefs[k].cnShowInPD     = null;
        self.colDefs[k].cnSpellCheck   = r.cells[k].getAttribute("spellcheck") == "true";
        self.colDefs[k].cnNoGrammarCheck   = r.cells[k].getAttribute("nogrammarcheck") == "true";
        if (self.colDefs[k].cnEditType == "DELETE" && self.colDefs[k].cnCellCss == null) {
            self.colDefs[k].cnCellCss = "def_delcolumn_css";
            r.cells[k].className = self.colDefs[k].cnCellCss;
        }
        if(self.colDefs[k].cnTitleCss) r.cells[k].className = self.colDefs[k].cnTitleCss;
        self.colDefs[k].cnSortDr       = "";
        self.colDefs[k].cnValues = new Object();
    }

    
    self.PopUpInsert = (self.topDiv.getAttribute("PopUpInsert") == "True");
    
    if(self.PopUpInsert)
    {
        self.popupdiv = document.createElement("div");
        self.topDiv.appendChild(self.popupdiv);
        self.PopUpInsertCaption = (self.topDiv.getAttribute("PopUpInsertCaption") ? self.topDiv.getAttribute("PopUpInsertCaption") : "Create new entry");
        var PopUpInsertCaptionStr = " Caption3d='" + self.PopUpInsertCaption + "'";
        var PopUpInsertCss = " style='" + (self.topDiv.getAttribute("PopUpInsertStyle") ? self.topDiv.getAttribute("PopUpInsertStyle") : "") + "'";
        var PopUpInsertClass = " class='" + (self.topDiv.getAttribute("PopUpInsertCss") ? self.topDiv.getAttribute("PopUpInsertClass") : "") + "'";
        
        self.popupdiv.innerHTML = "<div id='" + self.name + "_Inner_PopUp' Style3d='True' OnHide=\"TableClearEF('" + self.name + "');\" " + PopUpInsertCaptionStr + PopUpInsertCss + PopUpInsertClass + ">" +
            "<table style='width:100%; height:100%;'><tr><td id='" + self.name + "_EditFormHolder'></td></tr>" +
                "<tr><td align='center' style='padding-top:20px;'>" +
                    "<input type='button' value='Create' onclick=\"TableMakeInsertEF('" + self.name + "'); PopUpShow('" + self.name + "_Inner', false);\"  />" +
                    "<input type='button' value='Cancel' onclick=\"PopUpShow('" + self.name + "_Inner', false);\"  />" +
                "</td></tr></table></div>";

        PopUpInit(self.name + "_Inner");
    }
    
    self.InsertImg = (self.topDiv.getAttribute("InsertImg") ? self.topDiv.getAttribute("InsertImg") : "PAT/images/add.png");
    self.insRow = null;
    self.insRowDef = null;

    if(self.topDiv.getAttribute("InsertRow") != "False" && ! self.PopUpInsert)
    {
        self.insRow = document.createElement("tr");
        self.insRow.dbid = "-1";
        self.insRow.className = self.RowCss;
        for (var j = 0; j < self.colDefs.length; j++) 
        {
            var cell = document.createElement("td");
            self.insRow.appendChild(cell);
            cell.setAttribute("columnIndex", j);
            if(self.colDefs[j].cnEditType == "DELETE")
                cell.innerHTML = "<img style='border:0' title='Insert Row' alt='Insert Row' src='" + self.InsertImg + "' onclick=\"if(this.getAttribute('disabled') != 'disabled'){ TableMakeInsert('" + self.name + "'); event.cancelBubble = true;}\" />";
        }
    }
    
    self.EditFormInput = function (coldef)
    {
        var theEditor;
        switch(coldef.cnEditType)
        {
            case "TEXT":
                theEditor = document.createElement("INPUT");
                theEditor.type = "text";
                break;
            case "MONEY":
                theEditor = document.createElement("INPUT");
                theEditor.type = "text";
                theEditor.onkeydown = function(evt){return ImpEventMoneyFormatCheck(this, (evt ? evt : window.event)); };
                break;
            case "TEXTAREA":
            case "HTML":
                theEditor = document.createElement("textarea");
                theEditor.className = (self.topDiv.getAttribute("EditformTaCss") ? self.topDiv.getAttribute("EditformTaCss") : "def_editform_ta_css");;
                break;
            case "DATETIME":
                theEditor = document.createElement("INPUT");
                theEditor.type = "text";

                /*
	            if(coldef.cnClndBtn != "False")
	            {
	                theEditor.style.height = "12px";
    		        
                    var bt = document.createElement("img");    
                    bt.id = theEditor.id + "_CalendarBtn";
                    bt.setAttribute("impId", theEditor.id);
                    bt.alt = "";
                    bt.src = "PAT/Calendar/calendar.gif";

                    var pr = theEditor.parentNode;
                    var t = document.createElement("table");  
                    t.className = "def_emptytable_css"; 
                    var r = t.insertRow(0);
                    r.insertCell(0).appendChild(theEditor);
                    r.insertCell(1).appendChild(bt);

                    pr.appendChild(t);
                    bt.onclick = function(){if(!$get(this.getAttribute("impId")).disabled) return popUpCalendar(this, $get(this.getAttribute("impId")), 'MM/dd/yyyy'); };
                    theEditor.onclick = function(){if(!this.disabled) return popUpCalendar($get(this.id + "_CalendarBtn"), this, 'MM/dd/yyyy'); };
                }
                else
                */
                    theEditor.onclick = function(){if(!this.disabled) return popUpCalendar(this, this, 'MM/dd/yyyy'); };

                break;
            case "PULLDOWN":
                theEditor = document.createElement("SELECT");

                break;
            case "BOOL":
	            theEditor = document.createElement("INPUT");
	            theEditor.type = "checkbox";
                break;
        }

        theEditor.id = self.name + "_editform_" + coldef.cnIndex;
        return theEditor;
    }
    
    self.EditFormHolder = $get(self.name + "_EditFormHolder");
    if(self.EditFormHolder)
    {
        self.EditForm = document.createElement("div");
        for (var j = 0; j < self.colDefs.length; j++) 
        {
            var coldef = self.colDefs[j];
            if(coldef.cnEditType == "DELETE" || coldef.cnEditType == "MULTSEL" || coldef.cnEditType == "CUSTOM" || !coldef.cnInEditForm) continue;

            var theEditor = self.EditFormInput(coldef);
            coldef.cnEditFormInput = theEditor;

            var elDiv = document.createElement("div");
            elDiv.className = (self.topDiv.getAttribute("EditformElCss") ? self.topDiv.getAttribute("EditformElCss") : "def_editform_el_css");
            if(coldef.cnEditType == "TEXTAREA") elDiv.className = (self.topDiv.getAttribute("EditformElTaCss") ? self.topDiv.getAttribute("EditformElTaCss") : "def_editform_elta_css");
            
            self.EditForm.appendChild(elDiv);

            var nameDiv = document.createElement("div");
            nameDiv.className = (self.topDiv.getAttribute("EditformNameCss") ? self.topDiv.getAttribute("EditformNameCss") : "def_editform_name_css");
            nameDiv.innerHTML = coldef.cnTitle;
            elDiv.appendChild(nameDiv);
            
            var valDiv = document.createElement("div");
            valDiv.className = (self.topDiv.getAttribute("EditformValCss") ? self.topDiv.getAttribute("EditformValCss") : "def_editform_val_css");
            valDiv.appendChild(theEditor);
            elDiv.appendChild(valDiv);
        }
        self.EditFormHolder.appendChild(self.EditForm);
    }

    self.ClearEF = function ()
    {
        for (var j = 0; j < self.colDefs.length; j++) 
            if(self.colDefs[j].cnEditFormInput) 
                ClearInput(self.colDefs[j].cnEditFormInput);
    }

    self.ShowEF = function (show)
    {
        show = (show == null ? true : show);
        PopUpShow(self.name + "_Inner", show);
    }
    
    self.DeleteImg = (self.topDiv.getAttribute("DeleteImg") ? self.topDiv.getAttribute("DeleteImg") : "PAT/images/cancel.png");
    self.DeleteGrayImg = (self.topDiv.getAttribute("DeleteGrayImg") ? self.topDiv.getAttribute("DeleteGrayImg") : "PAT/images/cancelGray.PNG");

    self.GetCurrentRowID = function ()
        {
            var id = null;
            if (self.curRow != null)
                id = self.curRow.dbid;
            return id;
        }
    self.HideShowCol = function(n, b) {
        try {
            var col = self.rowPattern.cells[n];
            col.style.display = b ? "" : "none";
            col = self.headRow.cells[n];
            col.style.display = b ? "" : "none";
            for (var i = 0; i < self.tableHolders.length; i++) {
                var tab = self.tableHolders[i].getElementsByTagName("TABLE")[0];
                for (var i = 0; i < tab.rows.length; i++) {
                    col = tab.rows[i].cells[n];
                    col.style.display = b ? "" : "none";
                }
            }
        } catch (e) {
            alert(e);
        }
    }
    self.GetCurRowValueByColumn = function (columnName)
        {
            var res = null;

            if (self.curRow && self.table)
                for(var i=0; i<self.table.rows.length; i++)
                    if(self.table.rows[i][self.DbRowId] == self.curRow.dbid && self.table.rows[i][columnName] != null)
                    {
                        res = self.table.rows[i][columnName];
                        break;
                    }

            return res;
        }

    self.GetDataValue = function (columnName, rowID)
        {
            var res = null;

            if (self && self.table && self.table.rows)
                for (var index =0; index < self.table.rows.length; index++)
                    if (self.table.rows[index][self.DbRowId] == rowID)
                    {
                        res = self.table.rows[index][columnName];
                        break;
                    }

            return res;
        }

    self.OnDataChangeNotification = function (params) 
        { 
            if(params != null && params["act"] == "sre_setdata" && params["rowid"] != null)
                self.RefreshRow(params["rowid"])
            else
                self.LoadData();
        }

    self.OnRowChangeNotification = function (params) 
        { 
            if(params != null && params["rowid"] != null && params["rowidname"] != null)
                self.args = AddHash(self.args, params["rowidname"], params["rowid"]);
		    self.currentPage = 1;
			self.LoadData();
        }

    self.OnServiceRes = function (res)
        {
            switch(res["cmdCode"])
            {
                case "GetSingleRow": self.OnGetSingleRowRes(res); break;
                case "GetPage":      self.OnGetPageRes(res); break;
                case "GetPDTable":   self.OnGetPDTableRes(res); break;
                case "DelRow":       self.OnDelRowRes(res); break;
                case "SetData":      self.OnSetDataRes(res); break;
                case "InsRow":       self.OnInsRowRes(res); break;
            }
        }

    self.RefreshRow = function (rowid) 
        { 
            ServerCall("GetSingleRow", self.name, Hash("rowid", rowid, "args", self.args));
        }

    self.SetCurRow = function (rowid) 
        { 
            if(!rowid) return self.SelectRowByRow(null, null);
            
            var row = self.Row(rowid);
		    if(row) return self.SelectRowByRow(row, null);
            
            self.ClearAllSelection();
            ServerCall("GetPage", self.name, Hash("rowid", rowid, "pagesize", self.RowsCnt, "sort", self.SortNames, "args", self.args)); 
        }

        self.OnGetSingleRowRes = function(res) {
            if (res["errCode"] != null) return OnError(self.name + ": " + res["errCode"]);
            var tabData = res["tableRes"];
            var rowid = res["args"]["rowid"];

            try {
                var fContinue = true;
                if (self.table != null && self.table.rows != null && tabData != null && tabData.rows != null) {
                    for (var newRowIndex = 0; newRowIndex < tabData.rows.length && fContinue; newRowIndex++) {
                        var newRow = tabData.rows[newRowIndex];
                        if (newRow[self.DbRowId] != null) {
                            for (var currRowIndex = 0; currRowIndex < self.table.rows.length && fContinue; currRowIndex++) {
                                var currRow = self.table.rows[currRowIndex];
                                if (newRow[self.DbRowId] == currRow[self.DbRowId]) {
                                    for (var j = 0; j < self.colDefs.length; j++)
                                        if (newRow[self.colDefs[j].cnDBName] != null)
                                        currRow[self.colDefs[j].cnDBName] = newRow[self.colDefs[j].cnDBName];
                                    fContinue = false;
                                }
                            }
                        }
                        else
                            fContinue = false;
                    }
                }
            }
            catch (err) { }

            if (self.onDataArrived != null) try { eval(self.onDataArrived + "(tabData);"); eval(self.onDataArrived + "(self.table);"); } catch (err) { }

            if (tabData == null || tabData.rows == null || tabData.rows.length == 0) return;

            var row = self.Row(rowid);
            for (var j = 0; j < self.colDefs.length; j++) {
                self.setCell(row, self.colDefs[j], tabData.rows[0][self.colDefs[j].cnDBName], tabData.rows[0]);
                if (self.colDefs[j].cnEditType == "PULLDOWN") self.SetPullDownCell(row.cells[j], self.colDefs[j]);
            }
            if (self.onRowLoad != null) try { eval(self.onRowLoad + "(self, row, tabData.rows[0]);"); } catch (err) { }
        }
    
    self.SortOnHeadClick = function (cell, evt) 
        {
            if(!checkTag(cell, "td")) return;
            
            var coldef = self.colDefs[cell.getAttribute("columnIndex")];
                        
            if(self.MultiColumnsSorting == "False")
            {
                for(var k = 0; k < cell.parentNode.cells.length; k++)
                {
                    if(self.colDefs[k].cnSorting != "True" || cell.getAttribute("columnIndex") == k || cell.parentNode.cells[k].childNodes.length == 0) continue;
                    var img = cell.parentNode.cells[k].childNodes[0].childNodes[0].childNodes[0].childNodes[1].childNodes[0];
                    if(checkTag(img, "img"))
                    {
                        img.src = "PAT/images/UpDn.png";
                        img.alt = "no sorting";
                        self.colDefs[k].cnSortDr = "";
                    }
                }
            }

            var sDr = (coldef.cnSortDr == "" ? "asc" : coldef.cnSortDr == "asc" ? "desc" : "");
            coldef.cnSortDr = sDr;
            var img = cell.childNodes[0].childNodes[0].childNodes[0].childNodes[1].childNodes[0];
            if(!checkTag(img, "img")) return;
            img.src = "PAT/images/" + (sDr == "" ? "UpDn.png" : sDr == "asc" ? "Dn.png" : "Up.png");
            img.alt = (sDr == "" ? "sort asc" : sDr == "asc" ? "sort desc" : "no sorting");
            
            
            self.SortNames = "";
            if(self.MultiColumnsSorting == "True")
            {
                var sNames = (self.SortNames != null ? self.SortNames.split(",") : new Array());
                for(var i=0; i<sNames.length; i++)
                    if(sNames[i].substring(0,coldef.cnDBName.length) != coldef.cnDBName)
                        self.SortNames += (self.SortNames == "" ? "" : ",") + sNames[i];
            }
            self.SortNames += (sDr != "" ? (self.SortNames == "" ? "" : ",") + coldef.cnDBName + " " + sDr : "") ;

            self.Sort(self.SortNames);
        }
        
    self.Sort = function (sNames) 
    {
        self.SortNames = sNames;
        self.LoadData(); 
    }

    self.LoadData = function (args) 
        {
            if(args) AddHash(self.args, args);
            ServerCall("GetPage", self.name, Hash("page", self.currentPage, "pagesize", self.RowsCnt, "sort", self.SortNames, "args", self.args));
        }

    self.OnGetPageRes = function (res) 
        {
            if (res["errCode"] != null) return OnError(self.name + ": " + res["errCode"]);
            var tabData = res["tableRes"];
            self.table = tabData;
            self.rowsTotal = res["scalarRes"];
            self.pagesCount = (self.RowsCnt == null || self.RowsCnt == 0 ? 1 : 1 + parseInt((self.rowsTotal - 1) / self.RowsCnt));
            if(self.pagesCount < 1) self.pagesCount = 1;
            if(self.currentPage > self.pagesCount) TableSetCurPage(self.name, self.pagesCount);

            if (self.onDataArrived != null) try { eval(self.onDataArrived + "(tabData);"); } catch(err) {}

            var curRowId, curRowRestored = false;
            if (self.curRow != null)
            {
                curRowId = self.curRow.dbid;
                self.curRow.className = self.RowCss;
                self.curRow = null;
            }
            if(res["args"]["rowid"] != null) 
            {
                curRowId = res["args"]["rowid"];
                if (self.onSelRow) try {eval("" + self.onSelRow + "('" + self.name + "'," + curRowId + ");");} catch(err) {}
            }

            self.currentPage = (res["args"]["page"] == null ? 1 : res["args"]["page"]);

            var len = (tabData != null && tabData.rows != null ? tabData.rows.length : 0);
            for(var i=0; i<len; i++)
                if(tabData.rows[i][self.DbRowId] == "-1")
                {
                    self.insRowDef = tabData.rows[i];
                    Array.removeAt(tabData.rows,i);
                    len--;
                }
            
            if(self.MaxRows != null && self.insRow != null)
                self.insRow.style.display= (self.MaxRows <= len ? "none" : "");

            self.SizeTable(len);

            if (self.insRow != null)
            {
                for (var i=0;i<self.colDefs.length;i++)
                {
                    var cd = self.colDefs[i];
                    var val = cd.cnDefVal == null ? "" : cd.cnDefVal;
                    if(self.insRowDef != null) val = self.insRowDef[cd.cnDBName] == null ? val : self.insRowDef[cd.cnDBName];
                    self.setCell(self.insRow, cd, val, self.insRowDef);
                    if(cd.cnEditType == "PULLDOWN") self.SetPullDownCell( self.insRow.cells[i], cd);
                }    
                       
                AddHandler(self.insRow, "click", self.SelectRowByRow);
                AddHandler(self.insRow, "mouseover", self.onRowMouseOver);
                AddHandler(self.insRow, "mouseout", self.onRowMouseOut);
            }

            for (var i = 0; i < len; i++)
            {
                var row = self.TableRows[i];
                row.dbid = tabData.rows[i][self.DbRowId];
                                
                AddHandler(row, "click", self.SelectRowByRow);
                AddHandler(row, "mouseover", self.onRowMouseOver);
                AddHandler(row, "mouseout", self.onRowMouseOut);

                for (var j = 0; j < self.colDefs.length; j++)
                    self.setCell(row, self.colDefs[j], tabData.rows[i][self.colDefs[j].cnDBName], tabData.rows[i]);

                if (curRowId && row.dbid == curRowId) { self.SelectCurRow(row); curRowRestored = true; }

                self.SelectRow(row.dbid,self.selRowsId[row.dbid]);
                if(self.OddRowBackColor && i%2==0) row.style.backgroundColor = self.OddRowBackColor;
                if (self.onRowLoad != null) try { eval(self.onRowLoad + "(self, row, tabData.rows[i]);"); } catch(err) {}
            }
            
            if(curRowId != null && curRowId != "")
                if(!curRowRestored)
                    RowChangeNotify(self.RowChangeNotifyList, Hash("rowid", "-1", "rowidname", self.DbRowId));
                else if(res["args"]["rowid"] != null) // row was setted
                    RowChangeNotify(self.RowChangeNotifyList, Hash("rowid", curRowId, "rowidname", self.DbRowId));

            for (var i = 0; i < self.colDefs.length; i++)
            {
                if(self.colDefs[i].cnEditType != "PULLDOWN") continue;
                if (self.colDefs[i].cnRelTableName != null)// && typeof (self.colDefs[i].cnRelTableName) != "undefined")
                    ServerCall("GetPDTable", self.name, Hash("pdName", self.colDefs[i].cnRelTableName, "args", self.args, "columnIndex", i));
                else
                    self.OnGetPDTableRes(Hash("args", Hash("pdName", null, "columnIndex", i)));
            }
            
            if(self.LockedBody) self.LockTable(self.LockedBody, self.LockedInsR);
            if (self.onTableLoad != null) try { eval(self.onTableLoad + "(self, tabData);"); } catch(err) {}
            if (self.onRowSelected) try {eval("" + self.onRowSelected + "('" + self.name + "'," + (self.curRow ? "\"" + self.curRow.dbid + "\"" : "''") + ");");} catch(err) {}
        }


        self.OnGetPDTableRes = function(res) {
            if (res["errCode"] != null) return OnError(self.name + ": " + res["errCode"]);
            var dataRes = res["tableRes"];
            var columnIndex = res["args"]["columnIndex"];
            var pdName = res["args"]["pdName"];

            var coldef = self.colDefs[columnIndex];
            coldef.cnRelNames = (coldef.cnRelNamesStr != null ? coldef.cnRelNamesStr.split(",") : new Array());
            coldef.cnRelValues = (coldef.cnRelValuesStr != null ? coldef.cnRelValuesStr.split(",") : new Array());
            coldef.cnRelColors = (coldef.cnRelColorsStr != null ? coldef.cnRelColorsStr.split(",") : new Array());
            coldef.cnShowInPD = new Array();
            if (dataRes && dataRes.rows && dataRes.rows.length) {
                for (var i = 0; i < dataRes.rows.length; i++) {
                    var len = coldef.cnRelNames.length != null ? coldef.cnRelNames.length : 0;
                    coldef.cnRelNames[len] = dataRes.rows[i][dataRes.columns[1].name];
                    coldef.cnRelValues[len] = dataRes.rows[i][dataRes.columns[0].name];
                    if (coldef.cnRelBackColor != null) coldef.cnRelColors[len] = dataRes.rows[i][coldef.cnRelBackColor];
                    if (coldef.cnRelShowInPD != null) coldef.cnShowInPD[len] = dataRes.rows[i][coldef.cnRelShowInPD];
                }
            }

            if (self.insRow) self.SetPullDownCell(self.insRow.cells[columnIndex], self.colDefs[columnIndex]);
            if (coldef.cnEditFormInput) self.SetPullDownOptions(coldef, coldef.cnEditFormInput, null);
            for (var i = 0; i < self.TableRows.length; i++)
                self.SetPullDownCell(self.TableRows[i].cells[columnIndex], self.colDefs[columnIndex]);
        }

        self.SetPullDownOptions = function(coldef, theEditor, row) 
        {
            if(coldef.cnRelNames != null && coldef.cnRelNames.length != null && coldef.cnRelValues != null && coldef.cnRelValues.length == coldef.cnRelNames.length && theEditor.innerHTML == "")
                for (var i=0; i < coldef.cnRelNames.length; i++)
                {
                    if(coldef.cnShowInPD != null && coldef.cnShowInPD.length == coldef.cnRelNames.length && !coldef.cnShowInPD[i] && (row == null || coldef.cnValues[row.dbid] != coldef.cnRelValues[i]))
                            continue;
                    var el = new Option(coldef.cnRelNames[i], coldef.cnRelValues[i]);
                    theEditor.options.add(el);
                    if (coldef.cnRelBackColor != null && coldef.cnRelColors != null && coldef.cnRelColors.length == coldef.cnRelNames.length)
                            el.style.backgroundColor = coldef.cnRelColors[i];
                }
        }

        self.SetPullDownCell = function(cell, coldef) {
            var val = null; 
            try{
            val = coldef.cnValues[cell.parentNode.dbid];
            }
            catch(ex){};
            if (coldef.cnRelNames != null && coldef.cnRelNames.length != null && coldef.cnRelValues != null && coldef.cnRelValues.length == coldef.cnRelNames.length)
                for (var i = 0; i < coldef.cnRelNames.length; i++)
                if (coldef.cnRelValues[i] == val || (coldef.cnRelValues[i] == null && val == "null")) {
                cell.innerHTML = "<div class='def_valuediv_css " + (cell.getAttribute("pat_readonlyObj") == "True" ? self.ReadonlyCss : "") + "' onselectstart='return false;'>" + self.FormatValue(coldef.cnRelNames[i], coldef) + "</div>"
                if(self.theEditor) self.theEditor = null;
                if (coldef.cnRelColors != null) {
                    cell.style.backgroundColor = coldef.cnRelColors[i];
                    cell.style.color = self.CalcTxtColor(coldef.cnRelColors[i]);
                }
                return;
            }
            cell.innerHTML = "<div></div>"
        }

        self.SizeTable = function(datarows) {
            var row, cell;
            while (self.TableRows.length > datarows)  //TODO
            {
                var r = self.TableRows.pop();
                var p = r.parentNode;
                p.removeChild(r);
                if (p.childNodes.length == (self.insRow == null ? 1 : 2)) p.parentNode.parentNode.removeChild(p.parentNode);
            }

            var insrowRendered = false;
            while (self.TableRows.length < datarows || datarows == 0) //TODO
            {
                var body;
                if ((self.PageSize == null && self.TableRows.length == 0) || self.TableRows.length % self.PageSize == 0) {
                    var page = (self.PageSize == null ? 0 : Math.round((self.TableRows.length - 1) / self.PageSize));
                    var t = self.tabPattern.cloneNode(false);
                    t.id = t.id + "_" + page;
                    t.style.display = "";
                    body = document.createElement("TBODY");
                    t.appendChild(body);
                    var head = self.headRow.cloneNode(true);
                    head.id = head.id + "_" + page;
                    body.appendChild(head);

                    for (var k = 0; k < head.cells.length; k++)
                    {
                        if(self.colDefs[k].cnEditType == "DELETE" && self.PopUpInsert)
                        {
                            head.cells[k].style.cursor = "pointer";
                            AddHandler(head.cells[k], "click", self.ShowEF);
                            head.cells[k].innerHTML = "<img src='" + self.InsertImg + "' alt='" + self.PopUpInsertCaption + "' title='" + self.PopUpInsertCaption + "' />";
                        }
                        if (self.colDefs[k].cnSorting) 
                        {
                            AddHandler(head.cells[k], "click", self.SortOnHeadClick);
                            head.cells[k].innerHTML = "<table class='def_sorttable_css'><tr><td>" + head.cells[k].innerHTML + "</td><td><img src='PAT/images/UpDn.png' alt='sort' /></td></tr></table>";
                        }
                    }

                    if (self.insRow != null && self.TableRows.length == 0 && !insrowRendered) 
                    {
                        insrowRendered = true;
                        body.appendChild(self.insRow);

                        if(self.insRowHolder)
                        {
                            self.insRowHolder.innerHTML = "";
                            self.insRowHolder.appendChild(t);
                            continue;
                         }
                    }

                    self.tableHolders[page].innerHTML = "";
                    self.tableHolders[page].appendChild(t);
                }
                else
                    body = self.TableRows[self.TableRows.length - 1].parentNode;

                if (datarows == 0) break;
                var row = self.rowPattern.cloneNode(true);
                body.appendChild(row);
                self.TableRows.push(row);
            }

            //  Add pager control
            if (self.topPager || self.botPager) {
                var pagerCode = self.RenderPager(1);
                if (self.topPager && self.TopPagerCss) self.topPager.className = self.TopPagerCss;
                if (self.botPager && self.BotPagerCss) self.botPager.className = self.BotPagerCss;
                if (self.topPager) { self.topPager.innerHTML = pagerCode; self.topPager.style.display = (pagerCode == "" ? "none" : ""); }
                if (self.botPager) { self.botPager.innerHTML = pagerCode; self.botPager.style.display = (pagerCode == "" ? "none" : ""); }
            }

            if (self.rowsPP) {
                self.rowsPP.innerHTML = "rows/pp: <input style=\"width:30px;height:13px;font-size:11px;\" type=\"text\" value=\"" + self.PageSize + "\" onblur=\"javascript:TableSetRowsPerPage('" + self.name + "', this.value);\" onkeypress=\"javascript:if((window.event || event).keyCode == ENTER_KEY_CODE){TableSetRowsPerPage('" + self.name + "', this.value); return false;}\" />";
                self.rowsPP.className = (self.topDiv.getAttribute("RowsPPCss") ? self.topDiv.getAttribute("RowsPPCss") : "def_rowspp_css");
            }

            if (self.gotoPage) {
                self.gotoPage.innerHTML = (self.pagesCount > 1 ? "go to: <input style=\"width:30px;height:13px;font-size:11px;\" type=\"text\" value=\"" + self.currentPage + "\" onkeypress=\"javascript:if((window.event || event).keyCode == ENTER_KEY_CODE){TableSetCurPage('" + self.name + "', this.value); return false;}\" onblur=\"javascript:TableSetCurPage('" + self.name + "', this.value);\" />" : "");
                self.gotoPage.className = (self.topDiv.getAttribute("GoToPageCss") ? self.topDiv.getAttribute("GoToPageCss") : "def_gotopage_css");
            }

            if (self.rowsCnt) {
                self.rowsCnt.innerHTML = "total: " + self.rowsTotal;
                self.rowsCnt.className = (self.topDiv.getAttribute("RowsCntCss") ? self.topDiv.getAttribute("RowsCntCss") : "def_rowscnt_css");
            }
        }

    self.addEditEvent = function (row, coldef, add)
        {
            var cell = row.cells[coldef.cnIndex];
            RmvHandler(cell, "click", self.DoEdit);
            cell.style.cursor = "";
            if(add && coldef.cnEditType == "BOOL")
                disableCtrl(cell.firstChild, cell.getAttribute("pat_readonlyObj") == "True" ? true : false);
            if(add && (row == self.curRow || self.OneClickEdit) && coldef.cnEditType != "BOOL" && coldef.cnEditType != "DELETE" && coldef.cnEditType != "CUSTOM" && coldef.cnEditType != "MULTSEL" && coldef.cnEditType != "READONLY" && (row.dbid == "-1" && !self.LockedInsR || row.dbid != "-1" && !self.LockedBody) && cell.getAttribute("pat_readonlyObj") != "True" )
            {
                AddHandler(cell, "click", self.DoEdit);
                cell.style.cursor = "text";
            }
        }

    self.setCell = function (row, coldef, val, DataRow)
        {
            if(row == null) return;
            
            var cell = row.cells[coldef.cnIndex];
            var isIns = (row.dbid == "-1");
            coldef.cnValues[row.dbid] = val;
            
            var ReadonlyByVal = (row.dbid != "-1" && self.ReadOnly == "True") || coldef.cnReadonly == "True" || (self.ReadonlyBy && self.ReadonlyBy !="" && DataRow && DataRow[self.ReadonlyBy] == 1) || (coldef.cnReadonlyBy && coldef.cnReadonlyBy !="" && DataRow && DataRow[coldef.cnReadonlyBy] == 1);
            cell.setAttribute("pat_readonlyObj", ReadonlyByVal ? "True" : "False");

            if(val == null) val = (coldef.cnEditType == "PULLDOWN" ? "null" : "");

            if(self.RowTip && DataRow && DataRow[self.RowTip]) row.setAttribute("title", DataRow[self.RowTip]); else  row.setAttribute("title", "");
            if(self.RowBackColor && DataRow && DataRow[self.RowBackColor]) row.style.backgroundColor = DataRow[self.RowBackColor]; else row.style.backgroundColor = "";
            if(coldef.cnTip && DataRow && DataRow[coldef.cnTip]) cell.setAttribute("title", DataRow[coldef.cnTip]); 
            else if(coldef.cnTip) cell.setAttribute("title", coldef.cnTip); else cell.setAttribute("title", ""); 
            
	        switch (coldef.cnEditType)
            {
                case "BOOL":
                    var chk = cell.firstChild;
                    if(chk == null)
                    {
			            chk = document.createElement("INPUT");
			            chk.type = "checkbox";
			            cell.appendChild(chk);
                        AddHandler(chk, "click", self.DoEditChk);
                        AddHandler(cell.childNodes[0], "keydown", self.TextKeyEvent);
                    }
                    chk.checked = val;
                    disableCtrl(chk, cell.getAttribute("pat_readonlyObj") == "True" ? true : false);
                    break;
                case "TEXT":
                case "READONLY":
                case "DATETIME":
                case "TEXTAREA":
                    cell.innerHTML = "<div class='def_valuediv_css' onselectstart='return false;'>" + self.FormatValue(val, coldef) + "</div>";
                    if(coldef.cnEditType == "TEXTAREA") cell.style.whiteSpace = "normal";
					if (coldef.cnSpellCheck && (typeof(PNWSpeller) != "undefined") && (PNWSpeller != null))
						SpellDecorate(cell, "en", self.simulateEndEdit, coldef.cnNoGrammarCheck);
                    break;
                case "MONEY":
                    cell.innerHTML = "<div class='def_valuediv_css' onselectstart='return false;'> $ " + FormatMoney(val) + "</div>";
                    break;
                case "HTML":
                    cell.innerHTML = "<div class='def_valuediv_css' onselectstart='return false;'>" + val + "</div>";
                    break    
                case "DELETE":
                    if(!isIns && self.DeleteMode != "False")
                        if(ReadonlyByVal)
                            cell.innerHTML = "<img title='Delete Row' alt='Delete Row' src='" + self.DeleteGrayImg + "' style='border: 0' />";
                        else
                            cell.innerHTML = "<img title='Delete Row' alt='Delete Row' src='" + self.DeleteImg + "' style='border: 0' onclick=\"if(this.getAttribute('disabled') != 'disabled'){ TableDelRow('" + self.name + "', '" + row.dbid + "', '" + self.delConfirm + "'); event.cancelBubble = true;}\" />";
                    break;
                case "CUSTOM":
                    if(coldef.cnCellTemplFnc)
                        eval(coldef.cnCellTemplFnc + "(self, row, coldef, cell, val)");
                    else
                        cell.innerHTML = coldef.cnCellTemplIH;
                    break;
                case "MULTSEL":
                    var chk = cell.firstChild;
                    if(chk == null)
                    {
			            chk = document.createElement("INPUT");
			            chk.type = "checkbox";
			            cell.appendChild(chk);
                        AddHandler(chk, "click", self.SelectRowOnCheck);
                    }
                    break;
            }
            if(self.headRow.cells[coldef.cnIndex].style.width != null && self.headRow.cells[coldef.cnIndex].style.width != "" && cell.firstChild && cell.firstChild.tagName && cell.firstChild.tagName.toUpperCase() == "DIV")
                cell.firstChild.style.width = self.headRow.cells[coldef.cnIndex].style.width;

            if(cell.firstChild && cell.firstChild.tagName && cell.firstChild.tagName.toUpperCase() == "DIV" && coldef.cnWordWrap == "True")
                cell.firstChild.className = cell.firstChild.className + " def_valuedivWW_css";
            
            if(cell.firstChild && cell.firstChild.tagName && cell.firstChild.tagName.toUpperCase() == "DIV" && cell.getAttribute("pat_readonlyObj") == "True")
                cell.firstChild.className = cell.firstChild.className + " " + self.ReadonlyCss;

            cell.style.backgroundColor = "";
            if(coldef.cnGetSellColorFnct != null) try { cell.style.backgroundColor = eval("" + coldef.cnGetSellColorFnct + "('" + val + "');"); } catch(err) {}
            cell.className = coldef.cnCellCss;

            if(DataRow != null && coldef.cnBackColor != null && DataRow[coldef.cnBackColor] != null)
            {
                cell.style.backgroundColor = DataRow[coldef.cnBackColor];
                cell.style.color = self.CalcTxtColor(DataRow[coldef.cnBackColor]);
            }
            
            if(self.OneClickEdit) self.addEditEvent(row, coldef, true)
        }

    self.SelectRowOnCheck = function (chk, evt)
        {
            if(!checkTag(chk, "input")) return;
            self.SelectRow(chk.parentNode.parentNode.dbid,chk.checked);
            if(chk.parentNode.parentNode == self.curRow && !chk.checked) self.UnselectCurRow();
            CancelBubbling(evt);
        }

    self.CalcTxtColor = function (backColor) 
        {            
            if(!backColor || backColor.length != 7) return "#000000";
            var res = "#";
            for(var i=1; i<7; i++)
            {
                var l = backColor.substring(i,i+1);
                res += (isNaN(l) || l>8 ? "0" : "F");
            }
            return res;
        }

    self.DelRow = function (row, confirm) 
        {             
            var allowDel = true;
            if(self.onBeforeDelRow != null) allowDel = eval(self.onBeforeDelRow+"(row)");
            if (allowDel == true && (confirm == "" || window.confirm(confirm))) ServerCall("DelRow", self.name, Hash("rowid", row, "args", self.args));
	        if(self.onDelRow != null) eval(self.onDelRow + "(row)");
        }

    self.OnDelRowRes = function (res)
        {
            if (res["errCode"] != null) return OnError(self.name + ": " + res["errCode"]);
            self.LoadData(); 
            DataChangeNotify(self.DataChangeNotifyList, Hash("act", "table_delrow", "rowid", res["args"]["rowid"]));
        }

    self.EndEdit_ = function (inp, evt)
        {
            self.EndEdit(inp, null, null);
        }

	self.simulateEndEdit = function(ctrl, val)
	{
		self.EndEdit(ctrl, val, true);
	}

    self.EndEdit = function (oc, newValue, skipSpell)
        {
            while(oc != null && oc.tagName.toUpperCase() != "TD") oc = oc.parentNode;
            if (oc == null || !self.theEditor) return;

            var row = oc.parentNode;
            var val;
            var coldef = self.colDefs[oc.getAttribute("columnIndex")];
            
            switch (coldef.cnEditType)
            {
                case "MONEY":
					if (newValue != null)
						val = newValue;
					else
						val = self.theEditor.value;

                    if (!self.isValid(coldef, val)) return self.cancelEdit();
                    oc.firstChild.innerHTML = " $ " + FormatMoney(val);
                    break;
                case "TEXT":
                case "TEXTAREA":
                case "HTML":
					if (newValue != null)
						val = newValue;
					else
						val = self.theEditor.value;

                    if (!self.isValid(coldef, val)) return self.cancelEdit();
                    oc.firstChild.innerHTML = self.FormatValue(val, coldef);
                    break;
                case "DATETIME":
                    if(self.theEditor.firstChild.firstChild.firstChild.firstChild.firstChild)
                        val = self.theEditor.firstChild.firstChild.firstChild.firstChild.firstChild.value;
                    else
                        val = self.theEditor.firstChild.firstChild.firstChild.firstChild.value;
                    if (!self.isValid(coldef, val)) return self.cancelEdit();
                    oc.firstChild.innerHTML = self.FormatValue(val, coldef);
                    hideCalendar();
                    break;
                case "PULLDOWN":
                    val = self.theEditor.value;
                    if(val == "null") val = null;
                    if (!self.isValid(coldef, val)) return self.cancelEdit();
                    if(self.theEditor.selectedIndex > -1) oc.style.backgroundColor = self.theEditor.options[self.theEditor.selectedIndex].style.backgroundColor;
                    break;
                case "BOOL":
                    break;
            }
            var oldVal = "" + coldef.cnValues[row.dbid];
            val = "" + val;
            var changed = (oldVal.replace(/\r\n/g,"<BR>").replace(/\n/g,"<BR>").replace(/\r/g,"<BR>") != val.replace(/\r\n/g,"<BR>").replace(/\n/g,"<BR>").replace(/\r/g,"<BR>"));
            var oldval = coldef.cnValues[row.dbid];
            coldef.cnValues[row.dbid] = val;
            if (row.dbid != "-1" && changed)
            {
                var colName = (typeof(oc.dbfield) != 'undefined') ? oc.dbfield: coldef.cnDBName;

                if(self.endEdit == null || self.endEdit == "")
                    ServerCall("SetData", self.name, Hash("rowid", row.dbid, "field", colName, "value", val, "oldval", oldval, "args", self.args));
                else
    	            eval(self.endEdit + "(self.name, row.dbid, colName, val, row, self.args)");

                if(self.onEndEdit != null && self.onEndEdit != "") eval(self.onEndEdit + "(self.name, row.dbid, colName, val, row, self.args)");
            }
            
            if(coldef.cnEditType == "PULLDOWN") 
                self.SetPullDownCell(oc,coldef);
            else
                self.SwitchTableEditToView();
            
	        if (!skipSpell && coldef.cnSpellCheck && (typeof(PNWSpeller) != "undefined") && (PNWSpeller != null))
				SpellDecorate(oc, "en", self.simulateEndEdit, coldef.cnNoGrammarCheck);
        }
        
        self.SwitchTableEditToView = function()
        {
            if(self.theEditor == null) return;
            AutoCompleteDel(self.theEditor.id); // if it was AutoComplete all attached events will be deleted
            var edt = self.theEditor;
            while(edt.parentNode != null && edt.parentNode.tagName.toUpperCase() != "TD") edt = edt.parentNode;
            if(edt.parentNode == null || edt.parentNode.firstChild == null || edt.parentNode.firstChild.tagName.toUpperCase() != "DIV") return OnError("Wrong table html.");
            edt.style.display = "none";
            edt.parentNode.firstChild.style.display = "";
            window.setTimeout(function(){if(edt && edt.parentNode) edt.parentNode.removeChild(edt);}, 1); 
            self.theEditor = null;
        }

        self.OnSetDataRes = function(res) {
            var rowid = res["args"]["rowid"];
            var field = res["args"]["field"];
            var value = res["args"]["value"];
            var oldval = res["args"]["oldval"];
            var scalarRes = res["scalarRes"];

            if (self.RefreshRowOnChange == "True") self.RefreshRow(rowid);

            for (var j = 0; j < self.colDefs.length && self.colDefs[j].cnDBName != field; j++);
            if (res["errCode"] != null) {
                var row = self.Row(rowid);

                self.setCell(row, self.colDefs[j], oldval, null);
                if (self.colDefs[j].cnEditType == "PULLDOWN") self.SetPullDownCell(row.cells[j], self.colDefs[j]);
                return OnError(self.name + ": " + res["errCode"]);
            } else {
                if (self.colDefs[j].RefreshTableOnChange == "True") self.LoadData();
            }

            DataChangeNotify(self.DataChangeNotifyList, Hash("act", "table_setdata", "rowid", rowid));
            if (self.onTableSet != null) eval(self.onTableSet + "(self, rowid, field, value, scalarRes)");
        }

    self.DoEditChk = function (chk, evt)
        {
            if(!checkTag(chk, "input")) return;
            self.DoEdit(chk.parentNode,  evt);
        }

    self.DoEdit = function (cell, evt)
        {
            if((evt !=null && evt.ctrlKey) || !checkTag(cell, "td") || cell.firstChild == null || cell.firstChild.style == null || cell.firstChild.style.display.toUpperCase() == "NONE") return;
            var row = cell.parentNode;

            if(self.theEditor) self.SwitchTableEditToView();
            var coldef = self.colDefs[cell.getAttribute("columnIndex")];
	        switch(coldef.cnEditType)
            {
                case "TEXT":
                    var EditSpan = document.createElement("span");
                    EditSpan.id = "TableEditObj";

                    cell.firstChild.style.display = "none";
                    cell.appendChild(EditSpan);

                    self.theEditor = document.createElement("INPUT");
                    self.theEditor.type = "text";
                    self.theEditor.style.width = (cell.offsetWidth - 17).toString() + "px";
                    self.theEditor.style.height = (cell.offsetHeight - 10).toString()  + "px";
                    self.theEditor.id = "TableEdit";
                    EditSpan.appendChild(self.theEditor);

                    self.theEditor.value = coldef.cnValues[row.dbid] == null ? "" : coldef.cnValues[row.dbid];
                    
                    if(coldef.cnRelTableName) 
                    {
                        self.theEditor.setAttribute("autocomplete","off");

                        self.theEditor.setAttribute("cnRelTableName", coldef.cnRelTableName);
                        if(coldef.cnRelColors)    self.theEditor.setAttribute("cnRelColors",    coldef.cnRelColors);
                        if(coldef.cnRelNames)     self.theEditor.setAttribute("cnRelNames",     coldef.cnRelNames);
                        if(coldef.cnRelBackColor) self.theEditor.setAttribute("cnRelBackColor", coldef.cnRelBackColor);
                        if(coldef.cnMaxOpts)      self.theEditor.setAttribute("cnMaxOpts",      coldef.cnMaxOpts);
                        if(coldef.cnColumn)       self.theEditor.setAttribute("cnColumn",       coldef.cnColumn);
                        if(coldef.divW)           self.theEditor.setAttribute("divW",           coldef.divW);
                        if(coldef.divH)           self.theEditor.setAttribute("divH",           coldef.divH);

                        self.theEditor.setAttribute("onHide", "TableEndEdit('" + self.name + "')");
                        
                        window.setTimeout(function(){if(self.theEditor)AutoCompleteInit(self.theEditor.id);}, 5);
                    }
                    else
                    {
                        AddHandler(self.theEditor, "blur", self.EndEdit_);
                    }
                    self.theEditor.focus();
                    AddHandler(self.theEditor, "keydown", self.TextKeyEvent);
                    break;
                case "MONEY":
                    self.theEditor = document.createElement("INPUT");
                    self.theEditor.type = "text";
                    self.theEditor.style.width = (cell.offsetWidth - 17).toString() + "px";
                    self.theEditor.style.height = (cell.offsetHeight - 10).toString()  + "px";
                    self.theEditor.id = "TableEdit";

                    AddHandler(self.theEditor, "keydown", self.TextKeyEvent);
                    AddHandler(self.theEditor, "blur", self.EndEdit_);
                    self.theEditor.onkeydown = function(evt){return ImpEventMoneyFormatCheck(this, (evt ? evt : window.event)); };

                    cell.firstChild.style.display = "none";
                    cell.appendChild(self.theEditor);

                    self.theEditor.value = FormatMoney(coldef.cnValues[row.dbid]);
                    self.theEditor.focus();
                    break;
                case "TEXTAREA":
                case "HTML":
                    self.theEditor = document.createElement("textarea");
                    self.theEditor.style.width = (cell.offsetWidth - 17).toString() + "px";
                    self.theEditor.style.height = (cell.offsetHeight - 9).toString()  + "px";
                    self.theEditor.className = self.TextAreaCss;
                    self.theEditor.id = "TableTextArea";

                    AddHandler(self.theEditor, "keydown", self.TextKeyEvent);
                    AddHandler(self.theEditor, "blur", self.EndEdit_);

                    self.theEditor.value = coldef.cnValues[row.dbid];
                    cell.firstChild.style.display = "none";
                    cell.appendChild(self.theEditor);
                    self.theEditor.focus();
                    break;
                case "DATETIME":
                    self.theEditor = document.createElement("span");
                    self.theEditor.id = "ClndObj";

                    AddHandler(self.theEditor, "keydown", self.TextKeyEvent);
                    //AddHandler(self.theEditor, "blur", self.EndEdit_);

                    cell.firstChild.style.display = "none";
                    cell.appendChild(self.theEditor);
                    //ClndInit(self.theEditor.id, coldef.cnValues[row.dbid]);
                    //CreateCalendar(placeHolder, value, inpCss, onEndEditFunction, showbtn, opened)
                    CreateCalendar(self.theEditor, coldef.cnValues[row.dbid], "CalendarImp", self.EndEdit, false, true);
                    self.theEditor.focus();
                    break;
                case "PULLDOWN":
                    self.theEditor = document.createElement("SELECT");
                    self.theEditor.style.width = (cell.offsetWidth - 12).toString() + "px";
                    self.theEditor.style.height = (cell.offsetHeight - 2).toString()  + "px";

                    self.theEditor.id = "TablePullDown";

                    self.SetPullDownOptions(coldef, self.theEditor, row);

                    AddHandler(self.theEditor, "keydown", self.TextKeyEvent);
                    AddHandler(self.theEditor, "change", self.EndEdit_);
                    AddHandler(self.theEditor, "blur", self.EndEdit_);

                    cell.firstChild.style.display = "none";
                    cell.appendChild(self.theEditor);
                    self.theEditor.value = coldef.cnValues[row.dbid];
                    self.theEditor.focus();
                    break;
                case "BOOL":
                    coldef.cnValues[row.dbid] = cell.childNodes[0].checked;
                    if (row.dbid != "-1")
                    {
	                    if(self.endEdit == null || self.endEdit == "")
                            ServerCall("SetData", self.name, Hash("rowid", row.dbid, "field", coldef.cnDBName, "value", cell.childNodes[0].checked, "oldval", !cell.childNodes[0].checked, "args", self.args));
                        else
	                        eval(self.endEdit + "(self.name, row.dbid, coldef.cnDBName, val, row, self.args)");
                        if(self.onEndEdit != null && self.onEndEdit != "") eval(self.onEndEdit + "(self.name, row.dbid, coldef.cnDBName, cell.childNodes[0].checked, row, self.args)");
	                }
                    break;
            }
        }

    self.SelectRowByRow = function (row, evt)
        {
            if(!row) {self.UnselectCurRow(); return;}
            if(!checkTag(row, "tr")) return;
            
            if(evt && evt.ctrlKey && self.multSel)
            {
                if(row == self.curRow)
                {
                    self.UnselectCurRow();
                    if (self.onSelRow) try {eval("" + self.onSelRow + "('" + self.name + "'," + (self.curRow ? "\"" + self.curRow.dbid + "\"" : "''") + ");");} catch(err) {}
                    RowChangeNotify(self.RowChangeNotifyList, Hash("rowid", -1, "rowidname", self.DbRowId));
					if (self.onRowSelected) try {eval("" + self.onRowSelected + "('" + self.name + "'," + (self.curRow ? "\"" + self.curRow.dbid + "\"" : "''") + ");");} catch(err) {}
                }
                else
                    self.SelectRow(row.dbid,self.selRowsId[row.dbid] != true);

                return;
            }
            else if(evt && evt.shiftKey && self.multSel && self.curRow)
            {
                var go = false;
                for (var i = 0; i < self.TableRows.length; i++)
                {
		            if(self.TableRows[i] == self.curRow || self.TableRows[i] == row) go = !go;
		            if(go || self.TableRows[i] == self.curRow || self.TableRows[i] == row)
                        self.SelectRow(self.TableRows[i].dbid,true);
		        }
                return;
            }
            
            if(self.onNewRow) try {eval("" + self.onNewRow + "('" + self.name + "'," + (row ? row.dbid : "''") + ");");} catch(err) {}
            if(row == self.curRow) return;

            self.ClearAllSelection();
            self.SelectCurRow(row);
            
            if (self.onSelRow) try {eval("" + self.onSelRow + "('" + self.name + "'," + (self.curRow ? "\"" + self.curRow.dbid + "\"" : "''") + ");");}catch(err){}
            RowChangeNotify(self.RowChangeNotifyList, self.curRow ? Hash("rowid", self.curRow.dbid, "rowidname", self.DbRowId) : null);
            if (self.onRowSelected) try {eval("" + self.onRowSelected + "('" + self.name + "'," + (self.curRow ? "\"" + self.curRow.dbid + "\"" : "''") + ");");}catch(err){}
            
        }

    self.Row = function (id)
    {
        for (var i = 0; i < self.TableRows.length; i++)
	        if(self.TableRows[i].dbid == id)
	            return self.TableRows[i];
	    if(id == "-1") return self.insRow;
        return null;
	}

    self.SelectAllRows = function ()
    {
        for (var i = 0; i < self.TableRows.length; i++)
            self.SelectRow(self.TableRows[i].dbid, true);
    }

    self.SelectRow = function (id, sel)
    {
        var row = self.Row(id);
        
        if(sel)
            self.selRowsId[id] = true;
        else
            delete self.selRowsId[id];

        if(row)row.className = (sel ? self.SelRowCss : self.RowCss);
        for (var j = 0; j < self.colDefs.length; j++)
            if(row && self.colDefs[j].cnEditType == "MULTSEL" && row.cells[j].firstChild) row.cells[j].firstChild.checked = sel;
        if (self.onSelRowsChanged) try {eval("" + self.onSelRowsChanged + "(self, self.selRowsId, id, sel);");}catch(err){}
    }

    self.SelectCurRow = function (row)
    {
        self.curRow = row;
        self.SelectRow(row.dbid,true);
        if (!self.OneClickEdit && self.curRow) 
            for (var j = 0; j < self.colDefs.length; j++) self.addEditEvent(self.curRow, self.colDefs[j], true);
    }

    self.UnselectCurRow = function ()
    {
        if(!self.curRow) return;
        for (var j = 0; j < self.colDefs.length; j++)
        {
			if(!self.OneClickEdit) self.addEditEvent(self.curRow, self.colDefs[j], false);
			if (self.colDefs[j].cnSpellCheck && (typeof(PNWSpeller) != "undefined") && (PNWSpeller != null))
			{
				var td = self.curRow.cells[self.colDefs[j].cnIndex];
				if ((typeof(td.decorator) == "undefined") || (td.decorator == null) || !td.decorator.stuffed)
					SpellDecorate(td, "en", self.simulateEndEdit, self.colDefs[j].cnNoGrammarCheck);
			}
		}
        self.curRow = null;
        if (self.onRowSelected) try {eval("" + self.onRowSelected + "('" + self.name + "'," + (self.curRow ? "\"" + self.curRow.dbid + "\"" : "''") + ");");}catch(err){}
    }

    self.ClearAllSelection = function ()
    {
        for (var id in self.selRowsId) 
        {
            self.SelectRow(id, false);
            delete self.selRowsId[id];
        }
        self.UnselectCurRow();
    }

    self.LockTable = function(disable, disableIns) {
        if (disable == null) disable = true;
        if (disableIns == null) disableIns = disable;
        self.LockedBody = disable;
        self.LockedInsR = disableIns;
        
        self.LockRow(self.insRow, disableIns);

        if (!self.TableRows) return;

        for (var i = 0; i < self.TableRows.length; i++)
            self.LockRow(self.TableRows[i], disable);
    }

    self.LockRow = function(row, lock) 
    {
        if (!row) return;
        for (var j = 0; j < self.colDefs.length; j++) {
            var coldef = self.colDefs[j];

            disableCtrl(row.cells[coldef.cnIndex], lock);
            self.addEditEvent(row, coldef, !lock);
        }
    }
    
    self.InsertRow = function() {
        if (self.addRow) return eval(self.addRow + "(self.name, self.insRow)");

        var n = new Array(self.colDefs.lenght);
        var o = new Array(self.colDefs.lenght);
        var ln = 0;
        for (var i = 0; i < self.colDefs.length; i++) {
            var coldef = self.colDefs[i];
            if (coldef.cnDBName == null || coldef.cnDBName == "") continue;
            switch (coldef.cnEditType) {
                case "TEXT": case "TEXTAREA": case "BOOL": case "MONEY": case "HTML": case "PULLDOWN": case "DATETIME":
                    o[ln] = (self.insRow == null ? coldef.cnDefVal : coldef.cnValues["-1"]);
                    n[ln++] = coldef.cnDBName;
                    break;
                case "CUSTOM":
                    if (coldef.cnCustomValue == "" || self.insRow.cells[coldef.cnIndex].getAttribute("pat_readonlyObj") == "True") break;
                    o[ln] = self.insRow[coldef.cnCustomValue];
                    n[ln++] = coldef.cnDBName;
                    break;
            }
            if (!self.isValid(coldef, o[ln - 1])) return;
        }

        ServerCall("InsRow", self.name, Hash("insNames", n, "insArgs", o, "args", self.args));

        if (self.onAddRow != null) eval(self.onAddRow + "(tabname, self.insRow)");
    }
    
    self.InsertRowEF = function() {
        if (self.addRow) return eval(self.addRow + "(self.name, self.insRow)");

        var n = new Array(self.colDefs.lenght);
        var o = new Array(self.colDefs.lenght);
        var ln = 0;
        for (var i = 0; i < self.colDefs.length; i++) {
            var coldef = self.colDefs[i];
            var imp = coldef.cnEditFormInput;
            if (coldef.cnDBName == null || coldef.cnDBName == "") continue;

            switch (coldef.cnEditType) {
                case "TEXT": case "TEXTAREA": case "MONEY": case "HTML": case "PULLDOWN":
                    o[ln] = (imp == null ? coldef.cnDefVal : imp.value);
                    n[ln++] = coldef.cnDBName;
                    break;
                case "BOOL":
                    o[ln] = (imp == null ? coldef.cnDefVal : imp.checked);
                    n[ln++] = coldef.cnDBName;
                    break;
                case "DATETIME":
                    o[ln] = (imp == null ? coldef.cnDefVal : imp.value);// (imp.firstChild.firstChild.firstChild.firstChild.firstChild ? imp.firstChild.firstChild.firstChild.firstChild.firstChild.value : imp.firstChild.firstChild.firstChild.firstChild.value));
                    n[ln++] = coldef.cnDBName;
                    break;
                case "CUSTOM":
                    break;
            }
            if (!self.isValid(coldef, o[ln - 1])) return;
        }

        ServerCall("InsRow", self.name, Hash("insNames", n, "insArgs", o, "args", self.args));

        if (self.onAddRow != null) eval(self.onAddRow + "(tabname, self.insRow)");
    }

    self.OnInsRowRes = function (res)
        {
            if (res["errCode"] != null) return OnError(self.name + ": " + res["errCode"]);
            self.LoadData();
            DataChangeNotify(self.DataChangeNotifyList, Hash("act", "table_insrow"));
        }

    self.TextKeyEvent = function (inp, evt)
        {
            var cell = inp.parentNode;
            while(cell.parentNode != null && cell.tagName.toUpperCase() != "TD") cell = cell.parentNode;
            var type = self.colDefs.length > cell.getAttribute("columnIndex") ? self.colDefs[cell.getAttribute("columnIndex")].cnEditType : "NONE";
            if(!checkTag(cell, "td")) return;            
            switch(evt.keyCode)
            {
                case ESC_KEY_CODE:
                    window.setTimeout(function(){self.cancelEdit();}, 1);
                    break;
                case ENTER_KEY_CODE:
                    if(type != "TEXTAREA") window.setTimeout(function(){self.EndEdit(cell);}, 1); 
                    break;
                case TAB_KEY_CODE:
                    var cd = null, cl = null, row = self.curRow;
                    
                    cl = self.getNextEditCellInRow(row, cell.getAttribute("columnIndex"));
                    while(!cl)
                    {
                        row = self.getNextRow(row);
		                if(!row) break;
		                cl = self.getNextEditCellInRow(row, 0);
                    }
                    if(!cl) break;
                    if(row != self.curRow) self.SetCurRow(row.dbid);

                    if(type != "BOOL" && type != "DATETIME") self.EndEdit(cell);
                    if(type == "DATETIME") hideCalendar();

                    if(self.colDefs[cl.getAttribute("columnIndex")].cnEditType != "BOOL")
                        return window.setTimeout(function(){self.DoEdit(cl, null);}, 1); // let finish onEdit reaction before (important!!!)
                    else
                        return window.setTimeout(function(){cl.firstChild.focus();}, 1);

                    break;
            }
        }

    self.getNextRow = function (row)
    {
        for (var i = 0; i < self.TableRows.length; i++)
            if(self.TableRows[i] == row && i + 1 < self.TableRows.length)
                return self.TableRows[i + 1];
        return null;
    }

    self.getNextEditCellInRow = function (row, cellnum)
    {
        if(!row) return null;
        for(var i=cellnum + 1; i<self.colDefs.length; i++)
            if(row.cells[self.colDefs[i].cnIndex].getAttribute("pat_readonlyObj") != "True" && self.colDefs[i].cnEditType != "DELETE" && self.colDefs[i].cnEditType != "CUSTOM" && self.colDefs[i].cnEditType != "READONLY")
                return row.cells[self.colDefs[i].cnIndex];
        return null;
    }

    self.cancelEdit = function ()
        {
            self.SwitchTableEditToView();
        }

    self.isValid = function (coldef, val)
        {
            if(coldef == null || coldef.cnValidate == null) return true;
            var result = true;
            try { eval("result = "+coldef.cnValidate+"('"+val+"')"); } catch (err) { }
            if (!result) OnError(self.name + ": Incorrect " + coldef.cnTitle + ": " + (!ValidateRequired(val) ? "empty field" : val));
            return result;
        }

    self.onRowMouseOver = function (row, evt)
        {
            if(!checkTag(row, "tr")) return;
            if (row != self.curRow && self.selRowsId[row.dbid] != true) row.className = self.MouseOverRowCss;
            if (self.OnRowMouseOver != null) try { eval(self.OnRowMouseOver + "(self, row, evt);"); } catch(err) {}
        }
    self.onRowMouseOut = function (row, evt)
        {
            if(!checkTag(row, "tr")) return;
            if (row != self.curRow && self.selRowsId[row.dbid] != true) row.className = self.RowCss;
            if (self.OnRowMouseOut != null) try { eval(self.OnRowMouseOut + "(self, row, evt);"); } catch(err) {}
        }

    self.FormatValue = function (val, coldef)
        {
            //we should formate Date now, and have only one attribut to format value by: cnMaxLen, but it is possible to have more format attributs
            var res = "" + val;
            
            if (coldef.cnFormat)
                try { eval("res = " + coldef.cnFormat + "(coldef, res)"); } catch (err) { res = ""; }
            else {
                if (coldef.cnEditType == "DATETIME" && val != "")
                    try { res = new Date(val).format("MM/dd/yyyy"); } catch (er) {res = "";}
            }
            res = ((coldef.cnMaxLen && coldef.cnMaxLen > 0 && coldef.cnMaxLen < res.length) ? subval = res.substring(0,coldef.cnMaxLen) + "..." : res);
            if(coldef.cnEditType == "TEXT" || coldef.cnEditType == "READONLY" || coldef.cnEditType == "TEXTAREA")
            {
                var d = document.createElement("div");
                SetText(d,res);
                res = d.innerHTML;
            }
            if(coldef.cnEditType == "TEXTAREA") {
                res = res.replace(/\cM\cJ/gm,"<br>");
                res = res.replace(/\cJ/gm,"<br>");
            }

            return res;     
        }

    self.RenderPager = function (Step)
        {
	        var result = "";
	        if (self.pagesCount > 1)
	        {
	            if(Step < 1) Step = 1; // Step - num of additional page links before and after current page

	            var start = self.currentPage - Step;
	            if (start < 2) start = 2;

	            var finish = start + Step*2 + 1;
	            if (finish > self.pagesCount)
	            {
	                start -= (finish - self.pagesCount);
		            if (start < 2) start = 2;
	                finish = self.pagesCount;
	            }

                result += self.PagerCode(1);
                if(start > 2)result += "<div class=\"" + self.PagerSepCss + "\">...</div>";

	            for (var i = start; i < finish; i++)
	                result += self.PagerCode(i);

                if(finish < self.pagesCount)result += "<div class=\"" + self.PagerSepCss + "\">...</div>";
                result += self.PagerCode(self.pagesCount);
	        }
	        return result;
        }

    self.PagerCode = function (Page)
        {
            var Label = Page;
            if(self.pagerText) try { Label = eval(self.pagerText + "(self, Page);"); } catch(err) {}		
            if (self.currentPage == Page) return "<div class=\"" + self.SelPagerCss + "\"><b>" + Label + "</b></div>";
            var funct = (self.pagerFunction == null ? "" : self.pagerFunction + "(" + Page + ");");
            return "<div class=\"" + self.PagerCss + "\" onclick=\"javascript:TableSetCurPage('" + self.name + "', " + Page + ");" + funct + "\">" + Label + "</div>";
        }

    self.SizeTable(0);
    self.LoadData();
}

//------------------------------------------------- Row Editor -------------------------------------------------
//--------------------------------------------------------------------------------------------------------------

function REInit(name, args, rowId, DataChangeNotifyList, alwaysEnabled, onDataLoaded, onDataArrived, onBeforeUpdate, onBeforeInsert, onSet)
{
    objList[name] = new RowEditor(name, args, rowId, DataChangeNotifyList, alwaysEnabled, onDataLoaded, onDataArrived, onBeforeUpdate, onBeforeInsert, onSet);
}

function RERefresh(name, args, rowId)
{
    if(objList[name])
    {
        if(args) AddHash(objList[name].args, args);
        if(rowId) objList[name].rowId = rowId;
        objList[name].LoadData();
    }
}

function RERowID(name) {
    if(objList[name])
    {
        return objList[name].rowId;
    }
    return -1;
}

function REUpdateArgs(name,args){
    if(objList[name])
    {
        if(args) AddHash(objList[name].args, args);        
    }
}

function REDisable(name, dis)
{
    if(objList[name]) objList[name].Disable(dis);
}

function REReadOnly(name, f)
{
    if(objList[name]) objList[name].ReadOnly(f);
}

function IsRELinked(name)
{
    var res = false;
    if (objList[name]) 
        res = objList[name].IsLinked();
    
    return res;
}

function REMakeInsert(name,args){
    if(args)AddHash(objList[name].args,args);
    objList[name].REInsertRow(true);
}

function RESave(name, inp)
{
    if(objList[name]) objList[name].REEndEdit(inp);
}

function RowEditor(name, args, rowId, DataChangeNotifyList, alwaysEnabled, onDataLoaded, onDataArrived, onBeforeUpdate, onBeforeInsert, onSet)
{
    if(args == null) args = new Object();

    var self = this;

    self.name = name;
    self.rowId = rowId;
    self.args = args;
    self.table = null;
    self.DataChangeNotifyList = DataChangeNotifyList;
    self.onDataLoaded = onDataLoaded;
    self.onDataArrived = onDataArrived;
    self.onBeforeUpdate = onBeforeUpdate;
    self.onBeforeInsert = onBeforeInsert;
    self.onSet = onSet;
    self.alwaysEnabled = alwaysEnabled;
	self.controls = null;

    self.OnDataChangeNotification = function (params) 
        { 
            self.LoadData();
        }

    self.OnRowChangeNotification = function (params) 
        { 
            if(params != null && params["rowid"] != null)
                if(params["rowidname"] != null && params["rowidname"] != "rowid" && params["rowidname"] != "id")
                    self.args = AddHash(self.args, params["rowidname"], params["rowid"]);
                else
                    self.rowId = params["rowid"];
			self.LoadData();
        }

    self.OnServiceRes = function (res)
    {
        switch(res["cmdCode"])
        {
            case "GetSingleRow": self.OnGetSingleRowRes(res); break;
            case "SetData":      self.OnSetDataRes(res); break;
            case "InsRow":       self.OnInsRowRes(res); break;
        }
    }

    self.LoadData = function ()
    {
        ServerCall("GetSingleRow", self.name, Hash("rowid", self.rowId, "args", self.args));
        self.LoadControls();
    }

    self.SetUpButtons = function ()
    {
        if(self.UpdateButton)
        {
            self.onValidateUpdate = self.UpdateButton.getAttribute("onValidate");
            self.onAfterUpdate = self.UpdateButton.getAttribute("onAfterUpdated");
            disableCtrl(self.UpdateButton, self.rowId == "-1");
            AddHandler(self.UpdateButton, "click", self.REUpdateRow_);
        }
        if(self.InsertButton)
        {
            self.onValidateInsert = self.InsertButton.getAttribute("onValidate");
            self.onAfterInsert = self.InsertButton.getAttribute("onAfterInsert");
            disableCtrl(self.InsertButton, self.rowId != "-1" && !self.UpdateButton);
            AddHandler(self.InsertButton, "click", self.REInsertRow_);
        }
        if(self.ClearButton)
        {
            disableCtrl(self.ClearButton, self.rowId != "-1" && !self.UpdateButton);
            AddHandler(self.ClearButton, "click", self.REClear);
        }
        if(self.DeselectButton)
        {
            disableCtrl(self.DeselectButton, self.rowId == "-1");
            AddHandler(self.DeselectButton, "click", self.REDeselect);
        }
    }

	self.LoadControls = function()
	{
	    if(self.controls != null) return;
		self.controls = new Array();
		var rex = new RegExp("^(.+)_" + self.name + "$", "i");
		var docall = document.getElementsByTagName('*');
		for (var i = 0; i < docall.length; i++)
		{
			var el = rex.exec(docall[i].id);
            if (el == null) continue;
            if (el[1] == "UpdateButton")  { self.UpdateButton = docall[i]; continue; }
            if (el[1] == "InsertButton")  { self.InsertButton = docall[i]; continue; }
            if (el[1] == "ClearButton")   { self.ClearButton = docall[i]; continue; }
            if (el[1] == "DeselectButton"){ self.DeselectButton = docall[i]; continue; }
        
            var control = { Input:docall[i], Type:inputType(docall[i]), Related:new Array() };
	        self.controls.push(control);
		}

		for (var i = 0; i < self.controls.length; i++)
		{
            var control = self.controls[i];
		    if(control.Type == inpType.Select) 
		    {
		        control.Related = self.FindRelated(control.Input);
		        DDInit(control.Input.id, AddHash(self.args,"rowid",self.rowId)); 
		    }
		    if(control.Type == inpType.DDEx) 
		    {
		        control.Related = self.FindRelated(control.Input);
		        DDExInit(control.Input.id, AddHash(self.args,"rowid",self.rowId)); 
		    }
		    if(control.Type == inpType.Money)
		    {
                var pr = control.Input.parentNode;
                var t = document.createElement("table");  
                t.className = "def_emptytable_css"; 
                var r = t.insertRow(0);
                r.insertCell(0).appendChild(control.Input);
                r.insertCell(1).innerHTML = "&nbsp;$";

                pr.appendChild(t);
                control.Input.onkeydown = function(evt){return ImpEventMoneyFormatCheck(this, (evt ? evt : window.event)); };
		    }
		    if(control.Type == inpType.Datetime)
		    {
		        if(control.Input.getAttribute("cnClndBtn") != "False")
		        {
		            control.Input.style.height = "12px";
    		        
                    var bt = document.createElement("img");    
                    bt.id = control.Input.id + "_CalendarBtn";
                    bt.setAttribute("impId", control.Input.id);
                    bt.alt = "";
                    bt.src = "PAT/Calendar/calendar.gif";

                    var pr = control.Input.parentNode;
                    var t = document.createElement("table");  
                    t.className = "def_emptytable_css"; 
                    var r = t.insertRow(0);
                    r.insertCell(0).appendChild(control.Input);
                    r.insertCell(1).appendChild(bt);

                    pr.appendChild(t);
                    bt.onclick = function(){if(!$get(this.getAttribute("impId")).disabled) return popUpCalendar(this, $get(this.getAttribute("impId")), 'MM/dd/yyyy'); };
                    control.Input.onclick = function(){if(!this.disabled) return popUpCalendar($get(this.id + "_CalendarBtn"), this, 'MM/dd/yyyy'); };
                }
                else
                    control.Input.onclick = function(){if(!this.disabled) return popUpCalendar(this, this, 'MM/dd/yyyy'); };
		    }
		}
	}

	self.FindRelated = function(inp)
	{
	    var List = inp.getAttribute("RowChangeNotifyList");
        var names  = (List != null && List != "" ? List.replace(/\s/g, "").split(",") : new Array());
        var res = new Array();
        for(var i=0; i<names.length; i++)
        {
            var parts = names[i].split("/");
    		var rex = new RegExp("^(.+)_" + self.name + "$", "i");
			if(parts.length > 1 && rex.exec(parts[0])) res.push({obj:parts[0], arg:parts[1]});
		}
        return res;
	}

	self.OnGetSingleRowRes = function(res) 
	{
	    if (res["errCode"] != null) return OnError(self.name + ": " + res["errCode"]);
	    var tabData = res["tableRes"];

	    self.SetUpButtons();

	    self.table = tabData;

	    if (self.onDataArrived && self.table != null && self.table.rows != null)
	        try {
	            if (typeof(self.onDataArrived) == "string")
	                eval(self.onDataArrived + "(self.table);");
	            else if (typeof(self.onDataArrived) == "function")
	                (self.onDataArrived)(self.table);
	        } catch (err) {}

	    if (self.rowId == "-1" || self.table == null || self.table.rows == null || self.table.columns == null || self.table.rows.length < 1) {
	        self.ClearControls();
	        if (!self.alwaysEnabled) self.Disable(true);

	        for (var i = 0; i < self.controls.length; i++) {
	            var input = self.controls[i].Input;

	            if (self.controls[i].Type == inpType.Text || self.controls[i].Type == inpType.Textarea) RmvHandler(input, "blur", self.REEndEdit);
	            else if (self.controls[i].Type == inpType.Check) RmvHandler(input, "click", self.REEndEdit);
	            else if (self.controls[i].Type == inpType.Select) RmvHandler(input, "change", self.REEndEdit);
	            else if(self.controls[i].Type == inpType.DDEx && objList[self.controls[i].id]) objList[self.controls[i].id].onValueChanged = null;
	            if (input.getAttribute("onDataLoaded") != null && input.getAttribute("onDataLoaded") != "") eval(input.getAttribute("onDataLoaded") + "('" + input.id + "','')");
	            input.setAttribute("rowid", self.rowId);
	            input.setAttribute("dbname", input.id.replace("_" + self.name, ""));

	            if ((input.getAttribute("spellcheck") == "true") && (typeof (PNWSpeller) != "undefined") && (PNWSpeller != null))
	                SpellDecorate(input, "en", null, (input.getAttribute("nogrammarcheck") == "true"));
	        }
	        return;
	    }

	    for (var i = 0; i < self.controls.length; i++) {
	        var input = self.controls[i].Input;
	        var field = input.id.replace("_" + self.name, "");
	        var value = self.table.rows[0][field];

	        disableCtrl(input, false);
	        if (input.getAttribute("onDataLoaded") != null && input.getAttribute("onDataLoaded") != "") eval(input.getAttribute("onDataLoaded") + "('" + input.id + "',value)");
	        var opts = null; try { opts = input.options; } catch (ex) { }

	        if (input.id.indexOf("Button_") > 0)
	            continue;

	        value = (value == null ? "" : value);
	        if (input.getAttribute("EditType") == "Html")
	            input.innerHTML = value;
	        else
	            switch (self.controls[i].Type) {
	            case inpType.Text: case inpType.Textarea:
	                var fmt = input.getAttribute("cnFormat");
	                if (fmt) try { eval("value = " + fmt + "(input, value)"); } catch (err) { }
	                input.value = value;
	                if (!self.UpdateButton) AddHandler(input, "blur", self.REEndEdit);
	                if ((input.getAttribute("spellcheck") == "true") && (typeof (PNWSpeller) != "undefined") && (PNWSpeller != null))
	                    SpellDecorate(input, "en", self.REEndEdit_noSpell, (input.getAttribute("nogrammarcheck") == "true"));
	                break;
	            case inpType.tinyMCE:
	                tinyMCE.get(input.id).setContent(value);
	                //if (!self.UpdateButton) tinyMCE.get(input.id).onChange = function(params) {self.REEndEdit(input);}
	                break;
	            case inpType.Datetime:
	                try { input.value = new Date(value).format("MM/dd/yyyy"); } catch (er) {res = "";}
	                if (!self.UpdateButton) AddHandler(input, "blur", self.REEndEdit);
	                break;
	            case inpType.DDEx:
	                DDExRefresh(input.id, AddHash(self.args,"rowid",self.rowId), value);
	                if (!self.UpdateButton && objList[input.id]) objList[input.id].onValueChanged = function(params) {self.REEndEdit(params.obj.base);}
	                break;
	            case inpType.Money:
	                input.value = FormatMoney(value);
	                if (!self.UpdateButton) AddHandler(input, "blur", self.REEndEdit);
	                break;
	            case inpType.Select:
	                if (objList[input.id]) objList[input.id].initval = value;
	                for (var k = 0; k < self.controls[i].Related.length; k++) SetArgs(self.controls[i].Related[k].obj, Hash(self.controls[i].Related[k].arg, value));
	                if (!self.UpdateButton) AddHandler(input, "change", self.REEndEdit);
	                break;
	            case inpType.Check:
	                input.checked = value;
	                if (!self.UpdateButton) AddHandler(input, "click", self.REEndEdit);
	                break;
	            default:
	                try { input.value = value; } catch (ex) { }
	                try { SetText(input, value); } catch (ex) { }
	                break;
	        }
	        input.setAttribute("rowid", self.rowId);
	        input.setAttribute("dbname", field);
	        if(input.getAttribute("EditType") == "Html" || self.controls[i].Type == inpType.Text || self.controls[i].Type == inpType.Textarea)
	            input.setAttribute("oldval", text2inputvalue(input, value));
	        else
	            input.setAttribute("oldval", value);
	    }
	    for (var i = 0; i < self.controls.length; i++)
	        if (self.controls[i].Type == inpType.Select) DDRefresh(self.controls[i].Input.id, Hash("rowid", self.rowId));

	    if (self.onDataLoaded) try { eval(self.onDataLoaded + "('" + self.name + "','" + self.rowId + "');"); } catch (err) { }
	}

    self.Disable = function (dis)
        {
            for (var i = 0; i < self.controls.length; i++)
                disableCtrl(self.controls[i].Input, dis);

            if (self.InsertButton)   disableCtrl(self.InsertButton, dis);
            if (self.UpdateButton)   disableCtrl(self.UpdateButton, dis);
            if (self.ClearButton)    disableCtrl(self.ClearButton, dis);
            if (self.DeselectButton) disableCtrl(self.DeselectButton, dis);
        }

    self.ClearControls = function ()
        {
            for (var i = 0; i < self.controls.length; i++)
                ClearInput(self.controls[i].Input);                
        }


    self.ReadOnly = function (f)
        {
            for (var i = 0; i < self.controls.length; i++)
                self.controls[i].Input.readOnly = f;
        }

    self.REEndEdit_noSpell = function(inp) 
    {
		self.REEndEdit(inp, null, true);
    }
        
    self.REEndEdit = function(inp, evt, skipSpell) 
        {
			if(inp == null) return;

            var val = inp.value;
            if(inp.type == "checkbox") val = (inp.checked ? 1 : 0);
            if(inp.getAttribute("cnEditType") == "DDEX") val = DDExValue(inp.id);
            if(inp.getAttribute("cnEditType") == "tinyMCE") val = tinyMCE.get(inp.id).getContent();
            if(inp.value == "null") val = null;
            
            if(inp.getAttribute("oldval") != val)
            {
				if(inp.getAttribute("cnValidate") && inp.getAttribute("cnValidate") != "")
				{
                    try { eval("var result = "+inp.getAttribute("cnValidate")+"('"+txt2js(val)+"')"); } catch (err) { }
                    if(result != null && (result.length == null && result == false || result.length && result.length > 0))
                    {  
                        if(result.length == null)
                            OnError(self.name + ": Incorrect '" + inp.id.substr(0, inp.id.indexOf("_")) + "': " + (!ValidateRequired(val) ? "empty field" : val));
                        else OnError(self.name + ": " + result);
                        return inp.value = inp.getAttribute("oldval");
                    }  
				}
				if(self.onBeforeUpdate) try { eval("val = " + self.onBeforeUpdate + "(inp.id, val);"); } catch(err) {}
				ServerCall("SetData", self.name, Hash("rowid", inp.getAttribute("rowid"), "field", inp.getAttribute("dbname"), "value", val, "args", self.args, "inputid", inp.id));
            }
            
	        if (!skipSpell && (inp.getAttribute("spellcheck") == "true") && (typeof(PNWSpeller) != "undefined") && (PNWSpeller != null))
				SpellDecorate(inp, "en", self.REEndEdit_noSpell, (inp.getAttribute("nogrammarcheck") == "true"));
        }

    self.OnSetDataRes = function (res)
        {
            var input = $get(res["args"]["inputid"]);
            var rowid = res["args"]["rowid"];
            var value = res["args"]["value"];
            if (res["errCode"] != null)
            {
				if (input.type == "checkbox")
                  input.checked = input.getAttribute("oldval");
                else
                  input.value = input.getAttribute("oldval");
              return OnError(self.name + ": " + res["errCode"]);
            }

            input.setAttribute("oldval", text2inputvalue(input, value));

            DataChangeNotify(self.DataChangeNotifyList, Hash("act", "sre_setdata", "rowid", rowid));

            if (input.getAttribute("onSet") != null && input.getAttribute("onSet") != "") eval(input.getAttribute("onSet") + "(res)");
 	        
 	        if (self.onSet != null)
 	            try {
 	                if (typeof(self.onSet) == "string")
 	                    eval(self.onSet + "(self.name, res)");
 	                else if (typeof(self.onSet) == "function")
 	                    (self.onSet)(self.name, res);
 	            } catch (err) {}
        }

    self.REUpdateRow_ = function (btn, evt)
        {
            try{if(self.onValidateUpdate != null && !eval(self.onValidateUpdate + "()")) return; }catch(e){}
            self.REInsertRow(true);
        }

    self.REInsertRow_ = function (btn, evt)
        {
            try{if(self.onValidateInsert != null && !eval(self.onValidateInsert + "()")) return; }catch(e){}
            self.REInsertRow(false);
        }

    self.REInsertRow = function (updt)
        {
            var n = new Array();
            var o = new Array();

            for (var i = 0; i < self.controls.length; i++)
            {
                var input = self.controls[i].Input;

                if(input.id.indexOf("Button_") > 0)
                    continue;
                
                var val = "";
                if(inputType(input) == inpType.Check) val = input.checked;
                else if(input.value) val = input.value;
                    
                if((updt && input.getAttribute("oldval") != val)||!updt)
                {
                    var cnValidate = input.getAttribute("cnValidate");
                    if(cnValidate && cnValidate != "")
                    {
                        try { eval("var result = "+cnValidate+"('"+txt2js(val)+"')"); } catch (err) { }
                        if(result != null && (result.length == null && result == false || result.length && result.length > 0))
                        {  
                            if(result.length == null)
                                OnError(self.name + ": Incorrect '" + input.id.substr(0, input.id.indexOf("_")) + "': " + (!ValidateRequired(val) ? "empty field" : val));
                            else OnError(self.name + ": " + result);
                            return input.focus();
                        }
                    }  
               
                    o.push(val);
                    n.push(input.id.replace("_" + self.name, ""))
                }
            }
            
            if(n.length > 0) 
            {
                if(self.onBeforeInsert) try { eval("val = " + self.onBeforeInsert + "(n, o);"); } catch(err) {}
                ServerCall("InsRow", self.name, Hash("insNames", n, "insArgs", o, "rowid", updt ? self.rowId : null, "args", self.args));
            }
        }

    self.OnInsRowRes = function (res)
    {
        if (res["errCode"] != null) return OnError(self.name + ": " + res["errCode"]);
        
        DataChangeNotify(self.DataChangeNotifyList, Hash("act", "sre_insertrow"));

        if(!self.UpdateButton || self.rowId == "-1")
        {   
            if(!self.InsertButton || self.InsertButton && self.InsertButton.getAttribute("notClear") != "True")     
                self.ClearControls();        
            if (self.onAfterInsert != null) try { eval(self.onAfterInsert + "("+res["scalarRes"]+");"); } catch(err) {}
        }
        else if(self.UpdateButton )
        {
            if (self.onAfterUpdate != null) try { eval(self.onAfterUpdate + "("+res.args.args["rowid"]+");"); } catch(err) {}
        }    
    }

    self.REClear = function ()
    {
        for (var i = 0; i < self.controls.length; i++)
        {
            var input = self.controls[i].Input;
            RmvHandler(input, "blur", self.REEndEdit);
            RmvHandler(input, "click", self.REEndEdit);
            ClearInput(input);
			if ((input.getAttribute("spellcheck") == "true") && (typeof(PNWSpeller) != "undefined") && (PNWSpeller != null))
				SpellDecorate(input, "en", self.REEndEdit_noSpell, (input.getAttribute("nogrammarcheck") == "true"));
        }
    }

    self.REDeselect = function ()
    {
        self.rowId = "-1";
        self.OnGetSingleRowRes(new Object());
    }
    
    self.IsLinked = function()
    {
        return self.rowId != "-1";
    }
    
    self.LoadData();
}





//-------------------------------------------------- DropDown --------------------------------------------------
//--------------------------------------------------------------------------------------------------------------

function DDInit(name, args, rowId)
{
    objList[name] = new DropDown(name, args, rowId);
    return objList[name];
}

function DDRefresh(name, args)
{
    if(objList[name]) objList[name].LoadData(args);
}

function SetArgs(name, args)
{
    if(objList[name]) objList[name].args = AddHash(objList[name].args, args);
}

function DDSetValue(name, val)
{
    if(objList[name]) objList[name].SetValue(val);
}

function REDisable(name, dis)
{
    if(objList[name]) objList[name].Disable(dis);
}

function DropDown(name, args, rowId)
{
    if(args == null) args = new Object();

    var self = this;

	self.initval = (rowId != null ? rowId : null);
    self.name = name;
    self.args = args;
    self.table = null;

	self.base =  $get(self.name);
	if (self.base == null) return;
	
	self.RowChangeNotifyList = self.base.getAttribute("RowChangeNotifyList");

    self.OnDataChangeNotification = function (params) 
        { 
            self.LoadData();
        }

    self.OnRowChangeNotification = function (params) 
        { 
            if (params != null)
            {
				if (params["rowid"] != null && params["rowidname"] != null)
					self.args = AddHash(self.args, params["rowidname"], params["rowid"]);
            	self.Disable(params["rowid"] == "-1");
				if (params["rowid"] != "-1") self.LoadData();
        	}
        }

    self.OnServiceRes = function (res)
    {
        switch(res["cmdCode"])
        {
            case "GetPDTable":   self.OnGetPDTableRes(res); break;
        }
    }

    self.LoadData = function (args)
        {
            if(args) AddHash(self.args, args);
            if (self.base.getAttribute("cnRelTableName")) 
                ServerCall("GetPDTable", self.name, Hash("pdName", self.base.getAttribute("cnRelTableName"), "args", self.args));
            else 
                self.OnGetPDTableRes(new Object());
        }


    self.OnGetPDTableRes = function (res)
        {
            if (res["errCode"] != null) return OnError(self.name + ": " + res["errCode"]);
            var relTable = res["tableRes"];
            
			var value = (self.initval != null ? self.initval : (self.base.value == "" ? self.base.getAttribute("cnDefVal") : self.base.value));
            self.initval = null;

            if(relTable) self.DbRowId = relTable.columns[0].name;
            AddHandler(self.base, "change", self.RowChangeNotify_);

            var cnRelNames  = (self.base.getAttribute("cnRelNames")  != null ? self.base.getAttribute("cnRelNames").split(",") : new Array());
            var cnRelValues = (self.base.getAttribute("cnRelValues") != null ? self.base.getAttribute("cnRelValues").split(",") : new Array());
            var cnRelColors = (self.base.getAttribute("cnRelColors") != null ? self.base.getAttribute("cnRelColors").split(",") : new Array());
            var cnRelBackColor = self.base.getAttribute("cnRelBackColor");

            if(relTable && relTable.rows)
                for (var i=0; i < relTable.rows.length; i++)
                {
                    var len = cnRelNames.length != null ? cnRelNames.length : 0;
                    cnRelNames[len]  = relTable.rows[i][relTable.columns[1].name];
                    cnRelValues[len] = relTable.rows[i][relTable.columns[0].name];
                    if (cnRelBackColor != null) cnRelColors[len] = relTable.rows[i][cnRelBackColor];
                }
            
            self.base.innerHTML = "";
                for (var i = 0; i < cnRelNames.length; i++)
                {
                    var el = new Option(cnRelNames[i], cnRelValues[i]);
                    self.base.options.add(el);
                    if (cnRelColors != null && cnRelColors.length == cnRelNames.length)
                    {
                        el.style.backgroundColor = cnRelColors[i];
                        if(cnRelColors[i] == 'Black' || cnRelColors[i] == '#000000')
                        {
							el.style.color = "White";
                        }
                    }
                }
                
                var display = self.base.style.display;
                self.base.style.display = "none"; self.base.style.display = display; // tabs hack
                
                if (value) self.base.value = value;
			    if (self.base.value != value) self.base.selectedIndex = 0;
		    }

    self.RowChangeNotify_ = function (dd, evt)
        {
            RowChangeNotify(self.RowChangeNotifyList, Hash("rowid", self.base.value != "" ? self.base.value : self.initval, "rowidname", self.DbRowId));
        }

    self.SetValue = function (val)
        {
            self.initval = val;
            self.base.value = val;
            self.RowChangeNotify_();
        }

    self.Disable = function (dis)
        {
            self.base.disabled = dis;
        }
        
    self.LoadData();
}

//------------------------------------------------- DropDownEx -------------------------------------------------
//--------------------------------------------------------------------------------------------------------------

function DDExInit(name, args, defval)
{
    objList[name] = new DropDownEx(name, args, defval);
}

function DDExRefresh(name, args, val)
{
    if(objList[name]) objList[name].Refresh(args, val);
}

function DDExDisable(name, dis)
{
    if(objList[name]) objList[name].Disable(dis);
}

function DDExValue(name)
{
    if(objList[name]) return objList[name].value;
}

function DDExSetValue(name, val) // No notification raised on this. We should care to refresh related objects
{
    if(objList[name]) return objList[name].SetValue(val);
}

function DDExSelectAll(name, select)
{
    if(objList[name]) return objList[name].SelectAll(select);
}

function DDExClear(name)
{
    if(objList[name]) objList[name].Clear();
}

function DropDownEx(name, args, defval)
{
    if(args == null) args = new Object();

    var self = this;

    self.name = name;
    self.args = args;
    self.table = null;

    self.base = $get(self.name);
    if(self.base == null) return;

    self.selOpts = new Object();
    self.addOpts = "";
    self.multSel = (self.base.getAttribute("multSel") == "True" ? true : false);
    self.showVal = (self.base.getAttribute("showVal") == "True" ? true : false);
    self.editable = (self.base.getAttribute("editable") == "True" ? true : false);
    self.selAll  = self.multSel && (self.base.getAttribute("selAll") != "False" ? true : false);

	self.defVl = (defval != null ? defval : self.base.getAttribute("cnDefVal"));
	self.selectFirst = self.base.getAttribute("selectFirst");
    self.value = null;
    self.dataLoaded = false;
        
    self.divCss = (self.base.getAttribute("divCss") ? self.base.getAttribute("divCss") : "def_ddex_div_css");
    self.optCss = (self.base.getAttribute("optCss") ? self.base.getAttribute("optCss") : "def_ddex_opt_css");
    self.spnCss = (self.base.getAttribute("spnCss") ? self.base.getAttribute("spnCss") : "def_ddex_spn_css");
    self.hovCss = (self.base.getAttribute("hovCss") ? self.base.getAttribute("hovCss") : "def_ddex_hov_css");
    self.selCss = (self.base.getAttribute("selCss") ? self.base.getAttribute("selCss") : "def_ddex_sel_css");
    self.ocnCss = (self.base.getAttribute("ocnCss") ? self.base.getAttribute("ocnCss") : "def_ddex_optcnt_css");
    self.saCss  = (self.base.getAttribute("saCss")  ? self.base.getAttribute("saCss")  : "def_ddex_sa_css");
    
    self.colID  = (self.base.getAttribute("colID")  ? self.base.getAttribute("colID")  : null);
    self.colName = (self.base.getAttribute("colName") ? self.base.getAttribute("colName") : null);

    self.divW = (self.base.getAttribute("divW")  ? self.base.getAttribute("divW")  : "150px");
    self.divH = self.base.getAttribute("divH");

    self.onValueChanged = self.base.getAttribute("onValueChanged");
    self.onDataLoaded = self.base.getAttribute("onDataLoaded");
    
    self.defSubscr = (self.base.getAttribute("defSubscr")? self.base.getAttribute("defSubscr") : "Please Select");
    self.input = document.createElement("div");
    self.input.className = (self.base.getAttribute("impCss")? self.base.getAttribute("impCss") : "def_ddex_imp_css");    
    self.input.innerHTML = self.defSubscr;
    if(self.base.getAttribute("impW")) self.input.style.width = self.base.getAttribute("impW");
    if(self.editable) self.input.setAttribute("contentEditable", "true");
    
    self.button = document.createElement("img");    
    self.button.className = (self.base.getAttribute("btnCss") ? self.base.getAttribute("btnCss") : "def_ddex_btn_css");    
    self.button.alt = "";
    self.button.src = "PAT/Images/ddex.gif";

    self.CntTableCss = (self.base.getAttribute("cntTableCss") ? self.base.getAttribute("cntTableCss") : "def_ddex_cnttable_css");    
    self.base.innerHTML = "<table class='" + self.CntTableCss + "'><tr><td></td><td></td></tr></table>";
    self.base.childNodes[0].childNodes[0].childNodes[0].childNodes[0].appendChild(self.input);
    self.base.childNodes[0].childNodes[0].childNodes[0].childNodes[1].appendChild(self.button);

    self.div = document.createElement("div");
    self.div.className = self.divCss;
    self.base.appendChild(self.div);
    self.div.style.display = "none";

    self.sadiv = document.createElement("div");
    self.sadiv.className = self.saCss;
    self.div.appendChild(self.sadiv);

    self.ocndiv = document.createElement("div");
    self.ocndiv.style.minHeight = "10px";
    if(self.divW) self.ocndiv.style.minWidth = self.divW.toString();
    if(self.divH) self.ocndiv.style.maxHeight = self.divH.toString();
    self.ocndiv.className = self.ocnCss;
    self.div.appendChild(self.ocndiv);

    self.OnDataChangeNotification = function (params) 
        { 
            self.LoadData();
        }

    self.OnRowChangeNotification = function (params) 
        { 
            if(params != null && params["rowid"] != null && params["rowidname"] != null)
                self.args = AddHash(self.args, params["rowidname"], params["rowid"]);

            self.Disable(params["rowid"] == "-1");
            if (params["rowid"] != "-1") self.LoadData();
        }

    self.OnServiceRes = function (res)
    {
        switch(res["cmdCode"])
        {
            case "GetPDTable":   self.OnGetPDTableRes(res); break;
        }
    }

    self.LoadData = function ()
        {
            var s = $get(self.name);
            if (s && s.getAttribute("cnRelTableName")) 
                ServerCall("GetPDTable", self.name, Hash("pdName", s.getAttribute("cnRelTableName"), "args", self.args));
            else 
                self.OnGetPDTableRes(new Object());
        }

    self.OnGetPDTableRes = function (res)
        {
            if (res["errCode"] != null) return OnError(self.name + ": " + res["errCode"]);
            var relTable = res["tableRes"];
            
            self.ClearVals();
            
            if(relTable) self.DbRowId = relTable.columns[0].name;
            self.RowChangeNotifyList = self.base.getAttribute("RowChangeNotifyList");

            var cnRelNames  = (self.base.getAttribute("cnRelNames")  != null ? self.base.getAttribute("cnRelNames").split(",") : new Array());
            var cnRelValues = (self.base.getAttribute("cnRelValues") != null ? self.base.getAttribute("cnRelValues").split(",") : new Array());
            var cnRelColors = (self.base.getAttribute("cnRelColors") != null ? self.base.getAttribute("cnRelColors").split(",") : new Array());
            var cnRelBackColor = self.base.getAttribute("cnRelBackColor");

            if(relTable && relTable.rows)
                for (var i=0; i < relTable.rows.length; i++)
                {
                    var len = cnRelNames.length != null ? cnRelNames.length : 0;
                    cnRelNames[len]  = relTable.rows[i][self.colName ? self.colName : relTable.columns[1].name];
                    cnRelValues[len] = relTable.rows[i][self.colID   ? self.colID   : relTable.columns[0].name];
                    if (cnRelBackColor != null) cnRelColors[len] = relTable.rows[i][cnRelBackColor];
                }

            if(self.selAll) self.sadiv.innerHTML = "<a href='javascript:DDExSelectAll(\"" + self.name + "\", true)'>Select All</a>&nbsp;<a href='javascript:DDExSelectAll(\"" + self.name + "\", false)'>Unselect All</a>";
            self.ocndiv.innerHTML = "";
            var contain = false;
            for (var i = 0; i < cnRelNames.length; i++)
            {
                var opt = document.createElement("div");
                opt.className = self.optCss;
                if(cnRelNames[i]) opt.innerHTML = (self.multSel ? "<input type='checkbox'/>" : "") + "<span class='" + self.spnCss + "'>" + Quote(cnRelNames[i]) + "</span>";
                opt.setAttribute("value", cnRelValues[i]);
                opt.setAttribute("name", cnRelNames[i]);
                if(cnRelColors){opt.style.backgroundColor = cnRelColors[i];}
                AddHandler(opt, "mouseover", self.onOptMouseOver);
                AddHandler(opt, "mouseout", self.onOptMouseOut);
                AddHandler(opt, "click", self.onOptMouseClick);
                self.ocndiv.appendChild(opt);
                if (self.value == cnRelValues[i])
                {
                    contain = true;
                }
            }
            self.dataLoaded = true;
            if(self.newval)
            {
                self.value = self.newval;
                self.newval = null;
            }
            else
                self.value = ((self.value && contain) ? self.value : (!self.multSel && self.defVl == null && cnRelValues.length > 0 && self.selectFirst == "True") ? cnRelValues[0] : self.defVl);
            self.SetValue(self.value);
    	    try { if(self.onDataLoaded) eval(self.onDataLoaded + "(self);"); } catch(err) {}
        }
    
    self.Refresh = function (args, val)
    {
        if(args) AddHash(self.args, args);
        if(val) self.newval = val;
        objList[name].LoadData();
    }

    self.onInpMouseClick = function (obj, evt)
        {
            ShowPopUp(self.div, self.input);
            AddHandler(window, "resize", self.changePos);
            CancelBubbling(evt);
        }
    
    self.changePos = function (obj, evt)
        {
    	    SetDropDownPos(self.input, self.div);
        }

    self.onOptMouseClick = function (opt, evt)
        {
            if(!checkTag(opt, "div")) return;
            if(self.multSel)
            {
                if(opt.className == self.selCss) 
                {
                    opt.className = self.optCss; 
                    opt.innerHTML = "<input type='checkbox' /><span>" + opt.childNodes[1].innerHTML + "</span>"; // checked = true/false work bad with CancelBubbling
                    delete self.selOpts[opt.getAttribute("value")]; 
                }
                else
                {
                    self.selOpts[opt.getAttribute("value")] = opt;
                    opt.innerHTML = "<input type='checkbox' checked/><span>" + opt.childNodes[1].innerHTML + "</span>"; // checked = true/false work bad with CancelBubbling
                    opt.className = self.selCss;
                }
                CancelBubbling(evt);
            }
            else
            {
                if(opt.className == self.selCss) return;
                self.ClearVals();
                self.selOpts[opt.getAttribute("value")] = opt;
                opt.className = self.selCss;
            }
            self.CalcValues();
            RowChangeNotify(self.RowChangeNotifyList, Hash("rowid", self.value, "rowidname", self.DbRowId));
            Exec(self.onValueChanged, Hash("obj", self, "val", self.value, "opt", opt));
            //if(self.onValueChanged) try { eval(self.onValueChanged + "(self, self.value, opt);"); } catch(err) {}
        }

    self.onOptMouseOver = function (opt, evt)
        {
            if(!checkTag(opt, "div")) return;
            if(opt.className == self.optCss) opt.className = self.hovCss;
        }

    self.onOptMouseOut = function (opt, evt)
        {
            if(!checkTag(opt, "div")) return;
            if(opt.className == self.hovCss) opt.className = self.optCss;
        }

    self.Disable = function (dis)
        {
            if(dis) RmvHandler(self.input,  "click", self.onInpMouseClick); else AddHandler(self.input,  "click", self.onInpMouseClick);
            if(dis) RmvHandler(self.button, "click", self.onInpMouseClick); else AddHandler(self.button, "click", self.onInpMouseClick);
        }
        
    self.ClearVals = function ()
        {
            self.addOpts = "";
            for (var id in self.selOpts) 
            { 
                self.selOpts[id].className = self.optCss; 
                if(self.multSel) self.selOpts[id].firstChild.checked = false;
                delete self.selOpts[id]; 
            }
        }

    self.CalcValues = function ()
        {
            var v = "", n = "";
            for (var id in self.selOpts) { v += id + ","; n += self.selOpts[id].getAttribute("name") + ", "; }
            v = (v.length > 1 ? v.substring(0, v.length - 1) : "");
            self.value = v + (v != "" && self.addOpts != "" ? "," : "") + self.addOpts;
            n = Quote(n.length > 2 ? n.substring(0, n.length - 2) : "");
            n = n + (n != "" && self.addOpts != "" ? ", " : "") + self.addOpts;
            if(n == "") n = self.defSubscr;
            if(self.showVal)
                self.input.innerHTML = self.ClearValue(self.value);
            else
                self.input.innerHTML = self.ClearValue(n);
        }

    self.Clear = function ()
        {
            self.ClearVals();
            self.CalcValues();
        }

    self.SetValue = function (val)    
        {
            self.ClearVals();
            self.value = val;
            if(!self.dataLoaded) 
            {
                self.newval = val;
                return;
            }
            var vals  = (val != null && val != "" ? val.toString().replace(/\s/g, "").split(",") : new Array());
            var op = null;
            
            for(var i=0; i<vals.length; i++)
            {
                for(var j=0; j<self.ocndiv.childNodes.length; j++)
                {
                    op = self.ocndiv.childNodes[j];
                    if(op.getAttribute("value") == vals[i])
                    {
                        self.selOpts[vals[i]] = op;
                        if(self.multSel) op.firstChild.checked = true;
                        op.className = self.selCss;
                    }
                }
                if(self.selOpts[vals[i]] == null) self.addOpts = self.addOpts + (self.addOpts != "" ? ", " : "") + vals[i];
            }
            if(self.editable) self.input.innerHTML = self.ClearValue(val);
            self.CalcValues();
        }
        
    self.ClearValue = function (val)    
        {
            if(!val) return "";
            return val.replace(/<[^>^<]*>/g, "");
        }

    self.LoadValue = function ()    
        {
            self.SetValue(self.ClearValue(self.input.innerHTML));        
            RowChangeNotify(self.RowChangeNotifyList, Hash("rowid", self.value, "rowidname", self.DbRowId));
            Exec(self.onValueChanged, Hash("obj", self, "val", self.value, "opt", null));
        }

    self.SelectAll = function (select)    
        {
            self.ClearVals();

            for(var j=0; select && j<self.ocndiv.childNodes.length; j++)
            {
                var op = self.ocndiv.childNodes[j];
                self.selOpts[op.getAttribute("value")] = op;
                if(self.multSel) op.firstChild.checked = true;
                op.className = self.selCss;
            }
            self.CalcValues();
            RowChangeNotify(self.RowChangeNotifyList, Hash("rowid", self.value, "rowidname", self.DbRowId));
            Exec(self.onValueChanged, Hash("obj", self, "val", self.value, "opt", null));
            //if(self.onValueChanged) try { eval(self.onValueChanged + "(self, self.value, null);"); } catch(err) {}
        }

    if(self.editable) AddHandler(self.input, "blur", self.LoadValue);
    AddHandler(self.input,  "click", self.onInpMouseClick);
    AddHandler(self.button, "click", self.onInpMouseClick);
    self.LoadData();
}


//------------------------------------------------- AutoComplete -------------------------------------------------
//--------------------------------------------------------------------------------------------------------------

function AutoCompleteInit(name, args)
{
    objList[name] = new AutoComplete(name, args);
}

function AutoCompleteDel(name)
{
    if(!objList[name]) return;

    RmvHandler(document, "click", objList[name].Hide);
    RmvHandler(self.base, "keydown", objList[name].onKeyPress);
    
    //objList[name].div.parentNode.removeChild(objList[name].div);
    
    delete objList[name];
}

function AutoComplete(name, args)
{
    if(args == null) args = new Object();

    var self = this;

    self.name = name;
    self.args = args;
    self.table = null;

    self.base = $get(self.name);
    if(self.base == null) return;

    self.divCss = (self.base.getAttribute("divCss") ? self.base.getAttribute("divCss") : "def_ddex_div_css");
    self.optCss = (self.base.getAttribute("optCss") ? self.base.getAttribute("optCss") : "def_ddex_opt_css");
    self.spnCss = (self.base.getAttribute("spnCss") ? self.base.getAttribute("spnCss") : "def_ddex_spn_css");
    self.hovCss = (self.base.getAttribute("hovCss") ? self.base.getAttribute("hovCss") : "def_ddex_hov_css");
    self.ocnCss = (self.base.getAttribute("ocnCss") ? self.base.getAttribute("ocnCss") : "def_ddex_optcnt_css");
    self.saCss  = (self.base.getAttribute("saCss")  ? self.base.getAttribute("saCss")  : "def_ddex_sa_css");
            
    self.cnMaxOpts = (self.base.getAttribute("cnMaxOpts")  ? self.base.getAttribute("cnMaxOpts")  : null);        

    self.cnDelay = (self.base.getAttribute("cnDelay")  ? self.base.getAttribute("cnDelay")  : 300);        
    
    self.divW = (self.base.getAttribute("divW")  ? self.base.getAttribute("divW")  : "150px");
    self.divH = self.base.getAttribute("divH");

    self.onDataLoaded = self.base.getAttribute("onDataLoaded");
    self.base.setAttribute("autocomplete","off");
    
    self.div = document.createElement("div");
    self.div.className = self.divCss;
    self.div.style.display = "none";
    self.base.parentNode.appendChild(self.div);

    self.sadiv = document.createElement("div");
    self.sadiv.className = self.saCss;
    self.div.appendChild(self.sadiv);

    self.ocndiv = document.createElement("div");
    self.ocndiv.style.minHeight = "10px";
    if(self.divW) self.ocndiv.style.minWidth = self.divW.toString();
    if(self.divH) self.ocndiv.style.maxHeight = self.divH.toString();
    self.ocndiv.className = self.ocnCss;
    self.div.appendChild(self.ocndiv);

    self.cnRelTableName = self.base.getAttribute("cnRelTableName");
    self.cnColumn = self.base.getAttribute("cnColumn");
    
    self.timer = null;
    self.opts = new Array();
    self.aOptInsex = -1;

    self.OnServiceRes = function (res)
    {
        switch(res["cmdCode"])
        {
            case "GetPDTable":   self.OnGetPDTableRes(res); break;
        }
    }

    self.LoadData = function ()
        {
            self.args.filter = self.base.value;
             
            if (self.cnRelTableName) 
                ServerCall("GetPDTable", self.name, Hash("pdName", self.cnRelTableName, "pagesize", self.cnMaxOpts, "args", self.args));
            else 
                self.OnGetPDTableRes(new Object());
        }

    self.OnGetPDTableRes = function (res)
        {
            if (res["errCode"] != null) return OnError(self.name + ": " + res["errCode"]);
            var relTable = res["tableRes"];
            
            var cnRelNames  = (self.base.getAttribute("cnRelNames")  != null ? self.base.getAttribute("cnRelNames").split(",") : new Array());
            var cnRelColors = (self.base.getAttribute("cnRelColors") != null ? self.base.getAttribute("cnRelColors").split(",") : new Array());
            var cnRelBackColor = self.base.getAttribute("cnRelBackColor");

            if(relTable && relTable.rows)
                for (var i=0; i < relTable.rows.length; i++)
                {
                    var len = cnRelNames.length != null ? cnRelNames.length : 0;
                    var cname = (self.cnColumn ? self.cnColumn : relTable.columns[0].name);
                    cnRelNames[len]  = relTable.rows[i][cname];
                    if (cnRelBackColor != null) cnRelColors[len] = relTable.rows[i][cnRelBackColor];
                }

            self.ocndiv.innerHTML = "";
            self.opts.length = 0;
            self.aOptInsex = -1;
            for (var i = 0; i < cnRelNames.length; i++)
            {
                if(!cnRelNames[i] || cnRelNames[i] == "") continue;
                var opt = document.createElement("div");
                opt.className = self.optCss;
                opt.setAttribute("index", i);
                opt.innerHTML = "<span class='" + self.spnCss + "'>" + Quote(cnRelNames[i]) + "</span>";
                opt.setAttribute("name", cnRelNames[i]);
                if(cnRelColors){opt.style.backgroundColor = cnRelColors[i];}
                AddHandler(opt, "mouseover", self.onOptMouseOver);
                AddHandler(opt, "mouseout", self.onOptMouseOut);
                AddHandler(opt, "click", self.onOptMouseClick);
                self.ocndiv.appendChild(opt);
                self.opts.push(opt);
            }
            
            if(self.opts.length > 0)
            {
                self.Show();
                AddHandler(window, "resize", self.changePos);
            }
            else
                self.Hide(false);

    	    try { if(self.onDataLoaded) eval(self.onDataLoaded + "(self);"); } catch(err) {}
        }

    self.onKeyPress = function (obj, evt)
        {
            switch(evt.keyCode)
            {
                case BOTTOM_KEY_CODE:
                    if(self.div.style.display == "none") break;
                    self.SetActiveOpt(self.aOptInsex + 1);
                    return;
                case TOP_KEY_CODE:
                    self.SetActiveOpt(self.aOptInsex - 1);
                    return;
                case ENTER_KEY_CODE: case TAB_KEY_CODE:
                    self.Close();
                    return;
                case ESC_KEY_CODE:
                    self.Hide(false);
                    return;
            }
	        if(self.timer) window.clearTimeout(self.timer);
	        self.timer = window.setTimeout(self.LoadData, self.cnDelay);
        }
    
    self.onBaseClick = function (obj, evt)
        {
            CancelBubbling(evt);
        }
    
    self.changePos = function (obj, evt)
        {
    	    SetDropDownPos(self.base, self.div);
        }

    self.onOptMouseClick = function (opt, evt)
        {
            if(!checkTag(opt, "div")) return;
            self.Close();
        }

    self.Close = function ()
        {
            if(self.aOptInsex >= 0 && self.aOptInsex < self.opts.length)
                self.base.value = self.opts[self.aOptInsex].firstChild.innerHTML;
            self.Hide();
        }

    self.onOptMouseOver = function (opt, evt)
        {
            if(!checkTag(opt, "div")) return;
            self.SetActiveOpt(opt.getAttribute("index"));
        }

    self.onOptMouseOut = function (opt, evt)
        {
            if(!checkTag(opt, "div")) return;
            self.SetActiveOpt();
        }

    self.SetActiveOpt = function (index)
        {
            if(self.opts.length == 0) return;
            if(self.aOptInsex >= 0 && self.aOptInsex < self.opts.length)self.opts[self.aOptInsex].className = self.optCss;
            self.aOptInsex = -1;

            if(index == null) return;
            if(index < 0) index = self.opts.length - 1;
            if(index >= self.opts.length) index = 0;
            
            self.aOptInsex = index;
            self.opts[index].className = self.hovCss;
        }

    self.Hide = function (fierEvt)
        {
            self.div.style.display = "none";
            if(fierEvt != false) try { eval(self.base.getAttribute("onHide") + "(self, self.base.value);"); } catch(err) {}
        }

    self.Show = function ()
        {
	        self.div.style.display = "";
	        SetDropDownPos(self.base, self.div);
        }

    AddHandler(document, "click", self.Hide);
    AddHandler(self.base, "keydown", self.onKeyPress);
    AddHandler(self.base, "click", self.onBaseClick);
}

//--------------------------------------------------- TabsObj --------------------------------------------------
//--------------------------------------------------------------------------------------------------------------

function TabsInit(name, selected, loader)
{
    objList[name] = new TabsObj(name, selected, loader);
}

function TabsSetSelected(name, tabname)
{
    if(objList[name]) objList[name].SetSelected(tabname);
}

function TabsDisable(name, tabname)
{
    if(objList[name]) objList[name].Disable(tabname);
}

function TabsHide(name, hide)
{
    if(objList[name]) objList[name].Hide(hide);
}

function TabsHideTab(name, tabname, hide)
{
    if(objList[name]) objList[name].HideTab(tabname, hide);
}

function TabsSetTabCaption(name, tabname, caption)
{
    if(objList[name]) objList[name].SetTabCaption(name, tabname, caption);
}

function TabsGetSelected(name)
{
    if(objList[name]) return objList[name].selected;
    return null; 
}

function TabsObj(name, selected, loader)
{
    var self = this;

    self.name = name;
    self.selected = selected;
	self.tabsContainer = $get(name + "_TabsContainer");
	self.tabsMenu = $get(name + "_TabsMenu");	
	
	if(self.tabsContainer == null || self.tabsMenu == null || self.tabsContainer.childNodes.length == 0) return;

	self.tabCss = self.tabsMenu.getAttribute("tabCss");
	self.atabCss = self.tabsMenu.getAttribute("atabCss");
	self.dtabCss = self.tabsMenu.getAttribute("dtabCss");
	self.htabCss = self.tabsMenu.getAttribute("htabCss");
	
	self.outSpCss = self.tabsMenu.getAttribute("outSpCss");
	self.aoutSpCss = self.tabsMenu.getAttribute("aoutSpCss");
	self.doutSpCss = self.tabsMenu.getAttribute("doutSpCss");
	self.houtSpCss = self.tabsMenu.getAttribute("houtSpCss");

	self.inSpCss = self.tabsMenu.getAttribute("inSpCss");
	self.ainSpCss = self.tabsMenu.getAttribute("ainSpCss");
	self.dinSpCss = self.tabsMenu.getAttribute("dinSpCss");
	self.hinSpCss = self.tabsMenu.getAttribute("hinSpCss");

	if("undefined" != typeof(loader))
	{
	   LoaderInit(loader);
	}

    self.tabs = new Object();
    self.itms = new Object();

    self.LoadObj = function () 
        { 
	        for(var i=0; i<self.tabsContainer.childNodes.length; i++)
	        {
	            if(self.tabsContainer.childNodes[i].getAttribute == null || self.tabsContainer.childNodes[i].getAttribute("name") == null || self.tabsContainer.childNodes[i].style.display == "none") continue;
	            var name = self.tabsContainer.childNodes[i].getAttribute("name");
	            if(self.selected == null) self.selected = name;
	            self.tabs[name] = self.tabsContainer.childNodes[i];
                if(name != self.selected) self.tabs[name].style.display = "none";

                var ul = document.createElement("ul");
                var lnk = document.createElement("li");
                var outSp = document.createElement("span");
                var inSp = document.createElement("span");
                AddHandler(lnk, "click", self.OnItemClick);
                AddHandler(lnk, "mouseover", self.OnItemMOver);
                AddHandler(lnk, "mouseout", self.OnItemMOut);
                lnk.setAttribute("name", name);
                inSp.innerHTML = name;
                lnk.className = (name != self.selected ? self.tabCss : self.atabCss);
                outSp.className = (name != self.selected ? self.outSpCss : self.aoutSpCss);
                inSp.className = (name != self.selected ? self.inSpCss : self.ainSpCss);
                ul.appendChild(lnk);
                lnk.appendChild(outSp);
                outSp.appendChild(inSp);
                self.tabsMenu.appendChild(ul);
                self.itms[name] = lnk;
	        }
	    }

    self.SetSelected = function (tabname) 
        { 
            if(self.selected == tabname || self.itms[tabname].className == self.dtabCss) return;
            self.tabs[self.selected].style.display = "none";
            self.itms[self.selected].className = self.tabCss;
            self.itms[self.selected].firstChild.className = self.outSpCss;
            self.itms[self.selected].firstChild.firstChild.className = self.inSpCss;
            self.selected = tabname;
            self.tabs[self.selected].style.display = "";
            self.itms[self.selected].className = self.atabCss;
            self.itms[self.selected].firstChild.className = self.aoutSpCss;
            self.itms[self.selected].firstChild.firstChild.className = self.ainSpCss;
            if(self.tabs[self.selected].getAttribute("onSelect"))
                try { eval(self.tabs[self.selected].getAttribute("onSelect") + "(tabname, self);"); } catch(err) {}
        }

    self.SetTabCaption = function (name, tabname, caption)
        {
            self.itms[tabname].firstChild.firstChild.innerHTML = caption;
        }

    self.Disable = function (tabname) 
        { 
            self.itms[tabname].className = self.dtabCss;
            self.itms[tabname].firstChild.className = self.doutSpCss;
            self.itms[tabname].firstChild.firstChild.className = self.dinSpCss;
        }

    self.Hide = function (hide) 
        { 
            self.tabsMenu.style.display = (hide ? "none" : "");
        }
        
    self.HideTab = function (tabname, hide)
        {
            self.itms[tabname].style.display = (hide ? "none" : "");
            if(hide && self.itms[tabname].className == self.atabCss)
                for (var tname in self.itms)
                    if(self.itms[tname].style.display != "none" && self.itms[tname].className != self.dtabCss)
                        return self.SetSelected(tname);
        }
        
    self.OnItemClick = function (lnk, evt) 
        {
            if(!checkTag(lnk, "li")) return;
            self.SetSelected(lnk.getAttribute("name"));
        }
        
    self.OnItemMOver = function (lnk, evt) 
        {
            if(!checkTag(lnk, "li")) return;
            if(lnk.className != self.atabCss && lnk.className != self.dtabCss)
            {
                lnk.className = self.htabCss;
                lnk.firstChild.className = self.houtSpCss;
                lnk.firstChild.firstChild.className = self.hinSpCss;
            }
        }
        
    self.OnItemMOut = function (lnk, evt) 
        {
            if(!checkTag(lnk, "li")) return;
            if(lnk.className != self.atabCss && lnk.className != self.dtabCss)
            {
                lnk.className = self.tabCss;
                lnk.firstChild.className = self.outSpCss;
                lnk.firstChild.firstChild.className = self.inSpCss;
            }
        }

    self.LoadObj();
}


//--------------------------------------------------- PopUpObj --------------------------------------------------
//--------------------------------------------------------------------------------------------------------------

function PopUpInit(name)
{
    objList[name] = new PopUpObj(name);
}

function PopUpShow(name, show)
{
    if(objList[name]) objList[name].Show(show);
}

function PopUpObj(name)
{
    var self = this;

    self.name = name;
	self.body = $get(name + "_PopUp");
	if(!self.body) { OnError("Pop-up '" + self.name + "' init Error"); return; }

    self.modaldiv = document.createElement("div");
    self.body.parentNode.appendChild(self.modaldiv);
    self.modaldiv.className = (self.body.getAttribute("ModalDivCss") ? self.body.getAttribute("ModalDivCss") : "def_popup_modaldiv_css");
	self.modaldiv.style.display = "none";
    
    self.bodybasediv = document.createElement("div");
    self.body.parentNode.appendChild(self.bodybasediv);

    self.bodybasediv.innerHTML = "<table style='width:100%; height:100%'><tr><td valign='middle' align='center' id='" + self.name + "_PopUp_baseTd'></td></tr></table>";  
    self.bodybasediv.className = (self.body.getAttribute("ModalBasDivCss") ? self.body.getAttribute("ModalBasDivCss") : "def_popup_basediv_css");
	self.bodybasediv.style.display = "none";
	
	self.onShow = (self.body.getAttribute("OnShow") ? self.body.getAttribute("OnShow") : null);
	self.onHide = (self.body.getAttribute("OnHide") ? self.body.getAttribute("OnHide") : null);
	
	if(self.body.getAttribute("Style3d") == "True")
	{
	    var Caption = (self.body.getAttribute("Caption3d") ? "<span style='float:left; margin-left:5px;'>" + self.body.getAttribute("Caption3d") + "</span>" : "")
	    var Close = (self.body.getAttribute("Close3d") != "False" ? "<span style='float:right; cursor:pointer; margin-right:5px;' onclick=\"PopUpShow('" + self.name + "', false);\">x</span>" : "")
	    $get(name + "_PopUp_baseTd").innerHTML = "<table class='dialog-3d'><tr><th class='caption-left' /><th class='caption-center'>" + Caption + Close + "</th><th class='caption-right' /></tr>" +
                              "<tr class='body-row'><td class='body-left' /><td class='body-placeholder' id='" + name + "_PopUp_base3dTd'>" + 
                              "</td><td class='body-right' /></tr><tr><td class='bottom-left' /><td class='bottom-center' /><td class='bottom-right' /></tr></table>";
        $get(name + "_PopUp_base3dTd").appendChild(self.body);
	}
	else
        $get(name + "_PopUp_baseTd").appendChild(self.body);
    
    self.Show = function (show) 
    { 
        self.modaldiv.style.display = (show ? "inline" : "none");
        self.bodybasediv.style.display = (show ? "inline" : "none");
        if (show && self.onShow) try {eval("" + self.onShow + "(self);");}catch(err){}
        if (!show && self.onHide) try {eval("" + self.onHide + "(self);");}catch(err){}
	}
}
//----------------------------------------------- Load Indicator ----------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------------------

function ProgressInit(progress, progress_css)
{
   Progress = new PATProgress(progress, progress_css);   
}

function PATProgress(progress, progress_css)
{
   var self = this;
   if(null != progress)   
   {
       self.Progress = document.getElementById(progress);
      if(self.Progress) self.Progress.className = (progress_css == null ? "def_progress_css" : progress_css);

      self.Show = function(show) 
      {
          if (self.onShow) try { eval(self.onShow(show)); } catch (ex) { OnError(self.name + ": Invalid " + self.onShow + " function(Show)") }
          if (self.Progress) self.Progress.style.visibility = (show ? "visible" : "hidden");
      }
   }
   self.Show(false);
}

//----------------------------------------------- Export ------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------------------
function ExportTo(objName, format, map)
{
	var sParams = "export="+format+"&obj=" + objName;
	var objArgs = TableGetArgs(objName);
	if (typeof(objArgs) != "undefined")
		sParams += "&args=" + escape(Quote(JSON.stringify(objArgs)));
	if (typeof(map) != "undefined")
		sParams += "&map=" + map;
	window.open('PAT/Export/Export.aspx?' + sParams);
}

//---------------------------------------------- Pivot Table -------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------

function PVTableEditor(name, args, xsl)
{
    var self = this;

    self.name = name;
    self.args = args;
    self.xsl = "" + xsl;
    
    var tblResult = null;
    var tblFiltered = null;
    var tblFilterBy = null;
 
    var Init = function()
    {
        if(self.args == null)
            self.args = new Object();
        
        if(self.args["pivotTable"] == null)
            self.args["pivotTable"] = self.name;
        
        tblFiltered = $get(self.name + "Filtered");
        if(tblFiltered == null)
            throw "Pivot table:\r\nFiltered table should be declared!";
        
        tblFilterBy = $get(self.name + "FilterBy");
        if(tblFilterBy == null)
            throw "Pivot table:\r\nFilterBy table should be declared!";
        
        tblResult = $get(self.name + "Result")
        if(tblResult == null)
            throw "Pivot table:\r\nResult table should be declared!";
            
        TableInit(tblFilterBy.id, self.args);
        TableInit(tblResult.id, self.args);
        TableInit(tblFiltered.id, self.args);
    }
  
    var activeField = "";
    self.OnFilterByRowChanged = function(name, dbid)
    {
        if(arguments.length > 0 && activeField != dbid)
        {
            var params = CloneHash(self.args);
            
            AddHash(params, "filterby", dbid);
            TableRefresh( self.name + "Result", params);
            TableRefresh( self.name + "FilterBy", params);
            TableRefresh( self.name + "Filtered", params);
            activeField = dbid;
        }
    }
    self.SelectedRender = function(self, row, coldef, cell, val)
    {
        var chk = null;
        if(cell.firstChild != null)
            chk = cell.firstChild;
        else
        {    
            chk = document.createElement("INPUT");
            chk.type = "checkbox";
            cell.appendChild(chk);
        }
        
        chk.checked = val;
        chk.setAttribute("table", self.name);
        var rowid = -1;
        try{
            rowid = self.table.rows[row.rowIndex-1][self.DbRowId];
        }catch(e){;}
        
        chk.style.display = (rowid == null || rowid == -1)? "none": "inline";
        chk.setAttribute("rowid", rowid);
        
        AddHandler(chk, "click", DoChk);
    }
    self.OnFilterByEnabled = function(self, row, coldef, cell, val)
    {
        if(row.getAttribute("arranged")) return;
        if( val == "0")
            row.style.color = "gray";
        else
            row.style.color = "";
    }
    self.OnDeleteFilter = function()
    {
        TableRefresh( self.name + "Result", TableGetArgs(self.name + "Result"));        
        TableRefresh( self.name + "FilterBy", TableGetArgs(self.name + "FilterBy"));
    }
    self.OnArrangedByRender = function(self, row, coldef, cell, val)
    {
        var div = row.cells[0].firstChild;
        if(row.getAttribute("arranged") != null && div != null)
        {
            if( val == "")
            {
                row.removeAttribute("disabled");
                row.style.color = "";
            }
            else
            {
                if(div.innerHTML.indexOf(val) == 0)
                {
                    AddHandler(row, "click", self.SelectRowByRow);
                    AddHandler(row, "mouseover", self.onRowMouseOver);
                    AddHandler(row, "mouseout", self.onRowMouseOut);
                    row.style.color = "green";
                }
                else
                {
                    RmvHandler(row, "click", self.SelectRowByRow);
                    RmvHandler(row, "mouseover", self.onRowMouseOver);
                    RmvHandler(row, "mouseout", self.onRowMouseOut);
                    row.style.color = "red";
                }
            }
        }
    }
    
    var DoChk = function(obj, evt)
    {
        var name = obj.getAttribute("table");
        var rowid = obj.getAttribute("rowid");

        var params = CloneHash(self.args);
        AddHash(params, "rowid", rowid);
        AddHash(params, "value", obj.checked);

        CustServerCall("Select", self.name, params, OnSelectRes)
    }
    var OnRes = function()
    {
        TableRefresh( self.name + "Result", self.args);
        TableRefresh( self.name + "FilterBy", self.args);
        TableRefresh( self.name + "Filtered", self.args);
    }
    var OnSelectRes = function()
    {
        TableRefresh( self.name + "FilterBy", self.args);
    }
    self.PivotReport = function()
    {
        var name = self.name +  "Result";
        var params = "type=pivot&obj=" + name;
        params += "&xsl=" + self.xsl;
        params += "&args=" + escape(JSON.stringify(self.args));
        
        window.open('PAT/Export/PVReport.aspx?' + params);
    }
    self.ExportTo = function(format)
    {
        var name = self.name +  "Result";
        var params = "export="+format+"&obj=" + name;
        params += "&args=" + escape(JSON.stringify(self.args));
        
        window.open('PAT/Export/Export.aspx?' + params);
    }
    self.Refresh = function()
    {
        CustServerCall("Refresh", self.name, self.args, OnRes);
    }
    
    Init();    
}
