/*===================================================================
*   建立日期：2004年5月17日
*
*   作者：   杜保发  东南融通系统工程有限公司
*
*
*   一、设计思想：
*
*   1)  利用DHTML技术，以表格、行、列、单元格为操作对象，
*       把表格看成一个内存表，动态对数据进行存储和操作。
*   2)  通过活动单元格内嵌编辑控件实现对活动单元格的编辑。
*   3)  利用对象的克隆(object.cloneNode)技术，
*       可对比表格编辑前后的数据变化，从而仅提交改动过的
*       数据到服务端。
*
*
*   二、实现功能
*
*   (a) 支持动态增加、修改以及删除表格行。
*
*   (b) 支持单元格内嵌任何控件。(如input，select，
*       textarea及第三方控件，如日历控件，树形控件等)。
*
*   (c) 支持列排序(只在客户端排序) 。
*
*   (d) 支持标识选中行，(如第一列的活动行会
*       显示一个小三角形，表示该行为活动行)。
*
*   (e) 支持Select对象的text与value的处理。
*       即是否同时保存Select的text和value，
*       还是仅保存value。
*
*   (f) 支持单元格默认值的设定(新增行时，自动赋默认值)、
*       空值校验(设置单元格不为空时，会提示必须输入，
*       同时焦点定位该单元格)。
*
*   (g) 支持箭头移动记录：
*       按向上箭头，记录上移一行；
*       按向下箭头，记录下移一行，如果到记录尾并且可编辑，则增加一行；
*       Ctrl+Insert，增加一行；Ctrl+Delete，删除一行。
*
*   (h) 保存时只提交改变过的数据。
*       提交时形成一串字符数据(仅提交修改，删除，新增过的数据)，
*       用换行符\n分隔行，制表符(\t)分隔列。
*       第一列为id(新增时为常量newRowId值,其它为数据库表的id)，
*       第二列为state(新增为常量insertState值，
*       修改为常量updateState值,删除为常量deleteState值)，
*       其它列按表格列顺序生成(对于列savable="false"不生成）。
*
*   三、操作详解
*
*   (1)通过document的onload事件，完成把数据到表格的装载。
*       同时，完成以下初始化工作
*       a.复制生成一个新表，用于保存初始数据，保存时与目标表作对照，
*         可知道那些数据作过修改
*       b.生成第一行(标题行)对象，以变取得列数及每列的属性
*
*   (2)在<table ...>里可以设置以下全局属性:
*       a.readonlyable:表格是否可编辑。
*           "true"：不可编辑，"false":可编辑，默认 "false";
*           如<table readonlyable="true" ...>...</table>
*
*       b.keyable:是否可用键盘操作表格;
*           "true"：可用键盘操作，"false":不可用键盘操作，默认"true";
*           如<table keyable="true" ...>...</table>；
*           有如下键盘操作：
*           上箭头，上移一行；
*           下箭头，下移一行，如果到记录尾并且可编辑，则增加一行；
*           Ctrl+Inert:插入一行;
*           Ctrl+Delete:删除一行;
*
*   (3)在标题行(介于<thead>与</thead>之间的行)的
*      每列上可以设置以下属性:
*       a.property:内嵌编辑控件容器的名称，指span对象的id，
*                  如果不指定，则当前列不可编辑
*       b.required:活动单元格(当前行的当前列)是否必输，
*                  如果不指定，默认"false"。
*       c.defaultvalue:新增时，列的初始值。如果不指定，为空
*       d.storable:设置列的存储值与显示值是否不同,在处理代码
*                  与名称的时候很有用。如果不指定，默认"false"。
*                  "true"：存储值与显示值不同，
*                  必须在数据单元格设置storevalue的值
*                  如：<td storevalue="code">name</td>
*       e.savetext:是否保存显示的文本，
*                  必须设置storeable="true"才能生效。
*                  即是否同时保存存储值与显示值。
*                  如果不指定，默认"false"，即只存存储值。
*       f.indexed:是否为非数据列，一般用来保存记录指标符及列的顺序
*       g.sortable:是否对列进行排序，默认不排序
*       h.sorttype:排序的列按什么方式排序，
*                  必须设置sorttable="true"才能生效。
*                  有以下几种排序方式：
*                  "number":按数字排序
*                  "date":按日期排序
*                  "caseinsensitive":按不区分大小写字符排序；
*                   除以上三种外，设置其它值(或不设置)
*                   都按区分大小写字符排序
*       i.display:本列是否显示,用于处理隐藏列，但仍生成串提交。
*                   "true":显示，"false"：不显示，默认显示
*       j.savable:是否保存该列，默认为"true"，为"false"时不生成串提交
*
*   (4)在数据行(介于<tbody>与</tbody>之间的行)的每列上可以设置以下属性:
*       a.id:用于保存每条记录的id，新增时取常量newRowId的值
*       b.storevalue:保存记录的存储值，需要设置标题标对应列的storable为"true"
*
*   (5)必须设置表格的id，同时通过init("tableid")赋给document.onload;
*
*   (6)设置编辑控件的内容，一般一列设置一个包函编辑控件的容器
*
*
*   四、使用示例
*
*  
*  
*  
*   <html>
*   <head>
*   <title>通用等级认定方案编辑</title>
*   <!--引入编辑表格的样式文件-->
*   <link  href="<c:url value="/css/edittable.css"/>"
*           rel="stylesheet" type="text/css">
*   <!--引入编辑表格的脚本控制文件-->
*   <script src="<c:url value="/script/edittable.js"/>"
*       type="text/javascript"></script>
*   <!--引入通用脚本控制文件-->
*   <script src="<c:url value="/script/common.js"/>"
*       type="text/javascript"></script>
*   </head>
*   <!-- 初始化表格 -->
*   <body topmargin="0" leftmargin="0" onload="init('mytable');" >
*   <table id="mytable" cellspacing=1px cellpadding=1px>
*   <thead onclick="sortColumn(event);"> <!--表格排序 -->
*   <tr >
*   <td  property="custlevel" sortable="true"
*        storable="true" required="true">等级名称</td>
*   <td  property="indexname" sortable="true"
*        storable="true" savetext="true" required="true">指标</td>
*   <td  property="indexfromvalue" sortable="true"
*        sorttype="number" required="true">起始值</td>
*   <td  property="indextovalue" sortable="true"
*        sorttype="number">截止值</td>
*   </tr> </thead>
*   <tbody  onclick="getActiveRow(event);">
*   <! - 循环取出数据绑定到动态表格 -->
*   <c:forEach var="item" items="${list}">
*   <! -- 设置数据行的ID -->
*   <tr id="<c:out value="${item.GRADESETTINGID}"/>">
*   <td storevalue="<c:out value="${item.CUSTLEVEL}"/>">
*       <c:out value="${item.CUSTLEVELNAME}"/>
*   </td>
*   <td storevalue="<c:out value="${item.INDEXNO}"/>">
*       <c:out value="${item.INDEXNAME}"/>
*   </td>
*   <td><c:out value="${item.FROMINDEXVALUE}"/></td>
*   <td><c:out value="${item.TOINDEXVALUE}"/></td>
*   </tr>
*   </c:forEach>
*   </tbody></table>
*   <! - 下面设置每列的内嵌的编辑控件,
*        通过使用span块元素把编辑控件动态装载到活动单元格内 -->
*   <span id="custlevel"  style="display:none">
*       <select name="edit_custlevel">
*           <ltcm:listgradename "/>
*       </select>
*   </span>
*   <span id="indexname"  style="display:none">
*       <select name="edit_indexname">
*           <ltcm:listctmgradeindex/>
*       </select>
*   </span>
*   <span id="indexfromvalue" style="display:none">
*       <input  type=text name="edit_indexfromvalue"
*               onkeypress='typefloat(this);'>
*   </span>
*   <span id="indextovalue" style="display:none">
*       <input  type=text name="edit_indextovalue"
*               onkeypress='typefloat(this);'>
*   </span>
*   </body></html>
*
**===================================================================*/

//当前行对象
var activeRow=null;
//当前行的背景色
var activeRowBgColor = "#e0f0ff";
//其它行的背景色
var inactiveRowBgColor = "white";
//编辑控件前缀，每个编辑控件的名字为：编辑控件前缀+包函编辑控件容器span的id
var controlPrefix = "edit_";
//第一行，即标题行对象
var firstRow;
//表格的列数
var colsCount;
//源表格：保存初始数据，提交时与目标表格对比，可取出变化的数据
var sourceTable;
//目标表格，也即当前操作的表格
var destTable;
//用换行符来分隔行
var rowSeparator = "\n";
//用制表符来分隔列
var colSeparator = "\t";
//新增行的ID
var newRowId = "0";
//插入状态的分隔符
var insertState = "insert";
//修改状态的分隔符
var updateState = "update";
//删除状态的分隔符
var deleteState = "delete";
//单元格为空的替代符，如果为空，必须用一个不为空的字符代替，
//传到中间层时才能分解相同的列数
var emptySwap  = " ";
//有效数据列开始计算的序号，有时设置第一列为导航列，因此有效列是从第二列开始
var colInitIndex;
//有效数据行开始计算的序号，从标题行的行数开始计算;
var rowInitIndex;
//排序向上箭头结点对象
var arrowUp;
//排序向下箭头结点对象
var arrowDown;
//表格是否可编辑
var readonlyable;
//键盘是否可操作
var keyable;
//选中行的ID
var rowId="";
//以下为信息提示
var noTableIdMessage = "没有设置表格的id！";
var requiredInputMessage = "不能为空！";
var reloadMessage = "数据已被修改，确实要取消所有的修改吗？";

