您的位置:首页 > Web前端 > JavaScript

javascript实现的具有EXCEL功能的table

2010-09-15 14:42 477 查看
用J***ASCRIPT实现了table的单元格合并、拆分,初步具备了EXCEL表格的功能。在网上搜了很多代码,都没有做到真正的单元格合并,要么就是代码的实现方式有问题,我对这些代码进行了整合与修改,形成了可以初步应用于项目的table操作,包括新增行、新增列、单元格合并、合并后的单元格拆分、对要合并的单元格进行是否能进行合并的校验等功能。目前已经在IE 7.0 FireFox 3.6.3下测试通过。



<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>无标题页</title>
    <mce:style type="text/css" rel="stylesheet"><!--
    .tds {
        border-collapse:collapse;
        border-color:#C6D8F0;
        border-style:solid;
        border-width:thin;
    }
    
--></mce:style><style type="text/css" rel="stylesheet" mce_bogus="1">    .tds {
        border-collapse:collapse;
        border-color:#C6D8F0;
        border-style:solid;
        border-width:thin;
    }
    </style>      
    <mce:script language="javascript" type="text/javascript"><!--
    var isIE = (document.all) ? true : false;

    var isIE6 = isIE && ([/MSIE (/d)/.0/i.exec(navigator.userAgent)][0][1] == 6);

    var $ = function (id) {
	    return "string" == typeof id ? document.getElementById(id) : id;
    };

    var Extend = function(destination, source) {
	    for (var property in source) {
		    destination[property] = source[property];
	    }
    };

    var Bind = function(object, fun) {
	    var args = Array.prototype.slice.call(arguments,2);
	    return function() {
		    return fun.apply(object, args);
	    }
    };

    var BindAsEventListener = function(object, fun) {
	    var args = Array.prototype.slice.call(arguments,2);
	    return function(event) {
		    return fun.apply(object, [event || window.event].concat(args));
	    }
    };

    var CurrentStyle = function(element){
	    return element.currentStyle || document.defaultView.getComputedStyle(element, null);
    };

    var addEventHandler = function(oTarget, sEventType, fnHandler) {
	    if (oTarget.addEventListener) {
		    oTarget.addEventListener(sEventType, fnHandler, false);
	    } else if (oTarget.attachEvent) {
		    oTarget.attachEvent("on" + sEventType, fnHandler);
	    } else {
		    oTarget["on" + sEventType] = fnHandler;
	    }
    };

    var removeEventHandler = function(oTarget, sEventType, fnHandler) {
	    if (oTarget.removeEventListener) {
		    oTarget.removeEventListener(sEventType, fnHandler, false);
	    } else if (oTarget.detachEvent) {
		    oTarget.detachEvent("on" + sEventType, fnHandler);
	    } else { 
		    oTarget["on" + sEventType] = null;
	    }
    };
    
    MerTable = function(){
        this.CreatTable=function(tableId,bodyId){
           var _table = document.getElementById (tableId);
           _table.border="1px";
           _table.width="800px";

           for(var i=1;i<10;i++){
                var row=document.createElement ("tr"); 
                row.id=i;
                for(var j=1;j<6;j++){
                    var cell=document.createElement ("td"); 
                    cell.id =i+"/"+j;
                    cell.appendChild(document.createTextNode ("第"+cell.id+"列")); 
                    row.appendChild (cell); 
                }
                $(bodyId).appendChild(row);
           }
           this.Table = _table;       
        },    
        this.init = function(tableId,bodyId){
            this.CreatTable(tableId,bodyId);
            if(!this.Table){return;}
            this.SetOptions();//设置参数
            
            this.TableId = tableId;
            this.BodyId = bodyId;
            this.HoverColor=this.Options.hoverColor;
            this.ActiveColor=this.Options.activeColor;
            this.Hover=this.Options.hover;
            this.Choose=this.Options.choose;
            this.Multiple=this.Options.multiple;
            this.Cancel=this.Options.cancel;
            this.Title=this.Options.title;
            this.DClick=this.Options.dclick;
            this.OnClick=this.Options.onClick;
            this.OnCancel=this.Options.onCancel;
            this.OnMove=this.Options.onMove;
            this.OnDClick=this.Options.onDClick;

            this.AddMouseEvent();  //添加事件
            
            this._CurrentRow=null; //当前移动行
            
            this.SelectedArray=new Array();//设置或返回被选中行的集合        
                   
        },
        this.SortSelected = function(){
            if(this.SelectedArray.length>2)
            {
                this.SelectedArray.sort(function(x,y){
                    var x1 = x.id.split("/");
                    var y1 = y.id.split("/");
                    return (parseInt(x1[0])-parseInt(y1[0]) || parseInt(x1[1])-parseInt(y1[1]));
                })
            }else{
                return;
            }
        },
        this.SetOptions=function(options){
            this.Options={
                hoverColor:"#FFFDD7",        //移动时背景色
                activeColor:"#FFFDD7",       //选中时背景色
                hover:true,                  //是否开启移动行背景色
                choose:true,                //是否开启选择
                multiple:true,             //是否开启多选,开启后按Ctrl可以多选,取消功能需要同时开启
                title:true,                 //是否提示title
                cancel:true,                //是否开启取消功能
                dclick:true,                //是否双击
                onClick:function(){},       //选中时附加方法
                onCancel:function(){},       //取消选择时附加方法,此时取消功能必须开启
                onMove:function(){},         //鼠标移动事件
                onDClick:function(){}       //双击
            };
            Extend(this.Options,options||{});
        },   
        this.AddMouseEvent=function(){
            if(this.Hover){
                addEventHandler(this.Table,"mousemove",BindAsEventListener(this, this.MouseMove));
                addEventHandler(this.Table,"mouseout",Bind(this, this.MouseLeave));
            }
            if(this.Choose){
                addEventHandler(this.Table,"click",BindAsEventListener(this, this.MouseClick));
            }
            if(this.DClick){
                //addEventHandler(this.Table,"dblclick",BindAsEventListener(this, this.Edit));
            }            
        },
        this.MouseClick=function(e){
            var elem=this.GetCurrentElem(e);
            if(elem==null){return;}
            var index=this.SelectedIndex(elem);
            if(index<0){
                if(this.Multiple&&this.Cancel){
                    this.AddSelected(elem);
                }
                else{
                    this.Clear();
                    this.AddSelected(elem);
                }
                elem.style.backgroundColor=this.ActiveColor;
                this.OnClick();
            }
            else if(this.Cancel){
                elem.style.backgroundColor= this.Hover ? this.HoverColor : "transparent";
                this.RemoveSelected(elem);
                this.OnCancel();
            }
        },
        this.Clear = function(){
            for(var i=0;i<this.SelectedArray.length;i++){
                this.SelectedArray[i].style.backgroundColor = "transparent";
            }
            this.RemoveAllSelected();
        },        
        //获取当前事件对象
        this.GetCurrentElem = function(e){
            var elem = e.srcElement || e.target;
            if(elem.tagName.toUpperCase()=="TD"){
                return elem;
            }
            return null;
        },
        this.FindById = function(tdId){
            for(var i=0;i<this.SelectedArray.length;i++){
                if(this.SelectedArray[i].id==tdId){
                    return i;
                }
            }
            return -1;            
        },
        this.SelectedIndex=function(elem){
            for(var i=0;i<this.SelectedArray.length;i++){
                if(elem==this.SelectedArray[i]){
                    return i;
                }
            }
            return -1;
        },                
        this.AddSelected = function(elem){
            this.SelectedArray.push(elem);
        },
        //从集合中移除
        this.RemoveSelected = function(elem){
            var index=this.SelectedIndex(elem);
            this.SelectedArray.splice(index,1);
        },
        this.RemoveAllSelected = function(){
            var count=this.SelectedArray.length;
            this.SelectedArray.splice(0,count);
        },        
        this.MouseMove=function(e){
            //清除选中内容
            document.selection? document.selection.empty() : window.getSelection();
            
            var elem=this.GetCurrentElem(e);
            if(elem==null){return;}
            if(this._CurrentRow!=null){
                if(this.SelectedIndex(this._CurrentRow)<0){
                    this._CurrentRow.style.backgroundColor = "transparent";
                }
                else{
                    this._CurrentRow.style.backgroundColor=this.ActiveColor;
                }
            }
            elem.style.backgroundColor=this.SelectedIndex(elem)<0?this.HoverColor:this.ActiveColor;
            this._CurrentRow=elem;
            //添加title
            if(this.Title){
                var cells=elem.getElementsByTagName("td");
                for(var i=0;i<cells.length;i++){
                    cells[i].title= isIE ? cells[i].innerText.replace(/(^/s*)|(/s*$)/g, "") : cells[i].textContent.replace(/(^/s*)|(/s*$)/g, "");
                }
            }
            this.OnMove();
        },
        //移出表格后,恢复原色
        this.MouseLeave=function(){
            if(this._CurrentRow!=null&&this.SelectedIndex(this._CurrentRow)<0){
                this._CurrentRow.style.backgroundColor = "transparent";
                this._CurrentRow=null;
            }
        },
        this.Edit = function(sender){
            var elem=this.GetCurrentElem(sender);
            if(elem==null){return;}        
            if(!elem.lastChild || elem.lastChild.tagName != "TEXTAREA")
            {
                var box = document.createElement("textarea");
                box.style.cssText = "background-color:transparent;border:none; font:12pt 宋体;margin:-2pt -1pt;width:100%; overflow:hidden";
                box.rows = 1;
                if(elem.align) box.style.textAlign = elem.align;
                box.defaultValue = box.value = elem.innerHTML;
                elem.innerHTML = "";
                elem.appendChild(box);
                box.onpropertychange = function()
                {
                    if(this.value) this.style.posHeight = this.scrollHeight;
                }
                box.onblur = function()
                {
                    if(this.value == this.defaultValue)
                    {
                        elem.innerText = this.value;
                        elem.bgColor = "";
                    }
                }
                box.focus();
                elem.bgColor = "#effbff";
            }      
        },             
        this.addRow = function(){
           var length=this.Table.rows.length;
           var tr=document.createElement("tr");
           tr.id=length+1;
           
           var colno = this.getTableCols(this.Table);
           
           for(i=1;i<=colno;i++){
               var td=document.createElement ("td"); 
               td.id=tr.id+"/"+i;
               td.appendChild(document.createTextNode("第"+td.id+"列"));
               tr.appendChild(td);           
           }
           $(this.BodyId).appendChild (tr);     
        },
        this.addCols = function(){
            var colNum = 0;
            for(var i=0;i<this.Table.rows.length;i++)
            {
                if(this.Table.rows[i].cells.length>colNum){
                    colNum = this.Table.rows[i].cells.length;
                }
            }
            
            for(var i=0;i<this.Table.rows.length;i++)
            {
                var cell=document.createElement ("td"); 
                cell.id =(i+1)+"/"+(colNum+1);
                cell.innerHTML="第"+(i+1)+"/"+(colNum+1)+"列";
                this.Table.rows[i].appendChild(cell);
            }         
        },
        this.deleteCols = function(){
            var colNum = 0;
            for(var i=0;i<this.Table.rows.length;i++)
            {
                if(this.Table.rows[i].cells.length>colNum){
                    colNum = this.Table.rows[i].cells.length;
                }
            }

            if(colNum<=1){
                alert("表格的列数不允许少于1");
            }else{
                for(var i=0;i<this.Table.rows.length;i++)
                {
                    var cell = $((i+1)+"/"+(colNum))
                    if(cell){
                        var parentElement=cell.parentNode;
                        
                        if(parentElement){        
                            parentElement.removeChild(cell);
                        }
                    }         
                } 
            }
        },
        this.deleteRow = function(){
            var row_no = this.Table.rows.length;
            if(row_no<=1){
                alert("表格的行数不允许少于1");
            }else{
                var row = $(row_no+"");
                
                if(row){
                    var parentElement=row.parentNode;
                    
                    if(parentElement){        
                        parentElement.removeChild(row);
                    }
                }
            }
        },
        this.getTableCols = function(table){
            var tableObject = table;
            if (!tableObject.rows || !tableObject.rows[0] || !tableObject.rows[0].cells){
                return 0;
            }
            var cells = tableObject.rows[0].cells;
            var cols = 0;
            for (var col = 0; col < cells.length; col++){
                if (cells[col].colSpan && cells[col].colSpan > 1){
                    cols = cols + cells[col].colSpan;
                }
                else{
                    cols = cols + 1;
                }
            }
            return cols;      
        },
        this.GetMaxRowNum = function(){        
            var MaxRowNum = 0;
            
            for(var i =0;i<this.SelectedArray.length;i++){            
                if(parseInt(this.SelectedArray[i].id.split("/")[0])>MaxRowNum){
                    MaxRowNum = parseInt(this.SelectedArray[i].id.split("/")[0]);
                }
            }
            return MaxRowNum;
        },
        this.GetMaxColNum = function(){
            var MaxColNum = 0;
            
            for(var i =0;i<this.SelectedArray.length;i++){            
                if(parseInt(this.SelectedArray[i].id.split("/")[1])>MaxColNum){
                    MaxColNum = parseInt(this.SelectedArray[i].id.split("/")[1]);
                }
            }
            return MaxColNum;        
        },
        this.GetMinRowNum = function(){
            var MinRowNum = 999999;
            
            for(var i =0;i<this.SelectedArray.length;i++){            
                if(parseInt(this.SelectedArray[i].id.split("/")[0])<MinRowNum){
                    MinRowNum = parseInt(this.SelectedArray[i].id.split("/")[0]);
                }
            }
            return MinRowNum;        
        },
        this.SplitCells = function(){
            if(this.SelectedArray.length<=0){
                alert("请选择要拆分的单元格!");
            }else{
                for(var i =0;i<this.SelectedArray.length;i++){
                    if((this.SelectedArray[i].colSpan>1)&&(this.SelectedArray[i].rowSpan>1)){
                        var cellPoint = this.SelectedArray[i].id.split("/")
                        var colNum = parseInt(cellPoint[1]);
                        var rowNum = parseInt(cellPoint[0]);
                        for(var m = this.SelectedArray[i].colSpan;m>0;m--){
                            for(var j = this.SelectedArray[i].rowSpan;j>0;j--){
                                //var cell=document.createElement("td"); 
                                var cellY = colNum+m-1;
                                var cellX = rowNum+j-1;
                                //cell.id =cellX+"/"+cellY;
                                //cell.innerHTML="第"+cellX+"/"+cellY+"列"
                                
                                if($(cellX+"/"+cellY)){
                                }else{
                                    var insertCellNum = cellY-1;
                                    for(var d=cellY;d>=0;d--){
                                        if($(cellX+"/"+d)){
                                            insertCellNum = d;
                                            break;
                                        }
                                    }
                                    var x=$(cellX+"").insertCell(insertCellNum);
                                    x.id =cellX+"/"+cellY;
                                    x.innerHTML="第"+cellX+"/"+cellY+"列";                                 
                                    //$(cellX+"").appendChild(cell);                                
                                }
                            }
                        }
                        this.SelectedArray[i].rowSpan = 1;
                        this.SelectedArray[i].colSpan = 1;
                    }else{
                        if(this.SelectedArray[i].colSpan>1 ){
                            var cellPoint = this.SelectedArray[i].id.split("/")
                            var colNum = parseInt(cellPoint[1]);
                            
                            //for(var m = 0;m<= this.SelectedArray[i].colSpan;m++){
                            for(var m = this.SelectedArray[i].colSpan;m>0;m--){                                
                                //var cell=document.createElement ("td"); 
                                var cellY = colNum+m-1;
                                //var cellId = cellPoint[0]+"/"+cellY;
                                //cell.id =cellPoint[0]+"/"+cellY;
                                //cell.innerHTML="第"+cellPoint[0]+"/"+cellY+"列";
                                //if($(cell.id)){                                
                                if($(cellPoint[0]+"/"+cellY)){
                                }else{                                
                                    var x=$(cellPoint[0]+"").insertCell(cellY-1);
                                    x.id =cellPoint[0]+"/"+cellY;
                                    x.innerHTML="第"+cellPoint[0]+"/"+cellY+"列";                                    
                                    //$(cellPoint[0]+"").appendChild(cell);                                
                                }
                            }
                            this.SelectedArray[i].colSpan = 1;
                        }
                        if(this.SelectedArray[i].rowSpan>1){
                            var cellPoint = this.SelectedArray[i].id.split("/")
                            var rowNum = parseInt(cellPoint[0]);
                            
                            for(var m = this.SelectedArray[i].rowSpan;m>0;m--){
                                //var cell=document.createElement ("td"); 
                                var cellX = rowNum+m-1;
                                //cell.id =cellX+"/"+cellPoint[1];
                                //cell.innerHTML="第"+cellX+"/"+cellPoint[1]+"列"
                                if($(cellX+"/"+cellPoint[1])){
                                }else{
                                    var x=$(cellX+"").insertCell(cellPoint[1]-1);
                                    x.id =cellX+"/"+cellPoint[1];
                                    x.innerHTML="第"+cellX+"/"+cellPoint[1]+"列";                                 
                                    //$(cellX+"").appendChild(cell);                                
                                }
                            }                             
                            this.SelectedArray[i].rowSpan = 1;
                        }
                    }
                }
                this.Clear();
                this.RemoveAllSelected();
            }
        },
        this.GetMinColNum = function(){
            var MinColNum = 999999;
            
            for(var i =0;i<this.SelectedArray.length;i++){            
                if(parseInt(this.SelectedArray[i].id.split("/")[1])<MinColNum){
                    MinColNum = parseInt(this.SelectedArray[i].id.split("/")[1]);
                }
            }
            return MinColNum;         
        },        
        this.SaveTable = function(){
            var tx = this.Table.parentNode.innerHTML;
            alert(tx);        
        },
        //对所选的单元格进行校验是否能进行合并
        this.CheckMergeCells = function(){
            if(this.SelectedArray.length<2){
                alert("您所选择的单元格无法合并!");
            }
            
            //循环判断所选单元格是否组成一个矩形,只有形成一个矩形的单元格才能合并
            var addCellArray = [];
            for(var k=0;k<this.SelectedArray.length;k++){ 
                if((this.SelectedArray[k].colSpan>1)&&(this.SelectedArray[k].rowSpan>1)){
                    var cellPoint = this.SelectedArray[k].id.split("/")
                    var colNum = parseInt(cellPoint[1]);
                    var rowNum = parseInt(cellPoint[0]);
                    for(var m = this.SelectedArray[k].colSpan;m>0;m--){
                        for(var j = this.SelectedArray[k].rowSpan;j>0;j--){
                            var cell=document.createElement("td"); 
                            var cellY = colNum+m-1;
                            var cellX = rowNum+j-1;
                            cell.id =cellX+"/"+cellY;
                            
                            if(this.FindById(cell.id)<0){                        
                                addCellArray.push(cell);
                            }                            
                        }
                    }
                }else{                      
                    if(this.SelectedArray[k].colSpan>1 ){
                        var cellPoint = this.SelectedArray[k].id.split("/")
                        var colNum = parseInt(cellPoint[1]);
                        
                        for(var m = this.SelectedArray[k].colSpan;m>0;m--){
                            var cell=document.createElement ("td"); 
                            var cellY = colNum+m-1;
                            cell.id =cellPoint[0]+"/"+cellY;
                            
                            if(this.FindById(cell.id)<0){                        
                                addCellArray.push(cell);
                            }
                        }
                    }
                    if(this.SelectedArray[k].rowSpan>1){
                        var cellPoint = this.SelectedArray[k].id.split("/")
                        var rowNum = parseInt(cellPoint[0]);
                        
                        for(var m = this.SelectedArray[k].rowSpan;m>0;m--){
                            var cell=document.createElement ("td"); 
                            var cellX = rowNum+m-1;
                            cell.id =cellX+"/"+cellPoint[1];
                            if(this.FindById(cell.id)<0){                        
                                addCellArray.push(cell);
                            }
                        }                
                    }
                }
            }  
            
            for(var k=0;k<addCellArray.length;k++){
                this.SelectedArray.push(addCellArray[k]);
            }
            
            //对所选的单元格进行排序            
            this.SortSelected();                          
            //取得最小的单元格和最大的单元格
            var minRow = this.GetMinRowNum();
            var minCol = this.GetMinColNum();
            var maxRow = this.GetMaxRowNum();
            var maxCol = this.GetMaxColNum();                    

            var canMerge = 0;
            for(var i = minRow;i<=maxRow;i++){
                for(var j=minCol;j<=maxCol;j++){
                    var isMerge = false;
   
                    var cellId = i+"/"+j;
                    for(var k=0;k<this.SelectedArray.length;k++){                        
                        if(this.SelectedArray[k].id==cellId){
                            isMerge = true;
                            break;
                        }
                    }
                    
                    if(isMerge == false)
                    {
                        canMerge = canMerge+1;
                        break;
                    }
                }
            }
            
            if(canMerge >0){
                return false;
                //alert("您所选择的单元格无法合并!");
            }else{
                return true;
                //alert("您所选择的单元格已经合并!");
            }
        },
        this.MergeCells = function(){
            if(!this.CheckMergeCells()){
                alert("您所选择的单元格无法合并!");
                this.Clear();
                this.RemoveAllSelected();
                return false;
            }
        
            var minRow = this.GetMinRowNum();
            var minCol = this.GetMinColNum();
            var maxRow = this.GetMaxRowNum();
            var maxCol = this.GetMaxColNum();
            
            //同行合并
            if(minRow==maxRow){
                var distance = parseInt(maxCol)-parseInt(minCol);//得到列差值   
                var tmpCell = $(minRow+"/"+minCol);
                tmpCell.colSpan = distance+1;
                for(var i=0;i<this.SelectedArray.length;i++){
                    if(this.SelectedArray[i].id!=tmpCell.id){
                        var parentElement=this.SelectedArray[i].parentNode;    
                        if(parentElement){        
                            parentElement.removeChild(this.SelectedArray[i]);
                        }
                    }
                }
            }
            
            //同列合并
            if(minCol == maxCol){
                var distance = parseInt(maxRow)-parseInt(minRow);//得到列差值   
                var tmpCell = $(minRow+"/"+minCol);
                tmpCell.rowSpan = distance+1;
                for(var i=0;i<this.SelectedArray.length;i++){
                    if(this.SelectedArray[i].id!=tmpCell.id){
                        var parentElement=this.SelectedArray[i].parentNode;    
                        if(parentElement){        
                            parentElement.removeChild(this.SelectedArray[i]);
                        }
                    }
                }
            }
            
            //多行多列合并
            if((minRow!=maxRow)&&(minCol != maxCol)){
                var row_distance = parseInt(maxRow)-parseInt(minRow);//得到行差值
                var col_distance = parseInt(maxCol)-parseInt(minCol);//得到列差值
                var tmpCell = $(minRow+"/"+minCol);
                tmpCell.rowSpan = row_distance+1; //行合并
                tmpCell.colSpan = col_distance+1; //列合并  
                
                for(var i=0;i<this.SelectedArray.length;i++){
                    if(this.SelectedArray[i].id!=tmpCell.id){
                        var parentElement=this.SelectedArray[i].parentNode;    
                        if(parentElement){        
                            parentElement.removeChild(this.SelectedArray[i]);
                        }
                    }
                }                              
            }
            this.Clear();
            this.RemoveAllSelected();
        }
    }     
    
// --></mce:script>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <table border="1" cellpadding="0" cellspacing="0" width="95%">
            <tr>
                <td>
                    <input id="addNewRow" type="button" value="新增行" onclick="mertable.addRow();" />
                    <input id="addNewCol" type="button" value="新增列" onclick="mertable.addCols();"/>
                    <input id="mergerCells" type="button" value="合并单元格" onclick = "mertable.MergeCells()"/>
                    <input id="splitCells" type="button" value="拆分单元格" onclick = "mertable.SplitCells()" />
                    <input id="deleteRow" type="button" value="删除行" onclick = "mertable.deleteRow()"/>
                    <input id="deleteCol" type="button" value="删除列" onclick = "mertable.deleteCols()"/>
                    <input id="save" type="button" value="保存" onclick="mertable.SaveTable()"/></td>
            </tr>
            <tr>
                <td>
                    <table id="designer"  class=tds cellpadding=2 cellspacing=2>
                        <tbody id="designerBody"></tbody>
                    </table>
                </td>
            </tr>
        </table>
        <mce:script language="javascript"><!--
            var mertable = new MerTable();
            mertable.init("designer","designerBody");
        
// --></mce:script>
    </div>
    </form>
</body>
</html>




运行后的效果图如下:



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: