在ASP.NET中应用Excel:(8)为HTML表格增加编辑功能

我们可以为HTML表格增加编辑功能,具体表现为:当用户单击某个单元格(术语:激活),该单元格位置上出现编辑框,背景也与其它未激活的单元格不同,以示区别,当用户完成编辑后,单元格内容被更新。如果用户使用方向键,则变化单元格的激活状态。整个情况类似于Excel中的操作。

要实现上述目的,我们首先要处理单元格的在激活事件(onactivate)和去激活事件(ondeactivate),具体实现如下:

[jscript] view plaincopy
  1. // 单元格的在激活事件  
  2.   
  3. function onCellActivate ()  
  4.   
  5. {  
  6.   
  7.     var parentTbl = this.parentElement.parentElement; // 单元格的父容器,在HTML元素中,单元格是<TD>,其父就是<TR>,<TR>的父就是<TABLE>  
  8.   
  9.       
  10.   
  11.     // 清除前一个被激活单元格状态  
  12.   
  13.     if ( parentTbl.activeCell != null )  // 前一个在激活的单元格存在?  
  14.   
  15.     {  
  16.   
  17.         if ( parentTbl.activeCell != this ) // 与当前相同是不是同一个?  
  18.   
  19.         {  
  20.   
  21.             parentTbl.activeCell.style.backgroundColor = ''// 不是同一个,则清除背景  
  22.   
  23.             parentTbl.activeCell.innerHTML = parentTbl.activeCell.dataField.length > 0 ? parentTbl.activeCell.value2 : ' '// 恢复显示内容  
  24.   
  25.         }  
  26.   
  27.     }  
  28.   
  29.       
  30.   
  31.     if ( parentTbl.activeCell != this ) // 如果当前单元格和前一个被激活的单元格不是同一个  
  32.   
  33.     {  
  34.   
  35.         parentTbl.activeCell = this// 设置当前单元格为被激活的单元格  
  36.   
  37.         // 插入编辑框  
  38.   
  39.         this.innerHTML = '<INPUT type="text" value="' + this.dataField +   
  40.   
  41.                         '" style="border-top:none;border-left:none;border-right:none;border-bottom:1px dashed black;background-color:transparent;font-weight: bold; color: black;" ' +  
  42.   
  43.                         ' onkeydown="return onTextBoxKeydown();" ' +  
  44.   
  45.                         ' onchange="return onTextBoxChange();" ></INPUT>';  
  46.   
  47.                           
  48.   
  49.         var textBox = this.children[0]; // 取得对象  
  50.   
  51.           
  52.   
  53.         textBox.width = this.offsetWidth; // 设置宽度  
  54.   
  55.           
  56.   
  57.         textBox.align = 'right'// 对齐方式,不起作用  
  58.   
  59.         textBox.setActive();  
  60.   
  61.         textBox.focus();  
  62.   
  63.           
  64.   
  65.         this.style.backgroundColor = '#CCCCFF'// 设置显眼的背景,表示处于激活状态  
  66.   
  67.     }  
  68.   
  69. }  
  70.   
  71.   
  72.   
  73. // 单元格的去激活事件  
  74.   
  75. // 当单元格被激活,编辑框出现,单元格就会失去激活,此事件就会激发  
  76.   
  77. function onCellDeactivate ()  
  78.   
  79. {  
  80.   
  81.     var parentTbl = this.parentElement.parentElement; // 获取Table  
  82.   
  83.       
  84.   
  85.     if ( parentTbl.activeCell != this ) // 如果被激活单元格不是当前单元格?  
  86.   
  87.     {  
  88.   
  89.         this.innerHTML = this.dataField.length > 0 ? this.value2 : ' '// 恢复显示内容  
  90.   
  91.     }  
  92.   
  93. }  

当然,HTML不像窗口程序,可以在设计时就挂接事件,因此,我们需要在页面加载完成后就为除行列标头之外的单元格挂接事件,进行初始化,同时可以进行还有跨行的单元格合并:

[jscript] view plaincopy
  1. document.onreadystatechange = function() // 在页面加载完成后,初始化TABLE  
  2.   
  3. {  
  4.   
  5.     if ( this.readyState == 'complete' )  
  6.   
  7.     {  
  8.   
  9.         initTable(); // 初始化  
  10.   
  11.     }  
  12.   
  13. }  
  14.   
  15.   
  16.   
  17. function initTable()  
  18.   
  19. {  
  20.   
  21.     for(var idx in document.worksheet ) // 遍历所有表  
  22.   
  23.     {  
  24.   
  25.         var tbl = $get(document.worksheet[idx].table); // 获取TABLE对象  
  26.   
  27.           
  28.   
  29.         forvar i = tbl.cells.length - 1; i > 1; i-- ) // 从后往前遍历所有单元格  
  30.   
  31.         {  
  32.   
  33.             var ctrl = tbl.cells[i]; // 单元格对象  
  34.   
  35.               
  36.   
  37.             if ( ctrl.cellIndex > 0 && ctrl.parentElement.rowIndex > 0) // 第一行和第一列不处理  
  38.   
  39.             {  
  40.   
  41.                 ctrl.onactivate = onCellActivate;       // 单元格的在激活事件  
  42.   
  43.                 ctrl.ondeactivate = onCellDeactivate;   // 单元格的去激活事件  
  44.   
  45.                   
  46.   
  47.                 if ( ctrl._rowspan && ctrl._rowspan > 1 && ctrl.parentElement.rowIndex + 1 < tbl.rows.length ) // 如果需要合并单元格,则合并之  
  48.   
  49.                 {  
  50.   
  51.                     forvar n = 1; n < ctrl._rowspan; n++ ) // 合并  
  52.   
  53.                     {  
  54.   
  55.                         if ( ctrl.cellIndex < tbl.rows[ctrl.parentElement.rowIndex + 1].cells.length )  
  56.   
  57.                             tbl.rows[ctrl.parentElement.rowIndex + 1].deleteCell(ctrl.cellIndex);  
  58.   
  59.                     }  
  60.   
  61.                       
  62.   
  63.                     ctrl.rowSpan = ctrl._rowspan; // 设置跨度  
  64.   
  65.                 }  
  66.   
  67.             }  
  68.   
  69.         }  
  70.   
  71.     }  
  72.   
  73. }  

注意到document.worksheet对象没有?这个对象在生成表格时添加并填充,包括所有的工作表名字和表格id。其格式如下:

[jscript] view plaincopy
  1. document.worksheet = { 'table'null// HTML table的id ,  
  2.   
  3.                        'name''' // 工作表名字  
  4.   
  5.                       };  

要使方向键起作用,需要为编辑框添加按键事件处理:

[jscript] view plaincopy
  1. // 编辑框的按键事件  
  2.   
  3. function onTextBoxKeydown()  
  4.   
  5. {  
  6.   
  7.     var sender = event.srcElement, // 事件属性  
  8.   
  9.         code = event.keyCode;  
  10.   
  11.           
  12.   
  13.     if ( sender.parentElement &&   
  14.   
  15.         sender.parentElement.tagName == 'TD')   
  16.   
  17.     {  
  18.   
  19.         var tbl = sender.parentElement.parentElement.parentElement, // 表格对象  
  20.   
  21.             col = sender.parentElement.cellIndex,                   // 列号  
  22.   
  23.             row = sender.parentElement.parentElement.rowIndex;      // 行号  
  24.   
  25.                
  26.   
  27.         switch(code) // 处理按键代码  
  28.   
  29.         {  
  30.   
  31.         case 37: // left  
  32.   
  33.             {  
  34.   
  35.                 sender.onchange(); // 手动激发改动事件和在激活事件  
  36.   
  37.                 if ( col > 1 ) // 第一列是标头,不需要激活  
  38.   
  39.                     tbl.rows[row].cells[col - 1].onactivate();  
  40.   
  41.             }  
  42.   
  43.             break;  
  44.   
  45.         case 38: // top  
  46.   
  47.             {  
  48.   
  49.                 sender.onchange();  
  50.   
  51.                 if ( row > 1 )  
  52.   
  53.                     tbl.rows[row - 1].cells[col].onactivate();  
  54.   
  55.             }  
  56.   
  57.             break;  
  58.   
  59.         case 39: // right  
  60.   
  61.             {  
  62.   
  63.                 sender.onchange();  
  64.   
  65.                 if ( col < tbl.rows[row].cells.length - 1 )  
  66.   
  67.                     tbl.rows[row].cells[col + 1].onactivate();  
  68.   
  69.             }  
  70.   
  71.             break;  
  72.   
  73.         case 13:  
  74.   
  75.         case 40: // down  
  76.   
  77.             {  
  78.   
  79.                 sender.onchange();  
  80.   
  81.                 if ( row < tbl.rows.length - 1 )  
  82.   
  83.                     tbl.rows[row + 1].cells[col].onactivate();  
  84.   
  85.                   
  86.   
  87.                 return false;  
  88.   
  89.             }  
  90.   
  91.             break;  
  92.   
  93.         }// switch  
  94.   
  95.     }  
  96.   
  97.           
  98.   
  99.     return true;  
  100.   
  101. }  

改动编辑框的内容后,还需要更新单元格内容和持有的数据,这需要处理onchange事件:

[jscript] view plaincopy
  1. // 编辑框的改变事件  
  2.   
  3. function onTextBoxChange()  
  4.   
  5. {  
  6.   
  7.     var src = event.srcElement; // 事件属性  
  8.   
  9.       
  10.   
  11.     if ( src.parentElement &&   
  12.   
  13.         src.parentElement.tagName == 'TD' )   
  14.   
  15.     {  
  16.   
  17.         var val = src.value.trim(); // 去掉空格  
  18.   
  19.           
  20.   
  21.         if ( val != src.parentElement.dataField ) // 内容有变化?  
  22.   
  23.         {   // 更新数据域  
  24.   
  25.             src.parentElement.dataField = val;  
  26.   
  27.             src.parentElement.value2 = val;  
  28.   
  29.             src.parentElement.hasFormula = /=.*/.test(val); // 使用正则表达式判断是否是公式  
  30.   
  31.         }  
  32.   
  33.     }  
  34.   
  35. }  

好了,现在我们的HTML表格具有类似于Excel的编辑功能了。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

阅读更多
个人分类: asp.net
上一篇在ASP.NET中应用Excel:(7)表格尺寸的计算
下一篇ASP.NET中应用Excel:(9)实现表格的自动增长
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