//初始化表格
function init(table,bActive)
{
    if (typeof(table) == 'undefined')
    {
        alert(noTableIdMessage);
        return;
    }
    if (typeof(bActive) == 'undefined') bActive = true;
    destTable = document.getElementById(table);
	//从现有表克隆一个新表，提交时与该新表做数据比较，
	//可发现哪些数据做过修改
    sourceTable = destTable.cloneNode(true);
	//取得第一行对象
    firstRow = destTable.rows(0);
	//取得表格列数
    colsCount = firstRow.cells.length;
	//取得表格标题行的行数
    rowInitIndex = destTable.tHead.rows.length;
	//取得指标符所在列的序号,一般设置为第一列
    colInitIndex = getIndexed();
	//初始化表格排序功能
    initSortTable();
	//初始化键盘操作表格功能
    setKeyTable();
	//激活键盘操作表格功能
	activeKeyTable();
	//设置表格是否可编辑
    setReadonlyTable();
	//处理列是否显示
	initDisplayCell();
	//激活表格，使表格可操作
	if (bActive) activeTable();
}

function setKeyTable(value)
{
	if (typeof(value) != 'undefined')
	{
		keyable = value;
		return;
	}

    var s = destTable.keyable;
    if (typeof(s) == 'undefined')
    {
        s = "true";
    }
	keyable = (s.toLowerCase() == "false")?false:true;
}


function setReadonlyTable(value)
{
	if (typeof(value) != 'undefined')
	{
		readonlyable = value;
		return;
	}

    var s = destTable.readonlyable;
    if (typeof(s) == 'undefined')
    {
        s = "false";
    }
    readonlyable = (s.toLowerCase() == "false")?false:true;
}

function activeKeyTable()
{
	 document.onkeydown = keyEvent;
}

function initDisplayCell()
{
    var result=0;
	var rowsLen = destTable.rows.length;
    for(var i=0;i<colsCount;i++)
    {
		if (getCellAttribute("display",i)=="false")
        {
           for(var j=0;j<rowsLen;j++)
		   {
			   destTable.rows(j).cells(i).style.display = "none";
		   }
        }
    }
}

//判断前面的列是否为非有效数据列
function getIndexed()
{
    var result=0;
    for(var i=0;i<colsCount;i++)
    {
        if (getCellAttribute("indexed",i)!="true")
        {
            break;
        }
        result += 1;
    }
    return result;
}

function activeTable()
{
	var tempActiveRow = activeRow==null?destTable.rows(destTable.rows.length-1):activeRow;
    setActiveRow(tempActiveRow);
}

//单击取得活动行
//参数e:捕捉单击的事件点
function getActiveRow(e)
{
    try
    {
        var _activeElement;
        var _activeColumn;
        var _activeRow;
        _activeElement= e.srcElement;
        _activeColumn = getParent(_activeElement, "TD");
        _activeRow=_activeColumn.parentNode;
        if (_activeRow == activeRow) return;
        if (!canSave()) return;
        setActiveRow(_activeRow);
        activeControl(_activeColumn.cellIndex);
    } catch (e)
    {
    }
}

function reset()
{
     activeRow=null;
}

function getParent(el, pTagName)
{
    if (el == null)
        return null;
    else if (el.nodeType == 1 && el.tagName.toLowerCase() == pTagName.toLowerCase())
        return el;
    else
        return getParent(el.parentNode, pTagName);
}


function addRow(rowData)
{
    if (readonlyable) return;
    if (!canSave()) return;
    if (typeof(rowData) == 'undefined') rowData = null;
    var rowsCount   = destTable.rows.length;
    var currRow = destTable.insertRow();
    setActiveRow(currRow,true,true,rowData);
}

function removeRow(index)
{
    if (activeRow==null) return;
    if (readonlyable) return;
    if (typeof(index) == 'undefined') index = activeRow.rowIndex;
    if (destTable.rows.length>rowInitIndex && destTable.rows.length>=(index+1))
    {
        destTable.deleteRow(index);
        setActiveRow(destTable.rows(destTable.rows.length-1));
    }
}

function modifyRow(index)
{
    var _activeRow;
    if (typeof(index) == 'undefined' || destTable.rows.length<(index+1))
        _activeRow = activeRow;
    else
        _activeRow = destTable.rows(index);
    if (_activeRow == null) return ;
    setActiveRow(_activeRow);
}

function canSave(bNoControl)
{
    if (activeRow == null || activeRow.rowIndex<1) return true;
    if (readonlyable) return true;
    if (typeof(bNoControl) == 'undefined') bNoControl = false;
    var required;
    for(var j=colInitIndex;j<colsCount;j++)
    {
        required = getCellAttribute("required",j);
        title = trim(firstRow.cells(j).innerText);
        lastChar =  title.substr(title.length-1,1);//取得最后一个字符
        if (lastChar == '5' || lastChar == '6') //如果当前列有排序字符(上、下箭头对应的字符为5,6)
            title = title.substr(0,title.length-1); // 去调最后一个排序字符
        if (required == "true" && getCellDisplayValue(activeRow.rowIndex,j,bNoControl)=="")
        {
            alert(title+requiredInputMessage);
            setActiveRow(activeRow,false);
            activeControl(j);
            return false;
        }
    }

    for(var k=colInitIndex;k<colsCount;k++)
    {
        if (getCellAttribute("storable",k) == "true")
            activeRow.cells(k).storevalue = getCellStoreValue(activeRow.rowIndex,k,bNoControl);
        activeRow.cells(k).innerText = getCellDisplayValue(activeRow.rowIndex,k,bNoControl);
        activeRow.cells(k).style.padding ="2px";
    }
    reset();
    return true;
}

//取得更新的数据
function getUpdateData()
{
    if (!canSave()) return "false";
    var destTableRowLen = destTable.rows.length;//取得表格行数
    var result="";
    var element;
    var rowid;
    //以下加上修改及增加的数据
    for (var i=rowInitIndex;i<destTableRowLen;i++)
    {
        if (isEmptyRow(i)) continue; //如果整行都为空，则不加上该行
        rowid = destTable.rows(i).id;
        //如果修改行没有改变，则不加上
        if (rowid!=newRowId && !isUpdateRow(destTable.rows(i),rowid,sourceTable)) continue;
        //第一行：id
        result += (result!=""?rowSeparator+rowid:rowid);
        //第二行：state
        result += colSeparator+(rowid==newRowId?insertState:updateState);
        //其它行：数据
        for(var j=colInitIndex;j<colsCount;j++)
        {
           //如果列的属性savable="false"，则不生成该列的值
            if  (getCellAttribute("savable",j) == "false") continue;
            element = formatStr(getValue(destTable.rows(i).cells(j),j));
            result += colSeparator+element;
        }
    }
    var sourceTableRowLen = sourceTable.rows.length;
    //以下加上删除了的数据
    for (var l=rowInitIndex;l<sourceTableRowLen;l++)
    {
        rowid = sourceTable.rows(l).id;
        if (getRowIndexById(rowid,destTable)>0) continue;
        //第一行：id
        result += (result!=""?rowSeparator+rowid:rowid);
        //第二行：state
        result += colSeparator+deleteState;
        //其它行：数据
        for(var k=colInitIndex;k<colsCount;k++)
        {
           //如果列的属性savable="false"，则不生成该列的值
            if  (getCellAttribute("savable",k) == "false") continue;        
            element = formatStr(getValue(sourceTable.rows(l).cells(k),k));
            result += colSeparator+element;
        }
    }
    reset();
    return result;
}

function isModified()
{
    return (getUpdateData()==""?false:true);
}

function reload()
{
    if (!isModified()) return;
    if (!window.confirm(reloadMessage)) return;

    var len = destTable.rows.length;
    var len2 = sourceTable.rows.length;
    var cell;
    var currRow;

    for(var i=len-1;i>=rowInitIndex;i--)
    {
        destTable.deleteRow(i);
    }
    for(var j=rowInitIndex;j<len2;j++)
    {
        currRow = destTable.insertRow();
        setIndexedRow(currRow,true);
        for(var l=colInitIndex;l<colsCount;l++)
        {
            currRow.id = sourceTable.rows(j).id;
            cell = currRow.insertCell(l);
            if (getCellAttribute("storable",l) == "true")
                cell.storevalue = sourceTable.rows(j).cells(l).storevalue;
            cell.innerText = sourceTable.rows(j).cells(l).innerText;
        }
    }
}

function isUpdateRow(sourceRow,sourceRowId,compareTable)
{
    var rowIndex = getRowIndexById(sourceRowId,compareTable);
    var destRow = compareTable.rows(rowIndex);
    for(var i=colInitIndex;i<colsCount;i++)
    {
        if (trim(sourceRow.cells(i).innerText) != trim(destRow.cells(i).innerText))
            return true;
    }
    return false;
}

function getRowIndexById(sourceRowId,compareTable)
{
    var len = compareTable.rows.length;
    for(var i=rowInitIndex;i<len;i++)
    {
        if (compareTable.rows(i).id == sourceRowId)
            return i;
    }
    return 0;
}

function sourceTableData()
{
    var rows = sourceTable.rows.length;//取得表格行数
    var result="";
    var element;
    var rowid;
    for (var i=rowInitIndex;i<rows;i++)
    {
        rowid = sourceTable.rows(i).id;
        result += (result!=""?rowSeparator+rowid:rowid);
        for(var j=colInitIndex;j<colsCount;j++)
        {
            element = formatStr(getValue(sourceTable.rows(i).cells(j),j));
            result+= colSeparator+element;
        }
    }
    reset();
    return result;
}

function destTableData()
{
    if (!canSave()) return "false";
    var rows = destTable.rows.length;//取得表格行数
    var result="";
    var element;
    var rowid;
    for (var i=rowInitIndex;i<rows;i++)
    {
        if (isEmptyRow(i)) continue; //如果整行都为空，则不加上该行
        rowid = destTable.rows(i).id;
        result += (result!=""?rowSeparator+rowid:rowid);
        for(var j=colInitIndex;j<colsCount;j++)
        {
            element = formatStr(getValue(destTable.rows(i).cells(j),j));
            result+= colSeparator+element;
        }
    }
    reset();
    return result;
}

function isEmptyRow(nRow)
{
    var isEmpty = true;
    for(var i=colInitIndex;i<colsCount;i++)
    {
        if (trim(destTable.rows(nRow).cells(i).innerText)!= "")
        {
            isEmpty = false;
            break;
        }
    }
    return (isEmpty);
}


function formatStr(s)
{
  return (trim(s) == ""?emptySwap:s);
}

//设置指定行为活动行
function setActiveRow(row,bTransfor,bNew,rowData)
{
    if (row == null) return;
    if (row.rowIndex<1) return;

    if (typeof(bTransfor) == 'undefined') bTransfor = true;
    if (typeof(bNew) == 'undefined') bNew = false;
    if (typeof(rowData) == 'undefined') rowData = null;
    clearTable();
    setIndexedRow(row,bNew);
    if (bTransfor && !readonlyable) transforRow(row,bNew,rowData);
    setRow(row,bTransfor);
    activeControl();
	//取得活动行的ID
	rowId = row.id;
}

//清除表格背景色及记录指示符(如果有)
function clearTable()
{
    var len = destTable.rows.length;
    for (var i=rowInitIndex;i<len;i++)
    {
        destTable.rows(i).style.backgroundColor=inactiveRowBgColor;
        if (colInitIndex==0) continue;//没有包含有指示符的列
        if (destTable.rows(i).cells(colInitIndex-1) != null)
        {
            destTable.rows(i).cells(colInitIndex-1).innerText = "";
        }
    }
}

//指定行是显示编辑控件还是显示纯文本
function transforRow(row,bNew,rowData)
{
    try
    {
        var cellValue;
        var rowDataArr;
        if (typeof(rowData) == 'undefined') rowData = null;
        if (rowData!=null)
        {
            rowDataArr = rowData.split(colSeparator);
        }
        for(var j=colInitIndex;j<colsCount;j++)
        {
            if (bNew)
            {
                if (rowData!=null)
                {
                    cellValue = rowDataArr[j-colInitIndex];
                } else {
                    cellValue = getCellAttribute("defaultvalue",j,false);
                }
                row.id = newRowId;
                row.insertCell(j).innerHTML = attachControl(row.rowIndex,j,cellValue);
            } else {
                if (rowData!=null)
                {
                    cellValue = rowDataArr[j-colInitIndex];
                } else {
                    cellValue = trim(getCellStoreValue(row.rowIndex,j));
                }
                row.cells(j).innerHTML = attachControl(row.rowIndex,j,cellValue);
            }
        }
    } catch(e) {
    }
}
//设置第一列为记录指示列，第一列有一个右三角形为活动行
function setIndexedRow(row,bNew)
{
    if (colInitIndex>0)
    {
        if (bNew)
        {
            row.insertCell(colInitIndex-1).innerText = "4";
            row.cells(colInitIndex-1).className="arrow";
        } else {
            row.cells(colInitIndex-1).innerText = "4";
            row.cells(colInitIndex-1).className="arrow";
       }
    }
}

function setRow(row,bTransfor)
{
    if (row==null || row.rowIndex<1) return;
    if (row == activeRow) return;
    if (typeof(bTransfor) == 'undefined') bTransfor = true;
    activeRow=row;
    if (bTransfor && !readonlyable)
    {
        for(var i=colInitIndex;i<colsCount;i++)
        {
             if  (getCellAttribute("display",i)=="false")
                activeRow.cells(i).style.display = "none";
            if (getCellAttribute("property",i) != "")
            activeRow.cells(i).style.padding = "0px";
        }
    }
    activeRow.style.backgroundColor=activeRowBgColor;
}
//内嵌编辑控件到当前单元格上
function attachControl(nRow,nCol,value)
{
    var property,spanObj;
    property = getCellAttribute("property",nCol);
    if (property == "" || readonlyable)   return value;
    setCellValue(nRow,nCol,value);
    spanObj = document.getElementById(property);
    if (typeof(spanObj) == 'undefined') return value;
    return spanObj.innerHTML;
}

function getValue(cell,j)
{
    if (cell == null) return "";
    if (typeof(cell.storevalue) == "undefined")
    {
        return cell.innerText;
    }
    else
    {
        if (getCellAttribute("savetext",j) == "true")
        {
            return cell.storevalue + colSeparator + cell.innerText;
        }
        else
        {
            return cell.storevalue;
        }
    }
}
//得到单元格实际存储值
function getCellStoreValue(rowIndex,colIndex,bNoControl)
{
    if (typeof(bNoControl)=='undefined')   bNoControl=false;
    return getCellValue(rowIndex,colIndex,true,bNoControl);
}

//得到单元格显示值
function getCellDisplayValue(rowIndex,colIndex,bNoControl)
{
    if (typeof(bNoControl)=='undefined')   bNoControl=false;
    return getCellValue(rowIndex,colIndex,false,bNoControl);
}
//根据属性名及单元格序号得到单元格属性值
function getCellAttribute(atrributeName,colIndex,bTransfer)
{
    if (typeof(bTransfer) == 'undefined') bTransfer = true;
    var atrributeValue = firstRow.cells(colIndex).getAttribute(atrributeName);
    atrributeValue = (atrributeValue == null || atrributeValue=="")
                        ?"":atrributeValue;
    return (bTransfer?atrributeValue.toLowerCase():atrributeValue);
}

//得到单元格值
function getCellValue(rowIndex,colIndex,bStore,bNoControl)
{
    if (typeof(rowIndex)=='undefined') rowIndex=rowInitIndex;
    if (typeof(colIndex)=='undefined') colIndex=colInitIndex;
    if (typeof(bStore)=='undefined')   bStore=false;
    if (typeof(bNoControl)=='undefined')   bNoControl=false;
    var property,controlObj,cell,activeRowIndex;
    property = getCellAttribute("property",colIndex);
    cell = destTable.rows(rowIndex).cells(colIndex);
    controlObj = document.getElementById(controlPrefix+property);
    activeRowIndex = activeRow==null?0:activeRow.rowIndex;
    //表格只读时，直接取得表格单元的显示值
	if (readonlyable)
	{
		return cell.innerText;
	}
	//只读行或非活动行，直接取得表格单元的显示或存储值
    if (property == "" || rowIndex != activeRowIndex || bNoControl)
    {
        if (bStore && (typeof(cell.storevalue) != "undefined"))
        {
            return cell.storevalue;
        }else {
            return cell.innerText;
        }
    }

    //活动行，取得活动表格单元内嵌控件显示值
    try
    {
        if (controlObj.tagName == "SELECT")
        {
            if (bStore)
            {
                return controlObj.options[controlObj.selectedIndex].value;
            } else {
                return controlObj.options[controlObj.selectedIndex].innerText;
            }
        } else
            return controlObj.value;
    }
    catch (e)
    {
        return controlObj.value;
    }

}

function setCellValue(rowIndex,colIndex,value)
{
    if (typeof(rowIndex)=='undefined') rowIndex=rowInitIndex;
    if (typeof(colIndex)=='undefined') colIndex=colInitIndex;

    var property,controlObj;
    property = getCellAttribute("property",colIndex);

    if (property == "")
    {
        destTable.rows(rowIndex).cells(colIndex).innerText = value;
        return;
    }
    controlObj = document.getElementById(controlPrefix+property);
    controlObj.value = value;
}

function activeControl(i)
{
    try
    {
        if (activeRow==null) return;
        if (typeof(i)=='undefined') i=colInitIndex;
        //得到当前列的列名
        var property = getCellAttribute("property",i);
        if (property == "") return;
        //得到当前列的编辑控件对象
        var controlObj = document.getElementById(controlPrefix+property);
        if (controlObj == null) return;
        //设置当前行当前列(当前单元)的焦点
        if (controlObj.tagName == "INPUT")
            controlObj.select();
        controlObj.focus();
    }
    catch (e)
    {
    }

}


function initSortTable()
{
    try
    {
        arrowUp = document.createElement("SPAN");
        var tn = document.createTextNode("6");
        arrowUp.appendChild(tn);
        arrowUp.className = "arrow";

        arrowDown = document.createElement("SPAN");
        var tn = document.createTextNode("5");
        arrowDown.appendChild(tn);
        arrowDown.className = "arrow";
    } catch (e) {
        //
    }
}
//             sortTable(table,i,el._descending, getCellAttribute("sorttype",el.cellIndex));

function sortTable(tableNode, nCol, bDesc, sType) {
 try {
    var tBody = tableNode.tBodies[0];
    var trs = tBody.rows;
    var a = new Array();

    for (var i=0; i<trs.length; i++) {
        a[i] = trs[i];
    }

    a.sort(compareByColumn(nCol,bDesc,sType));

    for (var i=0; i<a.length; i++)
    {
        tBody.appendChild(a[i]);
    }
   } catch(e) {
   }
}

function CaseInsensitiveString(s) {
    return String(s).toUpperCase();
}

function parseDate(s) {
    return Date.parse(s.replace(/\-/g, '/'));
}

/* alternative to number function
 * This one is slower but can handle non numerical characters in
 * the string allow strings like the follow (as well as a lot more)
 * to be used:
 *    "1,000,000"
 *    "1 000 000"
 *    "100cm"
 */

function toNumber(s) {
    return Number(s.replace(/[^0-9\.]/g, ""));
}

function compareByColumn(nCol, bDescending, sType)
{
    try {
    var c = nCol;
    var d = bDescending;
    var fTypeCast = String;
	
	sType = !sType ? "string" : sType.toLowerCase();

    if (sType == "number")
        fTypeCast = toNumber;
    else if (sType == "date")
        fTypeCast = parseDate;
    else if (sType == "caseinsensitive")
        fTypeCast = CaseInsensitiveString;

    return function (n1, n2) {
        if (fTypeCast(getInnerText(n1.cells[c])) < fTypeCast(getInnerText(n2.cells[c])))
            return d ? -1 : +1;
        if (fTypeCast(getInnerText(n1.cells[c])) > fTypeCast(getInnerText(n2.cells[c])))
            return d ? +1 : -1;
        return 0;
    };
    } catch(e) {
    }
}

function getInnerText(el) {
    return el.innerText;

    var str = "";

    for (var i=0; i<el.childNodes.length; i++) {
        switch (el.childNodes.item(i).nodeType) {
            case 1: //ELEMENT_NODE
                str += getInnerText(el.childNodes.item(i));
                break;
            case 3: //TEXT_NODE
                str += el.childNodes.item(i).nodeValue;
                break;
        }
    }
    return str;
}

function sortColumn(e)
{
    try
    {
        var tmp, el, tHeadParent;
        tmp = e.srcElement;
        tHeadParent = getParent(tmp, "THEAD");
        el = getParent(tmp, "TD");
        if (tHeadParent == null) return;
        if (getCellAttribute("sortable",el.cellIndex) != "true") return;
        if (el != null) {
            var p = el.parentNode;
            var i;
            if (!canSave()) return;
            if (el._descending) // catch the null
                el._descending = false;
            else
                el._descending = true;

            if (tHeadParent.arrow != null) {
                if (tHeadParent.arrow.parentNode != el) {
                    tHeadParent.arrow.parentNode._descending = null;    //reset sort order
                }
                tHeadParent.arrow.parentNode.removeChild(tHeadParent.arrow);
            }

            if (el._descending)
                tHeadParent.arrow = arrowDown.cloneNode(true);
            else
                tHeadParent.arrow = arrowUp.cloneNode(true);

            el.appendChild(tHeadParent.arrow);

      
			var table = getParent(el, "TABLE");
			var i = getActualCellIndex(table,el);
            sortTable(table,i,el._descending, el.sorttype);
        }
    } catch(e) {
		alert(e);
    }
}

 function getActualCellIndex(table,cell) {
	var firstRow = table.tHead.rows[0];
	var intCellIndex = 0;
	var intTmpCellIndex = 0;

	//当前单击单元是第一行标题或合并为第一行标题
 	if (cell.parentNode.rowIndex==0) 	{
			 for(var i=0;i<cell.cellIndex;i++) {
					intCellIndex+= parseInt(firstRow.cells[i].colSpan,10);
			 }
	} else if (cell.parentNode.rowIndex==1) {
			 var 	len = firstRow.cells.length; 
			 for(var i=0;i<len;i++) {
					var intCells = parseInt(firstRow.cells[i].colSpan,10) ;
					if (intCells==1) {
						  intCellIndex += 1;
					} else {
						if (intCells+ intTmpCellIndex < cell.cellIndex + 1) {
								   intTmpCellIndex += intCells; 
						} else {
							   intCellIndex += 	cell.cellIndex;
							   break;
						}
					}
					
			 }
 	} else {
		  intCellIndex = cell.cellIndex;
	} 
	return  intCellIndex;
 }


//=============================================
//功能：去掉左边的空格
//=============================================
function ltrim(str)
{
    if (str==null)
    {
        return null;
    }
    var rtnStr;
    rtnStr="";
    for (var i=0;i<str.length;i++)
    {
        if (str.charAt(i)!=" ")
        {
            rtnStr=str.substr(i);
            break;
        }
    }
    return rtnStr;
}

//==========================================
//功能：去掉右边的空格
//==========================================
function rtrim(str)
{
    if (str==null)
    {
        return null;
    }
    var rtnStr;
    rtnStr="";
    for (var i=str.length-1;i>=0;i--)
    {
        if (str.charAt(i)!=" ")
        {
            rtnStr=str.substring(0,i+1);
            break;
        }
    }
    return rtnStr;
}

//==========================================
//功能：去掉左右两边的空格
//==========================================

function trim(str)
{
    return(ltrim(rtrim(str)));
}

function keyEvent()
{
	if (!keyable) return;
    //alert(event.keyCode);
    switch (event.keyCode)
    {
        //case 37: //left arrow
        //event.keyCode = 9; //tab
        //break;
        case 38: //up arrow
        movePrevRecord();
        break;
        //case 39: //right arrow
        //event.keyCode = 9;
        //break;
        case 40: //down arrow
        moveNextRecord();
        break;
        case 13: //enter
        if (readonlyable) //表格不可编辑
        {
            destTable.tBodies[0].ondblclick();
        } else {
            event.keyCode = 9;
        }
        break;
		//case 45://insert
		//addRow();
		//break;
		//case 46://delete
		//removeRow();
		//break;
    }
    //ctrl + insert
    if (window.event.ctrlKey && window.event.keyCode == 45)
    {
        addRow();
        return;
    }
    //ctrl+delete
    if (window.event.ctrlKey && window.event.keyCode == 46)
    {
        removeRow();
        return;
    }

}

//移动到上一行
function movePrevRecord()
{
    if (activeRow == null) return;
    var intCurrRow = activeRow.rowIndex;
    if (intCurrRow==rowInitIndex) return; //数据的第一行，不可继续上移
    if (!canSave()) return;
    setActiveRow(destTable.rows(intCurrRow-1));
}

//移动到下一行
function moveNextRecord()
{
    if (activeRow == null) return;
    var intTotalRow = destTable.rows.length;
    var intCurrRow = activeRow.rowIndex;
    if ( intCurrRow== intTotalRow-1) //最后一行，增加新行
    {
        addRow();
    } else {
        if (!canSave()) return;
        setActiveRow(destTable.rows(intCurrRow+1));
    }
}
//屏蔽错误
window.onerror = function() {return false;}
