- 浏览: 1254135 次
- 性别:
- 来自: 杭州
文章分类
- 全部博客 (399)
- 心情故事 (12)
- java (115)
- linux (55)
- 关系型数据库 (35)
- struts,jsf,spring (11)
- jdbc,hibernate,ibatis (11)
- jsp,jstl,c:tag,标签库 (2)
- ejb,webservice (1)
- tomcat,jboss,jetty,weblogic,websphere (15)
- java网络编程 (6)
- java线程 (0)
- js,jquery,json,xml,dom,html.regex (25)
- 设计模式 (6)
- BUG记录 (2)
- ant (2)
- jsp,servlet (4)
- swing (6)
- lucene+nutch (6)
- log4j (2)
- windows doc (2)
- ruby (1)
- ruby on rails (3)
- 操作系统网络 (18)
- apache 错误 (1)
- tomcat (10)
- jboss (9)
- jetty (9)
- weblogic (9)
- websphere (10)
- apache (2)
- AIX的iostat命令查看系统磁盘的使用情况 (1)
- oracle 统计一个表格有多少列 (1)
- Exception in thread "main" java.security.KeyStoreException: Windows-MY not found (1)
- jsp (1)
- jstl (1)
- c:tag (1)
- 标签库 (1)
- struts (1)
- jsf (1)
- spring (2)
- oracle,sqlplus (2)
- sqlplus (2)
- show errors (1)
- proc (1)
- function (1)
- ORA-06544: PL/SQL: internal error (1)
- arguments: [55916] (1)
- [] (7)
- 终端身份实施文档 (1)
- 重装系统之后飞鸽传书只能看到自己 (1)
- vsftp "上传 553 Could not create file" (1)
- startWebLogic.sh启动失败,提示Error initializing Embedded LDAP Server (1)
- java agent 注册为 windows 服务 (1)
- centos (1)
- svn (1)
- apr (1)
- apr-util (1)
- activemq (2)
- oracle (5)
- mysql (3)
- nosql (3)
- NSIS (1)
- windows wmic (1)
- c 指针 (1)
- c c++ (0)
- jmeter (0)
- 性能测试 (0)
- linux,备份 (2)
- C++ ,Virtual (1)
- windows dos (1)
- android (2)
- 大数据,云计算 (1)
- JVM垃圾收集 (1)
- jdbc (2)
- invoke (1)
- hibernate (1)
- ibatis (1)
- 个人开源项目源码收藏 (1)
- 批处理 (1)
- Mongodb mapreduce (8)
- kettle (1)
- Mongodb capped (1)
- mongodb gridfs (1)
- Mongodb 入门基础知识 (1)
- mongodb (8)
- hadoop2.5.1 (1)
- hadoop (4)
- eclipse (1)
- hdfs fs (1)
- elipse hadoop plugin (1)
- PHP相关知识 (1)
- js (1)
- jquery (1)
- json (1)
- xml (1)
- dom (1)
- html.regex (1)
- 网络知识 (1)
- nginx (1)
- docker (1)
- 测试 (1)
- nodejs (1)
- iptables (1)
- linux gitlab (1)
最新评论
-
July01:
最近了解到一款StratoIO打印控件,功能如下:1、Html ...
web页面调用window.print()函数实现打印的功能 -
hxdtech:
非常感谢!
我在学习ibatis时的培训ppt -
zmwxiaoming:
what 能连数据库不错
SOLR的学习整理 -
springdata_springmvc:
java程序语言学习教程 地址http://www.zuida ...
java获取当前操作系统的信息 -
huanzei:
整理的不错,
oracle lpad函数
js操作html的table,包括添加行,添加列,删除行,删除列,合并单元格(未实现)
记得以前面试的时候遇到过这样一个问题:有一个表格,然后有4个输入框,一个合并 按钮,输入框是这样的,从第几行到第几行,从第几列到第几列,然后点击按钮,合并 。当时我从学校出来,js知识只是知道一些,根本做不到!现在想想,其实这个问题也还是考基础功夫是否扎实!大家有兴趣可以自己做做看,测下自己是不是能够做出来。题目的截图:
第1/1列 | 第1/2列 | 第1/3列 | 第1/4列 | 第1/5列 |
第2/1列 | 第2/2列 | 第2/3列 | 第2/4列 | 第2/5列 |
第3/1列 | 第3/2列 | 第3/3列 | 第3/4列 | 第3/5列 |
第4/1列 | 第4/2列 | 第4/3列 | 第4/4列 | 第4/5列 |
第5/1列 | 第5/2列 | 第5/3列 | 第5/4列 | 第5/5列 |
第6/1列 | 第6/2列 | 第6/3列 | 第6/4列 | 第6/5列 |
第7/1列 | 第7/2列 | 第7/3列 | 第7/4列 | 第7/5列 |
第8/1列 | 第8/2列 | 第8/3列 | 第8/4列 | 第8/5列 |
第9/1列 | 第9/2列 | 第9/3列 | 第9/4列 | 第9/5列 |
从第 行到 行 | |
从第 列到 列 |
现在做这个问题,看起来简单,但我还是花了很长时间,可能是我的思路不对吧?主要就是用js来操作html,我现在实现了添加行,删除行,添加列,删除列 ,但合并单元格却不能完整的实现 ,主要是表格会乱掉 。现在把这个问题发出来,有兴趣的同仁可以自己在有空的时候研究下,看自己能不能做出来!主要是合并单元格的问题!也可以帮我看看合并单元格的问题。
我自己实现的部分代码:
html部分 写道
<body onLoad="init();">
<table id="table" align="center">
<tbody id="newbody"></tbody>
</table>
<div>
<table width="800px" border="1px" align="center">
<tr><td align="center"><input type="button" id="addRow" name="addRow" onClick="addRow();" value="添加行"/></td>
<table id="table" align="center">
<tbody id="newbody"></tbody>
</table>
<div>
<table width="800px" border="1px" align="center">
<tr><td align="center"><input type="button" id="addRow" name="addRow" onClick="addRow();" value="添加行"/></td>
<td align="center"><input type="button" id="delRow" name="delRow" onClick="removeRow();" value="删除行"/></td>
</tr>
<tr><td align="center"><input type="button" id="delCell" name="delCell" onClick="removeCell();" value="删除列"/></td>
<tr><td align="center"><input type="button" id="delCell" name="delCell" onClick="removeCell();" value="删除列"/></td>
<td align="center"><input type="button" id="addCell" name="addCell" onClick=" addCell();" value="添加列"/></td>
</tr>
<tr><td align="center" colspan="2"><input type="button" id="addRows" name="addRows" onClick="addRow_withInsert();" value="添加行"/></td></tr>
</table>
</div>
<div>
<table width="800px" border="1px" align="center">
<tr><td>从第<input type="text" id="beginRow" name="beginRow" value=""/> 行到 <input type="text" name="endRow" id="endRow" value=""/> 行</td><td rowspan="2" id="test"><input type="button" name="hebing" id="hebing" value="合并" onClick="rebulid();"/> </td></tr>
<tr><td>从第<input type="text" name="beginCol" id="beginCol" value=""/> 列到<input type="text" name="endCol" id="endCol" value=""/> 列</td></tr>
</table>
</div>
</body>
<tr><td align="center" colspan="2"><input type="button" id="addRows" name="addRows" onClick="addRow_withInsert();" value="添加行"/></td></tr>
</table>
</div>
<div>
<table width="800px" border="1px" align="center">
<tr><td>从第<input type="text" id="beginRow" name="beginRow" value=""/> 行到 <input type="text" name="endRow" id="endRow" value=""/> 行</td><td rowspan="2" id="test"><input type="button" name="hebing" id="hebing" value="合并" onClick="rebulid();"/> </td></tr>
<tr><td>从第<input type="text" name="beginCol" id="beginCol" value=""/> 列到<input type="text" name="endCol" id="endCol" value=""/> 列</td></tr>
</table>
</div>
</body>
生成表格,采用appendChild 写道
function init(){
_table=document.getElementById ("table");
_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);
}
document.getElementById("newbody").appendChild (row);
}
}
_table=document.getElementById ("table");
_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);
}
document.getElementById("newbody").appendChild (row);
}
}
添加行,使用appendChild方法 写道
function addRow(){
var length=document.getElementById("table").rows.length;
/*document.getElementById("newbody").insertRow(length);
document.getElementById(length+1).setAttribute("id",length+2);*/
var tr=document.createElement("tr");
tr.id=length+1;
var td=document.createElement("td");
for(i=1;i<4;i++){
td.id=tr.id+"/"+i;
td.appendChild(document.createTextNode("第"+td.id+"列"));
tr.appendChild(td);
}
document.getElementById("newbody").appendChild (tr);
}
var length=document.getElementById("table").rows.length;
/*document.getElementById("newbody").insertRow(length);
document.getElementById(length+1).setAttribute("id",length+2);*/
var tr=document.createElement("tr");
tr.id=length+1;
var td=document.createElement("td");
for(i=1;i<4;i++){
td.id=tr.id+"/"+i;
td.appendChild(document.createTextNode("第"+td.id+"列"));
tr.appendChild(td);
}
document.getElementById("newbody").appendChild (tr);
}
添加行的另一种方法insertRow 写道
function addRow_withInsert(){
varrow=document.getElementById("table").insertRow( document.getElementById("table").rows.length);
var rowCount =document.getElementById("table").rows.length;
var countCell=document.getElementById("table").rows.item(0).cells.length;
for(var i=0;i<countCell;i++){
var cell=row.insertCell(i);
cell.innerHTML="新"+(rowCount)+"/"+(i+1)+"列";
cell.id=(rowCount)+"/"+(i+1);
}
}
varrow=document.getElementById("table").insertRow( document.getElementById("table").rows.length);
var rowCount =document.getElementById("table").rows.length;
var countCell=document.getElementById("table").rows.item(0).cells.length;
for(var i=0;i<countCell;i++){
var cell=row.insertCell(i);
cell.innerHTML="新"+(rowCount)+"/"+(i+1)+"列";
cell.id=(rowCount)+"/"+(i+1);
}
}
删除行,采用deleteRow(row Index) 写道
/*删除行,采用deleteRow(row Index)*/
function removeRow(){
/* var row=document.getElementById("2");
var index=row.rowIndex;
alert(index);*/
document.getElementById("newbody").deleteRow(document.getElementById(document.getElementById("table").rows.length).rowIndex);
}
function removeRow(){
/* var row=document.getElementById("2");
var index=row.rowIndex;
alert(index);*/
document.getElementById("newbody").deleteRow(document.getElementById(document.getElementById("table").rows.length).rowIndex);
}
添加列,采用insertCell(列位置)方法 写道
function addCell(){
/*document.getElementById("table").rows.item(0).cells.length
用来获得表格的列数
*/
for(var i=0;i<document.getElementById("table").rows.length;i++){
var cell=document.getElementById("table").rows[i].insertCell(2);
cell.innerHTML="第"+(i+1)+"/"+3+"列";
}
}
/*document.getElementById("table").rows.item(0).cells.length
用来获得表格的列数
*/
for(var i=0;i<document.getElementById("table").rows.length;i++){
var cell=document.getElementById("table").rows[i].insertCell(2);
cell.innerHTML="第"+(i+1)+"/"+3+"列";
}
}
删除列,采用deleteCell(列位置)的方法 写道
/*删除列,采用deleteCell(列位置)的方法*/
function removeCell(){
for(var i=0;i<document.getElementById("table").rows.length;i++){
document.getElementById("table").rows[i].deleteCell(0);
}
}
function removeCell(){
for(var i=0;i<document.getElementById("table").rows.length;i++){
document.getElementById("table").rows[i].deleteCell(0);
}
}
合并单元格(未实现) 写道
我的代码有问题,主要是表格会乱掉,一直没有改好
:
function rebulid(){
var beginRow=document.getElementById("beginRow").value;/*开始行*/
var endRow=document.getElementById("endRow").value;/*结束行*/
var beginCol=document.getElementById("beginCol").value;/*开始列*/
var endCol=document.getElementById("endCol").value;/*结束列*/
var tempCol=beginRow+"/"+beginCol;/*定位要改变属性的列*/
alert(tempCol);
var td=document.getElementById(tempCol);
/*删除要合并的单元格*/
for(var x=beginRow;x<=endRow;x++){
for(var i=beginCol;i<=endCol;i++){
if(x==beginRow){
document.getElementById("table").rows[x].deleteCell(i+1);
}
else{
document.getElementById("table").rows[x].deleteCell(i);
}
}
}
td.rowSpan=(endRow-beginRow)+1;
}
function rebulid(){
var beginRow=document.getElementById("beginRow").value;/*开始行*/
var endRow=document.getElementById("endRow").value;/*结束行*/
var beginCol=document.getElementById("beginCol").value;/*开始列*/
var endCol=document.getElementById("endCol").value;/*结束列*/
var tempCol=beginRow+"/"+beginCol;/*定位要改变属性的列*/
alert(tempCol);
var td=document.getElementById(tempCol);
/*删除要合并的单元格*/
for(var x=beginRow;x<=endRow;x++){
for(var i=beginCol;i<=endCol;i++){
if(x==beginRow){
document.getElementById("table").rows[x].deleteCell(i+1);
}
else{
document.getElementById("table").rows[x].deleteCell(i);
}
}
}
td.rowSpan=(endRow-beginRow)+1;
}
- 动态生成table.rar (1.6 KB)
- 下载次数: 3021
评论
36 楼
mingyuan0824
2009-09-20
这个东西作出来维护太费劲了,去年公司要开发一个WEB版的EXCEL当时刚刚接触JS,写了整整4各月才弄完,号要求能在线编辑表格,存成报表的格式。什么合并拆分单元格啊,函数,多个表合成一个报表什么的。提供实时存储。字体,边框样式、范围选择什么的,功能一大堆,不让使用任何框架,后来发现维护很困难,过段时间在看,逻辑关系自己都忘记了。不过只能兼容IE。
35 楼
shuaijie506
2009-09-18
我对js操作TABLE比较熟悉,经常使用。
其实合并和拆分单元格的技术并不复杂,最关键的是用户的使用体验上,和Excel的体验差远了,所以我没有专门做过类似Excel的功能。
关于操作单元格,有一个地方需要注意,那就是行号和列号,因为有合并单元格的情况出现,所以用tbl.rows[i].cells[j]并不能取到第i行第j列的单元格,我的方法是操作前对table的html对象建立单元格的一个二维数组,取第i行第j列的单元格直接用tbl.cells[i][j],在进行单元格操作时需要维护这个二维数组。其实如果真要开发这样的东西,可以自己建立一个JS对象,封装好对表格的操作,这样逻辑上更清晰一些。
行的操作:
合并,先用deleteCell删除第2个以及以后的TD,再修改第一个TD的rowSpan,这里需要注意的是不要从前往后删,最好是从后往前删,或者只删第N个,删M次,这样就达到了删除第N到第N+M个TD的目的了。(PS:看楼主的代码好像就犯了这个错)
拆分,更好做,修改RowSpan,再insertCell就行了。
至于列的操作,和行的操作是类似的。
其实合并和拆分单元格的技术并不复杂,最关键的是用户的使用体验上,和Excel的体验差远了,所以我没有专门做过类似Excel的功能。
关于操作单元格,有一个地方需要注意,那就是行号和列号,因为有合并单元格的情况出现,所以用tbl.rows[i].cells[j]并不能取到第i行第j列的单元格,我的方法是操作前对table的html对象建立单元格的一个二维数组,取第i行第j列的单元格直接用tbl.cells[i][j],在进行单元格操作时需要维护这个二维数组。其实如果真要开发这样的东西,可以自己建立一个JS对象,封装好对表格的操作,这样逻辑上更清晰一些。
行的操作:
合并,先用deleteCell删除第2个以及以后的TD,再修改第一个TD的rowSpan,这里需要注意的是不要从前往后删,最好是从后往前删,或者只删第N个,删M次,这样就达到了删除第N到第N+M个TD的目的了。(PS:看楼主的代码好像就犯了这个错)
拆分,更好做,修改RowSpan,再insertCell就行了。
至于列的操作,和行的操作是类似的。
34 楼
zjxingkongkk
2009-09-18
楼主太强大了~~down下来看了之后才知道js真的这么强大
正好解决了一个大难题~~忽忽
正好解决了一个大难题~~忽忽
33 楼
soni
2009-09-17
楼上的想法和我类似,首先对于这类操作,一定要建立一个2维数组来保存表格的单元格。以后的操作根据这个矩阵来实现。
另外,补充一点,ie的colSpan属性太让人崩溃了。
另外,补充一点,ie的colSpan属性太让人崩溃了。
32 楼
busy882376
2009-08-21
js果然很强
31 楼
jdai84
2009-08-19
正在找的一些东西。。谢谢楼主
30 楼
jejwe
2009-08-13
<p> </p>
<pre name="code" class="js">var TableApi;
(function () {
var MyDom = Helper.Dom;
var MyCore = Helper.Core;
TableApi = {
/**
* 获取table元素的单元格分布矩阵
* @param table
*/
getMatrix : function (table) {
var matrix = [];
for (var rowIndex = 0, rCnt = table.rows.length; rowIndex < rCnt; rowIndex++) {
if (!matrix[rowIndex]) {
matrix[rowIndex] = [];
}
for (var cellIndex = 0, cCnt = table.rows[rowIndex].cells.length; cellIndex < cCnt; cellIndex++) {
var columnIndex = cellIndex;
//In case there's are any horizontal or vertical spans before this cell
while (matrix[rowIndex][columnIndex]) {
columnIndex++;
}
var cell = table.rows[rowIndex].cells[cellIndex];
//Fill the corresponding matrix points
for (var i = 0; i < cell.rowSpan; i++) {
if (!matrix[rowIndex + i]) {
matrix[rowIndex + i] = [];
}
for (var j = 0; j < cell.colSpan; j++) {
matrix[rowIndex + i][columnIndex + j] = cell;
}
}
}
}
return matrix;
},
/**
* 合并单元格分布矩阵中选中的单元格
* @param matrix
*/
merge : function (matrix) {
var maxRowIndex = 0;
var minRowIndex = matrix.length - 1;
var maxColumnIndex = 0;
var minColumnIndex = matrix[0].length - 1;
var rowIndex, columnIndex, rCnt, cCnt;
//decide if selected cells region is mergable
for (rowIndex = 0,rCnt = matrix.length; rowIndex < rCnt; rowIndex++) {
for (columnIndex = 0,cCnt = matrix[0].length; columnIndex < cCnt; columnIndex++) {
if ($(matrix[rowIndex][columnIndex]).hasClass('selected')) {
if (rowIndex > maxRowIndex) {
maxRowIndex = rowIndex;
}
if (rowIndex < minRowIndex) {
minRowIndex = rowIndex;
}
if (columnIndex > maxColumnIndex) {
maxColumnIndex = columnIndex;
}
if (columnIndex < minColumnIndex) {
minColumnIndex = columnIndex;
}
}
}
}
var mergable = true;
for (rowIndex = minRowIndex; rowIndex <= maxRowIndex && mergable; rowIndex++) {
for (columnIndex = minColumnIndex; columnIndex <= maxColumnIndex; columnIndex++) {
if (!$(matrix[rowIndex][columnIndex]).hasClass('selected')) {
mergable = false;
break;
}
}
}
if (mergable) {
//then merge
var cellToMergeInto = matrix[minRowIndex][minColumnIndex];
for (rowIndex = minRowIndex; rowIndex <= maxRowIndex; rowIndex++) {
for (columnIndex = minColumnIndex; columnIndex <= maxColumnIndex; columnIndex++) {
var cell = matrix[rowIndex][columnIndex];
if (cell !== cellToMergeInto) {
for (var i = 0; i < cell.rowSpan; i++) {
for (var j = 0; j < cell.colSpan; j++) {
matrix[rowIndex + i][columnIndex + j] = cellToMergeInto;
}
}
MyDom.removeEl(cell);
}
}
}
cellToMergeInto.colSpan = (maxColumnIndex - minColumnIndex) + 1;
cellToMergeInto.rowSpan = (maxRowIndex - minRowIndex) + 1;
this.cleanUpEmptyRowsAndColumns(matrix);
}
return mergable;
},
/**
* 在单元格分布矩阵中指定行中搜索指定列的前一个单元格
* @param matrix
* @param rowIndex
* @param columnIndex
*/
searchForPreviousCellInRow : function (matrix, rowIndex, columnIndex) {
var columnIndexForPreviousCell = columnIndex;
var previousCell = null;
do{
columnIndexForPreviousCell -= 1;
previousCell = matrix[rowIndex][columnIndexForPreviousCell];
}
while (previousCell && (previousCell.parentNode.rowIndex !== rowIndex));
return previousCell;
},
/**
* 还原合并的单元格
* @param cell
*/
revertMerged : function (cell) {
var table = MyDom.searchUpByTagName(cell, 'TABLE');
var matrix = this.getMatrix(table);
var rowIndex = cell.parentNode.rowIndex;
var columnIndex = matrix[rowIndex].indexOf(cell);
var jCell = $(cell);
var tableApi = this;
MyCore.repeat(cell.colSpan - 1, function () {
jCell.after('<td>');
});
MyCore.repeat(cell.rowSpan - 1, function (time) {
var previousCell = tableApi.searchForPreviousCellInRow(matrix, rowIndex + time, columnIndex);
var task = null;
if (previousCell) {
var jPreviousCell = $(previousCell);
task = function () {
jPreviousCell.after('<td>');
};
}
else {
var jRow = $(table.rows[rowIndex + time]);
task = function () {
jRow.prepend('<td>');
};
}
MyCore.repeat(cell.colSpan, task);
});
cell.colSpan = cell.rowSpan = 1;
},
/**
* 清理单元格分布矩阵中的空行空列
* @param matrix
* @requires the matrix must reflect the current state of the table
*/
cleanUpEmptyRowsAndColumns : function (matrix) {
var table = matrix[0][0].parentNode.parentNode.parentNode;
var rowIndex, columnIndex, cell, cellToCollapse<script src="/javascripts/tinymce/themes/advanced/langs/zh.js" type="text/javascript"><!--mce:0--></script><script src="/javascripts/tinymce/plugins/javaeye/langs/zh.js" type="text/javascript"><!--mce:1--></script>, rCnt, cCnt;
cCnt = matrix[0].length;
//clean up empty rows
for (rowIndex = 0,rCnt = matrix.length; rowIndex < rCnt; rowIndex++) {
var isEmptyRow = true;
for (columnIndex = 0; columnIndex < cCnt; columnIndex++) {
cell = matrix[rowIndex][columnIndex];
if (cell.rowSpan === 1 || cell.parentNode.rowIndex === rowIndex) {
isEmptyRow = false;
break;
}
}
if (!isEmptyRow) {
continue;
}
//recalculate the rowspan
columnIndex = 0;
do{
cellToCollapse = matrix[rowIndex][columnIndex];
cellToCollapse.rowSpan -= 1;
columnIndex += cellToCollapse.colSpan;
}
while (columnIndex < cCnt);
//remove empty tr element
var row = table.rows[rowIndex];
MyDom.removeEl(row);
//remove empty row from matrix
for (var i = rowIndex, iLen = rCnt - 1; i < iLen; i++) {
matrix[i] = matrix[i + 1];
}
matrix.length -= 1;
rCnt--;
//cuz the original next row is now the current row
rowIndex--;
}
//clean up empty columns
for (columnIndex = 0; columnIndex < cCnt; columnIndex++) {
var isEmptyColumn = true;
for (rowIndex = 0; rowIndex < rCnt; rowIndex++) {
cell = matrix[rowIndex][columnIndex];
if (cell.colSpan === 1 || matrix[rowIndex][columnIndex + cell.colSpan - 1] === cell) {
isEmptyColumn = false;
break;
}
}
if (!isEmptyColumn) {
continue;
}
//recalculate the colspan
rowIndex = 0;
do{
cellToCollapse = matrix[rowIndex][columnIndex];
cellToCollapse.colSpan -= 1;
rowIndex += cellToCollapse.rowSpan;
}
while (rowIndex < rCnt);
//remove empty column from matrix
for (rowIndex = 0; rowIndex < rCnt; rowIndex++) {
for (var j = columnIndex, jLen = cCnt - 1; j < jLen; j++) {
matrix[rowIndex][j] = matrix[rowIndex][j + 1];
}
matrix[rowIndex].length -= 1;
}
cCnt--;
//remove corresponding col from colgroup if one exists
var colGroup = $('colgroup', table).get(0);
if (colGroup && colGroup.parentNode === table) {
MyDom.removeEl($('col:eq(' + columnIndex + ')', colGroup).get(0));
}
//cuz the original next column is now the current column
columnIndex--;
}
},
/**
* 根据指定的单元格和坐标获取在单元格分布矩阵中的精确位置
* @param matrix
* @param cell
* @param pageX
* @param pageY
*/
getAccuratePositionInMatrix : function (matrix, cell, pageX, pageY) {
var rowIndex = -1;
var columnIndex = -1;
var found, i, j, jCell, offset, iLen;
if (cell.colSpan === 1) {
columnIndex = matrix[cell.parentNode.rowIndex].indexOf(cell);
}
else {
var firstApperanceColumnIndex = matrix[cell.parentNode.rowIndex].indexOf(cell);
found = false;
//search for a single-column cell within the same column as the multi-column cell, which cuts through pageX horizontally.
for (j = firstApperanceColumnIndex; !found && j < firstApperanceColumnIndex + cell.colSpan; j++) {
for (i = 0,iLen = matrix.length; i < iLen; i++) {
if (matrix[i][j].colSpan !== 1) {
continue;
}
jCell = $(matrix[i][j]);
offset = jCell.offset();
if (offset.left <= pageX && offset.left + jCell.width() >= pageX) {
columnIndex = j;
found = true;
}
break;
}
}
if (!found) {
columnIndex = firstApperanceColumnIndex;
}
}
if (cell.rowSpan === 1) {
rowIndex = cell.parentNode.rowIndex;
}
else {
found = false;
var jLen = matrix[0].length;
//search for a single-row cell within the same row as the multi-row cell, which cuts through pageY vertically.
for (i = cell.parentNode.rowIndex; !found && i < cell.parentNode.rowIndex + cell.rowSpan; i++) {
for (j = 0; j < jLen; j++) {
if (matrix[i][j].rowSpan !== 1) {
continue;
}
jCell = $(matrix[i][j]);
offset = jCell.offset();
if (offset.top <= pageY && offset.top + jCell.height() >= pageY) {
rowIndex = i;
found = true;
}
break;
}
}
if (!found) {
rowIndex = cell.parentNode.rowIndex;
}
}
return {
rowIndex : rowIndex,
columnIndex : columnIndex
};
},
/**
* 重设列宽度
* @param table
* @param columnIndex
* @param width
*/
resizeColumn : function (table, columnIndex, width) {
//Notice that IE6 has problem with applying column width solely by col element. Set table-layout to fixed will solve this problem.
$('colgroup:first col:eq(' + columnIndex + ')', table).css('width', width);
},
/**
* 重设行高度
* @param table
* @param rowIndex
* @param height
*/
resizeRow : function (table, rowIndex, height) {
$('tbody:eq(0) > tr:eq(' + rowIndex + ')', table).css('height', height);
},
/**
* 计算获得table元素的行和列的位置偏移量
* @param matrix
*/
getOffsetsToTableForColumnAndRow : function (matrix) {
var columnOffsets = []; // the offset for the left edge of the columns
var rowOffsets = []; //the offset for the top edge of the rows
var tableOffset = $(MyDom.searchUpByTagName(matrix[0][0], 'TABLE')).offset();
var cell;
var
rCnt = matrix.length,
cCnt = matrix[0].length;
for (var rowIndex = 0; rowIndex < rCnt; rowIndex++) {
for (var columnIndex = 0; columnIndex < cCnt; columnIndex++) {
if (!columnOffsets[columnIndex]) {
cell = matrix[rowIndex][columnIndex];
if (cell.colSpan === 1 || matrix[rowIndex][columnIndex + cell.colSpan - 1] === cell) {
columnOffsets[columnIndex] = $(cell).offset().left - tableOffset.left;
}
}
if (!rowOffsets[rowIndex]) {
cell = matrix[rowIndex][columnIndex];
if (cell.rowSpan === 1 || cell.parentNode.rowIndex === rowIndex) {
rowOffsets[rowIndex] = $(cell).offset().top - tableOffset.top;
}
}
}
}
return {
columnOffsets : columnOffsets,
rowOffsets : rowOffsets
};
},
/**
* 在单元格所在列右边插入新列
* @param cell
* @param width
*/
insertColumnAfterCell : function (cell, width) {
var table = MyDom.searchUpByTagName(cell, 'TABLE');
var matrix = this.getMatrix(table);
var columnIndex = matrix[cell.parentNode.rowIndex].indexOf(cell) + cell.colSpan - 1;
//if the current column isn't the last column
if (columnIndex < matrix[0].length - 1) {
for (var rowIndex = 0, rCnt = matrix.length; rowIndex < rCnt; rowIndex++) {
var currentCell = matrix[rowIndex][columnIndex];
if (currentCell !== matrix[rowIndex][columnIndex + 1]) {
$(currentCell).after('<td>');
for (var i = 1; i < currentCell.rowSpan; i++) {
var previousCell = this.searchForPreviousCellInRow(matrix, rowIndex + i, columnIndex);
if (previousCell) {
$(previousCell).after('<td>');
}
else {
$(table.rows[rowIndex + i]).prepend('<td>');
}
}
}
else {
currentCell.colSpan++;
}
rowIndex += currentCell.rowSpan - 1;
}
}
else {
MyCore.each(table.rows, function (row) {
$(row).append('<td>');
});
}
$('col:eq(' + columnIndex + ')', table).after('<col style="width:' + width + 'px" />');
},
/**
* 在单元格所在列左边插入新列
* @param cell
* @param width
*/
insertColumnBeforeCell : function (cell, width) {
var table = MyDom.searchUpByTagName(cell, 'TABLE');
var matrix = this.getMatrix(table);
var columnIndex = matrix[cell.parentNode.rowIndex].indexOf(cell);
//if the current column isn't the first column
if (columnIndex > 0) {
for (var rowIndex = 0, rCnt = matrix.length; rowIndex < rCnt; rowIndex++) {
var currentCell = matrix[rowIndex][columnIndex];
if (currentCell !== matrix[rowIndex][columnIndex - 1]) {
$(currentCell).before('<td>');
for (var i = 1; i < currentCell.rowSpan; i++) {
var previousCell = this.searchForPreviousCellInRow(matrix, rowIndex + i, columnIndex);
if (previousCell) {
$(previousCell).after('<td>');
}
else {
$(table.rows[rowIndex + i]).prepend('<td>');
}
}
}
else {
currentCell.colSpan++;
}
rowIndex += currentCell.rowSpan - 1;
}
}
else {
MyCore.each(table.rows, function (row) {
$(row).prepend('<td>');
});
}
$('col:eq(' + columnIndex + ')', table).before('<col style="width:' + width + 'px" />');
},
/**
* 在单元格所在行下面插入新行
* @param cell
* @param height
*/
insertRowBelowCell : function (cell, height) {
var table = MyDom.searchUpByTagName(cell, 'TABLE');
var matrix = this.getMatrix(table);
var rowIndex = cell.parentNode.rowIndex + cell.rowSpan - 1;
var newRow = '<tr style="height:' + height + 'px">';
if (rowIndex < matrix.length - 1) {
for (var columnIndex = 0, cCnt = matrix[rowIndex].length; columnIndex < cCnt; columnIndex++) {
var currentCell = matrix[rowIndex][columnIndex];
if (currentCell !== matrix[rowIndex + 1][columnIndex]) {
MyCore.repeat(currentCell.colSpan, function () {
newRow += '<td></td>';
});
}
else {
currentCell.rowSpan++;
}
columnIndex += currentCell.colSpan - 1;
}
}
else {
MyCore.repeat(matrix[rowIndex].length, function () {
newRow += '<td></td>';
});
}
newRow += '</tr>';
$(table.rows[rowIndex]).after(newRow);
},
/**
* 在单元格所在行上面插入新行
* @param cell
* @param height
*/
insertRowAboveCell : function (cell, height) {
var table = MyDom.searchUpByTagName(cell, 'TABLE');
var matrix = this.getMatrix(table);
var rowIndex = cell.parentNode.rowIndex;
var newRow = '<tr style="height:' + height + 'px">';
if (rowIndex > 0) {
for (var columnIndex = 0, cCnt = matrix[rowIndex].length; columnIndex < cCnt; columnIndex++) {
var currentCell = matrix[rowIndex][columnIndex];
if (currentCell !== matrix[rowIndex - 1][columnIndex]) {
MyCore.repeat(currentCell.colSpan, function () {
newRow += '<td></td>';
});
}
else {
currentCell.rowSpan++;
}
columnIndex += currentCell.colSpan - 1;
}
}
else {
MyCore.repeat(matrix[rowIndex].length, function () {
newRow += '<td></td>';
});
}
newRow += '</tr>';
$(table.rows[rowIndex]).before(newRow);
},
/**
* 按照源table的尺寸更新目标table
* @param srcTable
* @param targetTable
*/
copySize : function (srcTable, targetTable) {
var targetCols = $('colgroup:first col', targetTable).get();
$('colgroup:first col', srcTable).each(function (index) {
targetCols[index].style.width = this.style.width;
});
var targetRows = $('tbody:first tr', targetTable).get();
$('tbody:first tr', srcTable).each(function (index) {
targetRows[index].style.height = this.style.height;
});
},
/**
* 移除单元格所在的行
* @param cell
*/
removeRow : function (cell) {
if (cell.rowSpan !== 1) {
throw 'The cell has to only belong to one row!';
}
var table = MyDom.searchUpByTagName(cell, 'TABLE');
if (table.rows.length === 1) {
throw '这是表中唯一的一行,不允许删除!';
}
var matrix = this.getMatrix(table);
var rowIndex = cell.parentNode.rowIndex;
for (var columnIndex = 0, cCnt = matrix[rowIndex].length; columnIndex < cCnt; columnIndex++) {
var currentCell = matrix[rowIndex][columnIndex];
if (currentCell.rowSpan > 1) {
currentCell.rowSpan -= 1;
if (currentCell.parentNode.rowIndex === rowIndex) {
var cellToInsertAfter = null;
for (var columnIndexOfTheRowBelow = columnIndex - 1; columnIndexOfTheRowBelow >= 0; columnIndexOfTheRowBelow--) {
var cellOfTheRowBelow = matrix[rowIndex + 1][columnIndexOfTheRowBelow];
if (cellOfTheRowBelow.rowSpan === 1 || cellOfTheRowBelow.parentNode.rowIndex === rowIndex + 1) {
cellToInsertAfter = cellOfTheRowBelow;
break;
}
}
var rowBelow = currentCell.parentNode.nextSibling;
if (cellToInsertAfter) {
rowBelow.insertBefore(currentCell, cellToInsertAfter.nextSibling);
}
else {
rowBelow.insertBefore(currentCell, rowBelow.firstChild);
}
}
}
columnIndex += currentCell.colSpan - 1;
}
MyDom.removeEl(table.rows[rowIndex]);
this.cleanUpEmptyRowsAndColumns(this.getMatrix(table));
},
/**
* 移除单元格所在的列
* @param cell
*/
removeColumn : function (cell) {
if (cell.colSpan !== 1) {
throw 'The cell has to only belong to one column!';
}
var table = MyDom.searchUpByTagName(cell, 'TABLE');
var matrix = this.getMatrix(table);
if (matrix[0].length === 1) {
throw '这是该表唯一的一列,不允许删除!';
}
var columnIndex = matrix[cell.parentNode.rowIndex].indexOf(cell);
for (var rowIndex = 0, rCnt = matrix.length; rowIndex < rCnt; rowIndex++) {
var currentCell = matrix[rowIndex][columnIndex];
if (currentCell.colSpan > 1) {
currentCell.colSpan -= 1;
}
else {
MyDom.removeEl(currentCell);
}
rowIndex += currentCell.rowSpan - 1;
}
MyDom.removeEl($('colgroup:first col:eq(' + columnIndex + ')', table).get(0));
this.cleanUpEmptyRowsAndColumns(this.getMatrix(table));
}
};
})();
</pre>
<pre name="code" class="js">var TableApi;
(function () {
var MyDom = Helper.Dom;
var MyCore = Helper.Core;
TableApi = {
/**
* 获取table元素的单元格分布矩阵
* @param table
*/
getMatrix : function (table) {
var matrix = [];
for (var rowIndex = 0, rCnt = table.rows.length; rowIndex < rCnt; rowIndex++) {
if (!matrix[rowIndex]) {
matrix[rowIndex] = [];
}
for (var cellIndex = 0, cCnt = table.rows[rowIndex].cells.length; cellIndex < cCnt; cellIndex++) {
var columnIndex = cellIndex;
//In case there's are any horizontal or vertical spans before this cell
while (matrix[rowIndex][columnIndex]) {
columnIndex++;
}
var cell = table.rows[rowIndex].cells[cellIndex];
//Fill the corresponding matrix points
for (var i = 0; i < cell.rowSpan; i++) {
if (!matrix[rowIndex + i]) {
matrix[rowIndex + i] = [];
}
for (var j = 0; j < cell.colSpan; j++) {
matrix[rowIndex + i][columnIndex + j] = cell;
}
}
}
}
return matrix;
},
/**
* 合并单元格分布矩阵中选中的单元格
* @param matrix
*/
merge : function (matrix) {
var maxRowIndex = 0;
var minRowIndex = matrix.length - 1;
var maxColumnIndex = 0;
var minColumnIndex = matrix[0].length - 1;
var rowIndex, columnIndex, rCnt, cCnt;
//decide if selected cells region is mergable
for (rowIndex = 0,rCnt = matrix.length; rowIndex < rCnt; rowIndex++) {
for (columnIndex = 0,cCnt = matrix[0].length; columnIndex < cCnt; columnIndex++) {
if ($(matrix[rowIndex][columnIndex]).hasClass('selected')) {
if (rowIndex > maxRowIndex) {
maxRowIndex = rowIndex;
}
if (rowIndex < minRowIndex) {
minRowIndex = rowIndex;
}
if (columnIndex > maxColumnIndex) {
maxColumnIndex = columnIndex;
}
if (columnIndex < minColumnIndex) {
minColumnIndex = columnIndex;
}
}
}
}
var mergable = true;
for (rowIndex = minRowIndex; rowIndex <= maxRowIndex && mergable; rowIndex++) {
for (columnIndex = minColumnIndex; columnIndex <= maxColumnIndex; columnIndex++) {
if (!$(matrix[rowIndex][columnIndex]).hasClass('selected')) {
mergable = false;
break;
}
}
}
if (mergable) {
//then merge
var cellToMergeInto = matrix[minRowIndex][minColumnIndex];
for (rowIndex = minRowIndex; rowIndex <= maxRowIndex; rowIndex++) {
for (columnIndex = minColumnIndex; columnIndex <= maxColumnIndex; columnIndex++) {
var cell = matrix[rowIndex][columnIndex];
if (cell !== cellToMergeInto) {
for (var i = 0; i < cell.rowSpan; i++) {
for (var j = 0; j < cell.colSpan; j++) {
matrix[rowIndex + i][columnIndex + j] = cellToMergeInto;
}
}
MyDom.removeEl(cell);
}
}
}
cellToMergeInto.colSpan = (maxColumnIndex - minColumnIndex) + 1;
cellToMergeInto.rowSpan = (maxRowIndex - minRowIndex) + 1;
this.cleanUpEmptyRowsAndColumns(matrix);
}
return mergable;
},
/**
* 在单元格分布矩阵中指定行中搜索指定列的前一个单元格
* @param matrix
* @param rowIndex
* @param columnIndex
*/
searchForPreviousCellInRow : function (matrix, rowIndex, columnIndex) {
var columnIndexForPreviousCell = columnIndex;
var previousCell = null;
do{
columnIndexForPreviousCell -= 1;
previousCell = matrix[rowIndex][columnIndexForPreviousCell];
}
while (previousCell && (previousCell.parentNode.rowIndex !== rowIndex));
return previousCell;
},
/**
* 还原合并的单元格
* @param cell
*/
revertMerged : function (cell) {
var table = MyDom.searchUpByTagName(cell, 'TABLE');
var matrix = this.getMatrix(table);
var rowIndex = cell.parentNode.rowIndex;
var columnIndex = matrix[rowIndex].indexOf(cell);
var jCell = $(cell);
var tableApi = this;
MyCore.repeat(cell.colSpan - 1, function () {
jCell.after('<td>');
});
MyCore.repeat(cell.rowSpan - 1, function (time) {
var previousCell = tableApi.searchForPreviousCellInRow(matrix, rowIndex + time, columnIndex);
var task = null;
if (previousCell) {
var jPreviousCell = $(previousCell);
task = function () {
jPreviousCell.after('<td>');
};
}
else {
var jRow = $(table.rows[rowIndex + time]);
task = function () {
jRow.prepend('<td>');
};
}
MyCore.repeat(cell.colSpan, task);
});
cell.colSpan = cell.rowSpan = 1;
},
/**
* 清理单元格分布矩阵中的空行空列
* @param matrix
* @requires the matrix must reflect the current state of the table
*/
cleanUpEmptyRowsAndColumns : function (matrix) {
var table = matrix[0][0].parentNode.parentNode.parentNode;
var rowIndex, columnIndex, cell, cellToCollapse<script src="/javascripts/tinymce/themes/advanced/langs/zh.js" type="text/javascript"><!--mce:0--></script><script src="/javascripts/tinymce/plugins/javaeye/langs/zh.js" type="text/javascript"><!--mce:1--></script>, rCnt, cCnt;
cCnt = matrix[0].length;
//clean up empty rows
for (rowIndex = 0,rCnt = matrix.length; rowIndex < rCnt; rowIndex++) {
var isEmptyRow = true;
for (columnIndex = 0; columnIndex < cCnt; columnIndex++) {
cell = matrix[rowIndex][columnIndex];
if (cell.rowSpan === 1 || cell.parentNode.rowIndex === rowIndex) {
isEmptyRow = false;
break;
}
}
if (!isEmptyRow) {
continue;
}
//recalculate the rowspan
columnIndex = 0;
do{
cellToCollapse = matrix[rowIndex][columnIndex];
cellToCollapse.rowSpan -= 1;
columnIndex += cellToCollapse.colSpan;
}
while (columnIndex < cCnt);
//remove empty tr element
var row = table.rows[rowIndex];
MyDom.removeEl(row);
//remove empty row from matrix
for (var i = rowIndex, iLen = rCnt - 1; i < iLen; i++) {
matrix[i] = matrix[i + 1];
}
matrix.length -= 1;
rCnt--;
//cuz the original next row is now the current row
rowIndex--;
}
//clean up empty columns
for (columnIndex = 0; columnIndex < cCnt; columnIndex++) {
var isEmptyColumn = true;
for (rowIndex = 0; rowIndex < rCnt; rowIndex++) {
cell = matrix[rowIndex][columnIndex];
if (cell.colSpan === 1 || matrix[rowIndex][columnIndex + cell.colSpan - 1] === cell) {
isEmptyColumn = false;
break;
}
}
if (!isEmptyColumn) {
continue;
}
//recalculate the colspan
rowIndex = 0;
do{
cellToCollapse = matrix[rowIndex][columnIndex];
cellToCollapse.colSpan -= 1;
rowIndex += cellToCollapse.rowSpan;
}
while (rowIndex < rCnt);
//remove empty column from matrix
for (rowIndex = 0; rowIndex < rCnt; rowIndex++) {
for (var j = columnIndex, jLen = cCnt - 1; j < jLen; j++) {
matrix[rowIndex][j] = matrix[rowIndex][j + 1];
}
matrix[rowIndex].length -= 1;
}
cCnt--;
//remove corresponding col from colgroup if one exists
var colGroup = $('colgroup', table).get(0);
if (colGroup && colGroup.parentNode === table) {
MyDom.removeEl($('col:eq(' + columnIndex + ')', colGroup).get(0));
}
//cuz the original next column is now the current column
columnIndex--;
}
},
/**
* 根据指定的单元格和坐标获取在单元格分布矩阵中的精确位置
* @param matrix
* @param cell
* @param pageX
* @param pageY
*/
getAccuratePositionInMatrix : function (matrix, cell, pageX, pageY) {
var rowIndex = -1;
var columnIndex = -1;
var found, i, j, jCell, offset, iLen;
if (cell.colSpan === 1) {
columnIndex = matrix[cell.parentNode.rowIndex].indexOf(cell);
}
else {
var firstApperanceColumnIndex = matrix[cell.parentNode.rowIndex].indexOf(cell);
found = false;
//search for a single-column cell within the same column as the multi-column cell, which cuts through pageX horizontally.
for (j = firstApperanceColumnIndex; !found && j < firstApperanceColumnIndex + cell.colSpan; j++) {
for (i = 0,iLen = matrix.length; i < iLen; i++) {
if (matrix[i][j].colSpan !== 1) {
continue;
}
jCell = $(matrix[i][j]);
offset = jCell.offset();
if (offset.left <= pageX && offset.left + jCell.width() >= pageX) {
columnIndex = j;
found = true;
}
break;
}
}
if (!found) {
columnIndex = firstApperanceColumnIndex;
}
}
if (cell.rowSpan === 1) {
rowIndex = cell.parentNode.rowIndex;
}
else {
found = false;
var jLen = matrix[0].length;
//search for a single-row cell within the same row as the multi-row cell, which cuts through pageY vertically.
for (i = cell.parentNode.rowIndex; !found && i < cell.parentNode.rowIndex + cell.rowSpan; i++) {
for (j = 0; j < jLen; j++) {
if (matrix[i][j].rowSpan !== 1) {
continue;
}
jCell = $(matrix[i][j]);
offset = jCell.offset();
if (offset.top <= pageY && offset.top + jCell.height() >= pageY) {
rowIndex = i;
found = true;
}
break;
}
}
if (!found) {
rowIndex = cell.parentNode.rowIndex;
}
}
return {
rowIndex : rowIndex,
columnIndex : columnIndex
};
},
/**
* 重设列宽度
* @param table
* @param columnIndex
* @param width
*/
resizeColumn : function (table, columnIndex, width) {
//Notice that IE6 has problem with applying column width solely by col element. Set table-layout to fixed will solve this problem.
$('colgroup:first col:eq(' + columnIndex + ')', table).css('width', width);
},
/**
* 重设行高度
* @param table
* @param rowIndex
* @param height
*/
resizeRow : function (table, rowIndex, height) {
$('tbody:eq(0) > tr:eq(' + rowIndex + ')', table).css('height', height);
},
/**
* 计算获得table元素的行和列的位置偏移量
* @param matrix
*/
getOffsetsToTableForColumnAndRow : function (matrix) {
var columnOffsets = []; // the offset for the left edge of the columns
var rowOffsets = []; //the offset for the top edge of the rows
var tableOffset = $(MyDom.searchUpByTagName(matrix[0][0], 'TABLE')).offset();
var cell;
var
rCnt = matrix.length,
cCnt = matrix[0].length;
for (var rowIndex = 0; rowIndex < rCnt; rowIndex++) {
for (var columnIndex = 0; columnIndex < cCnt; columnIndex++) {
if (!columnOffsets[columnIndex]) {
cell = matrix[rowIndex][columnIndex];
if (cell.colSpan === 1 || matrix[rowIndex][columnIndex + cell.colSpan - 1] === cell) {
columnOffsets[columnIndex] = $(cell).offset().left - tableOffset.left;
}
}
if (!rowOffsets[rowIndex]) {
cell = matrix[rowIndex][columnIndex];
if (cell.rowSpan === 1 || cell.parentNode.rowIndex === rowIndex) {
rowOffsets[rowIndex] = $(cell).offset().top - tableOffset.top;
}
}
}
}
return {
columnOffsets : columnOffsets,
rowOffsets : rowOffsets
};
},
/**
* 在单元格所在列右边插入新列
* @param cell
* @param width
*/
insertColumnAfterCell : function (cell, width) {
var table = MyDom.searchUpByTagName(cell, 'TABLE');
var matrix = this.getMatrix(table);
var columnIndex = matrix[cell.parentNode.rowIndex].indexOf(cell) + cell.colSpan - 1;
//if the current column isn't the last column
if (columnIndex < matrix[0].length - 1) {
for (var rowIndex = 0, rCnt = matrix.length; rowIndex < rCnt; rowIndex++) {
var currentCell = matrix[rowIndex][columnIndex];
if (currentCell !== matrix[rowIndex][columnIndex + 1]) {
$(currentCell).after('<td>');
for (var i = 1; i < currentCell.rowSpan; i++) {
var previousCell = this.searchForPreviousCellInRow(matrix, rowIndex + i, columnIndex);
if (previousCell) {
$(previousCell).after('<td>');
}
else {
$(table.rows[rowIndex + i]).prepend('<td>');
}
}
}
else {
currentCell.colSpan++;
}
rowIndex += currentCell.rowSpan - 1;
}
}
else {
MyCore.each(table.rows, function (row) {
$(row).append('<td>');
});
}
$('col:eq(' + columnIndex + ')', table).after('<col style="width:' + width + 'px" />');
},
/**
* 在单元格所在列左边插入新列
* @param cell
* @param width
*/
insertColumnBeforeCell : function (cell, width) {
var table = MyDom.searchUpByTagName(cell, 'TABLE');
var matrix = this.getMatrix(table);
var columnIndex = matrix[cell.parentNode.rowIndex].indexOf(cell);
//if the current column isn't the first column
if (columnIndex > 0) {
for (var rowIndex = 0, rCnt = matrix.length; rowIndex < rCnt; rowIndex++) {
var currentCell = matrix[rowIndex][columnIndex];
if (currentCell !== matrix[rowIndex][columnIndex - 1]) {
$(currentCell).before('<td>');
for (var i = 1; i < currentCell.rowSpan; i++) {
var previousCell = this.searchForPreviousCellInRow(matrix, rowIndex + i, columnIndex);
if (previousCell) {
$(previousCell).after('<td>');
}
else {
$(table.rows[rowIndex + i]).prepend('<td>');
}
}
}
else {
currentCell.colSpan++;
}
rowIndex += currentCell.rowSpan - 1;
}
}
else {
MyCore.each(table.rows, function (row) {
$(row).prepend('<td>');
});
}
$('col:eq(' + columnIndex + ')', table).before('<col style="width:' + width + 'px" />');
},
/**
* 在单元格所在行下面插入新行
* @param cell
* @param height
*/
insertRowBelowCell : function (cell, height) {
var table = MyDom.searchUpByTagName(cell, 'TABLE');
var matrix = this.getMatrix(table);
var rowIndex = cell.parentNode.rowIndex + cell.rowSpan - 1;
var newRow = '<tr style="height:' + height + 'px">';
if (rowIndex < matrix.length - 1) {
for (var columnIndex = 0, cCnt = matrix[rowIndex].length; columnIndex < cCnt; columnIndex++) {
var currentCell = matrix[rowIndex][columnIndex];
if (currentCell !== matrix[rowIndex + 1][columnIndex]) {
MyCore.repeat(currentCell.colSpan, function () {
newRow += '<td></td>';
});
}
else {
currentCell.rowSpan++;
}
columnIndex += currentCell.colSpan - 1;
}
}
else {
MyCore.repeat(matrix[rowIndex].length, function () {
newRow += '<td></td>';
});
}
newRow += '</tr>';
$(table.rows[rowIndex]).after(newRow);
},
/**
* 在单元格所在行上面插入新行
* @param cell
* @param height
*/
insertRowAboveCell : function (cell, height) {
var table = MyDom.searchUpByTagName(cell, 'TABLE');
var matrix = this.getMatrix(table);
var rowIndex = cell.parentNode.rowIndex;
var newRow = '<tr style="height:' + height + 'px">';
if (rowIndex > 0) {
for (var columnIndex = 0, cCnt = matrix[rowIndex].length; columnIndex < cCnt; columnIndex++) {
var currentCell = matrix[rowIndex][columnIndex];
if (currentCell !== matrix[rowIndex - 1][columnIndex]) {
MyCore.repeat(currentCell.colSpan, function () {
newRow += '<td></td>';
});
}
else {
currentCell.rowSpan++;
}
columnIndex += currentCell.colSpan - 1;
}
}
else {
MyCore.repeat(matrix[rowIndex].length, function () {
newRow += '<td></td>';
});
}
newRow += '</tr>';
$(table.rows[rowIndex]).before(newRow);
},
/**
* 按照源table的尺寸更新目标table
* @param srcTable
* @param targetTable
*/
copySize : function (srcTable, targetTable) {
var targetCols = $('colgroup:first col', targetTable).get();
$('colgroup:first col', srcTable).each(function (index) {
targetCols[index].style.width = this.style.width;
});
var targetRows = $('tbody:first tr', targetTable).get();
$('tbody:first tr', srcTable).each(function (index) {
targetRows[index].style.height = this.style.height;
});
},
/**
* 移除单元格所在的行
* @param cell
*/
removeRow : function (cell) {
if (cell.rowSpan !== 1) {
throw 'The cell has to only belong to one row!';
}
var table = MyDom.searchUpByTagName(cell, 'TABLE');
if (table.rows.length === 1) {
throw '这是表中唯一的一行,不允许删除!';
}
var matrix = this.getMatrix(table);
var rowIndex = cell.parentNode.rowIndex;
for (var columnIndex = 0, cCnt = matrix[rowIndex].length; columnIndex < cCnt; columnIndex++) {
var currentCell = matrix[rowIndex][columnIndex];
if (currentCell.rowSpan > 1) {
currentCell.rowSpan -= 1;
if (currentCell.parentNode.rowIndex === rowIndex) {
var cellToInsertAfter = null;
for (var columnIndexOfTheRowBelow = columnIndex - 1; columnIndexOfTheRowBelow >= 0; columnIndexOfTheRowBelow--) {
var cellOfTheRowBelow = matrix[rowIndex + 1][columnIndexOfTheRowBelow];
if (cellOfTheRowBelow.rowSpan === 1 || cellOfTheRowBelow.parentNode.rowIndex === rowIndex + 1) {
cellToInsertAfter = cellOfTheRowBelow;
break;
}
}
var rowBelow = currentCell.parentNode.nextSibling;
if (cellToInsertAfter) {
rowBelow.insertBefore(currentCell, cellToInsertAfter.nextSibling);
}
else {
rowBelow.insertBefore(currentCell, rowBelow.firstChild);
}
}
}
columnIndex += currentCell.colSpan - 1;
}
MyDom.removeEl(table.rows[rowIndex]);
this.cleanUpEmptyRowsAndColumns(this.getMatrix(table));
},
/**
* 移除单元格所在的列
* @param cell
*/
removeColumn : function (cell) {
if (cell.colSpan !== 1) {
throw 'The cell has to only belong to one column!';
}
var table = MyDom.searchUpByTagName(cell, 'TABLE');
var matrix = this.getMatrix(table);
if (matrix[0].length === 1) {
throw '这是该表唯一的一列,不允许删除!';
}
var columnIndex = matrix[cell.parentNode.rowIndex].indexOf(cell);
for (var rowIndex = 0, rCnt = matrix.length; rowIndex < rCnt; rowIndex++) {
var currentCell = matrix[rowIndex][columnIndex];
if (currentCell.colSpan > 1) {
currentCell.colSpan -= 1;
}
else {
MyDom.removeEl(currentCell);
}
rowIndex += currentCell.rowSpan - 1;
}
MyDom.removeEl($('colgroup:first col:eq(' + columnIndex + ')', table).get(0));
this.cleanUpEmptyRowsAndColumns(this.getMatrix(table));
}
};
})();
</pre>
29 楼
leisure
2009-06-15
本人最近也在做一个在线编辑器中画table功能,比楼主的复杂得多。
比如在经过多次拆分合并后的一个单元格中 再次进行增删功能
现在剩下 选择多个单元格合并未实现
封装啊 封装 楼主代码需要封装啊
比如在经过多次拆分合并后的一个单元格中 再次进行增删功能
现在剩下 选择多个单元格合并未实现
封装啊 封装 楼主代码需要封装啊
28 楼
whaosoft
2009-06-14
我们现在的项目也有这个功能是挺恶心的
27 楼
wy19280469
2009-06-14
你所写的东西网上已经有源代码了?去找找看,操作单元格!~ 你所说的所有功能都有 ....
26 楼
iampurse
2009-06-08
请看merge 里头的操作。
25 楼
iampurse
2009-06-08
var $ = jQuery;
var TBar = {
crt : function() {
var row = $('#row').val();
var col = $('#col').val();
$('#info table').remove();
var table = $("<table class='datalist form' cellspacing='0'></table>");
while (row-- > 0) {
var tr = $("<tr></tr>");
var num = col;
while (num-- > 0) {
tr.append("<td></td>");
}
table.append(tr);
}
$('#info').append(table);
App.initTd();
},
addRow : function() {
var tr = $('#info table tr:last').clone();
tr.find("td").html("");
App.initTd(tr.find("td"));
$('#info table').append(tr);
},
addCol : function() {
$('#info table tr').append(App.initTd($("<td></td>")));
},
delRow : function() {
var elIds = [];
$(".hit").parent().children().each(function() {
elIds[elIds.length] = $(this).children().attr("elid");
});
// FIXME 合理的不?
$.ajax({
url:'/c/wkf/delFormElement',
type:'post',
data:{elIds:elIds.join(",")},
dataType:'json',
success:function(rst){
if(rst.success===true){
$('.hit').parent().remove();
//更新模板
var tpl = TBar.getLayOut();
var formId = $('#formId').val();
updateFormTpl(formId, tpl);
}else{
alert('删除行失败');
}
}
});
},
delCol : function() {
var elIds = [];
$(".hit").each(function() {
elIds[elIds.length] = $(this).children().attr("elid");
});
// FIXME 合理的不?
$.ajax({
url:'/c/wkf/delFormElement',
type:'post',
data:{elIds:elIds.join(",")},
dataType:'json',
success:function(rst){
if(rst.success===true){
$('.hit').remove();
//更新模板
var tpl = TBar.getLayOut();
var formId = $('#formId').val();
updateFormTpl(formId, tpl);
}else{
alert('删除行失败');
}
}
});
},
clear : function() {
$('.hit').text("");
},
merge : function() {
var num = $('.hit').length;
if (num < 2) {
alert("请至少选择两个单元格!");
} else {
var first = $('.hit:first');
var last = $('.hit:last');
var lFirst = first.attr('offsetLeft');
var lLast = last.attr('offsetLeft');
var First = first.attr('offsetTop');
var tLast = last.attr('offsetTop');
var diffX = lLast - lFirst;
var diffY = tLast - First;
var cfg = false;
if (diffX == 0) {
cfg = {
offert : 'offsetLeft',
len : lFirst,
span : 'rowSpan'
};
}
if (diffY == 0) {
cfg = {
offert : 'offsetTop',
len : First,
span : 'colSpan'
};
}
if (cfg) {
var flag = true;
if (num > 2) {
$('.hit').each(function() {
var offert = $(this).attr(cfg.offert);
if (offert != cfg.len) {
return flag = false;
}
return flag = true;
});
}
if (flag) {
$('.hit').not(first).remove();
first.attr(cfg.span, num);
} else {
alert("请选择相邻的单元格!");
}
}
}
},
getLayOut : function() {
var tb = $('#info').clone();
tb.find('td').removeClass("hit").each(function() {
var el = $('.el', this).attr('el');
if (el) {
$(this).text("${" + el + "}")
} else {
$(this).text("")
}
});
var layout = tb.html().replace(/ jQuery\d*="null"/g, '');
return layout;
}
}
var TBar = {
crt : function() {
var row = $('#row').val();
var col = $('#col').val();
$('#info table').remove();
var table = $("<table class='datalist form' cellspacing='0'></table>");
while (row-- > 0) {
var tr = $("<tr></tr>");
var num = col;
while (num-- > 0) {
tr.append("<td></td>");
}
table.append(tr);
}
$('#info').append(table);
App.initTd();
},
addRow : function() {
var tr = $('#info table tr:last').clone();
tr.find("td").html("");
App.initTd(tr.find("td"));
$('#info table').append(tr);
},
addCol : function() {
$('#info table tr').append(App.initTd($("<td></td>")));
},
delRow : function() {
var elIds = [];
$(".hit").parent().children().each(function() {
elIds[elIds.length] = $(this).children().attr("elid");
});
// FIXME 合理的不?
$.ajax({
url:'/c/wkf/delFormElement',
type:'post',
data:{elIds:elIds.join(",")},
dataType:'json',
success:function(rst){
if(rst.success===true){
$('.hit').parent().remove();
//更新模板
var tpl = TBar.getLayOut();
var formId = $('#formId').val();
updateFormTpl(formId, tpl);
}else{
alert('删除行失败');
}
}
});
},
delCol : function() {
var elIds = [];
$(".hit").each(function() {
elIds[elIds.length] = $(this).children().attr("elid");
});
// FIXME 合理的不?
$.ajax({
url:'/c/wkf/delFormElement',
type:'post',
data:{elIds:elIds.join(",")},
dataType:'json',
success:function(rst){
if(rst.success===true){
$('.hit').remove();
//更新模板
var tpl = TBar.getLayOut();
var formId = $('#formId').val();
updateFormTpl(formId, tpl);
}else{
alert('删除行失败');
}
}
});
},
clear : function() {
$('.hit').text("");
},
merge : function() {
var num = $('.hit').length;
if (num < 2) {
alert("请至少选择两个单元格!");
} else {
var first = $('.hit:first');
var last = $('.hit:last');
var lFirst = first.attr('offsetLeft');
var lLast = last.attr('offsetLeft');
var First = first.attr('offsetTop');
var tLast = last.attr('offsetTop');
var diffX = lLast - lFirst;
var diffY = tLast - First;
var cfg = false;
if (diffX == 0) {
cfg = {
offert : 'offsetLeft',
len : lFirst,
span : 'rowSpan'
};
}
if (diffY == 0) {
cfg = {
offert : 'offsetTop',
len : First,
span : 'colSpan'
};
}
if (cfg) {
var flag = true;
if (num > 2) {
$('.hit').each(function() {
var offert = $(this).attr(cfg.offert);
if (offert != cfg.len) {
return flag = false;
}
return flag = true;
});
}
if (flag) {
$('.hit').not(first).remove();
first.attr(cfg.span, num);
} else {
alert("请选择相邻的单元格!");
}
}
}
},
getLayOut : function() {
var tb = $('#info').clone();
tb.find('td').removeClass("hit").each(function() {
var el = $('.el', this).attr('el');
if (el) {
$(this).text("${" + el + "}")
} else {
$(this).text("")
}
});
var layout = tb.html().replace(/ jQuery\d*="null"/g, '');
return layout;
}
}
24 楼
lobbychmd
2009-06-03
增加行
$(Grid + ' tbody tr:first-child').clone().appendTo(Grid + ' tbody');
$(Grid + ' tbody tr:first-child').clone().appendTo(Grid + ' tbody');
23 楼
ninecat
2009-06-03
大概实现了一下合并单元格, 没实现合并已经被合并的单元格
22 楼
fcu
2009-06-03
以前公司做设计的时候就是用TABLE来实现,合并,增加,删除,但是列移动没有实现,维护起来麻烦死了,后来用的DATAGGRID,和三方的GRID,楼主也找找看吧
21 楼
dragonboa
2009-06-03
var row0 = document.getElementByID("tableID").insertRow(-1);//tableID--该table的ID;-1表示是在该行的下面插入一行;
var cell = row0.insertCell(-1);//增加一个td
cell.innerHTML = "<td><strong>姓名:</strong></td>";//设置td的内容
cell.align = "right";//td的属性
row0.insertCell(-1).innerHTML = "<td><label><input type=\"text\" id=\"\" size=\"25\"></label></td>";//下一个td
可以这样不断的加
最后就形成了一个table了
至于删除的话document.getElementByID("tableID").deleteRow(1)就可以了,这是删除第二行。
var cell = row0.insertCell(-1);//增加一个td
cell.innerHTML = "<td><strong>姓名:</strong></td>";//设置td的内容
cell.align = "right";//td的属性
row0.insertCell(-1).innerHTML = "<td><label><input type=\"text\" id=\"\" size=\"25\"></label></td>";//下一个td
可以这样不断的加
最后就形成了一个table了
至于删除的话document.getElementByID("tableID").deleteRow(1)就可以了,这是删除第二行。
20 楼
chenhua_1984
2009-06-03
keyboard2000 写道
还是用控件吧,从底层写起太烦,且兼容性不好
实际运用的过程中是不会重新写的,这里只是练练手!是我以前的一个面试题目!
19 楼
chenhua_1984
2009-06-03
<div class="quote_title">pub10 写道</div>
<div class="quote_div">
<p>这个功能可以参考fckeditor代码,fck已经实现得很好了。具体可以看一下fck源码\internals\fcktablehandler.js</p>
<p> <img src="/upload/attachment/110239/19a3dac6-d72b-3a3a-a8cf-08db73db9a78.jpg" alt=""></p>
</div>
<p>恩,是的,谢谢提示!</p>
<div class="quote_div">
<p>这个功能可以参考fckeditor代码,fck已经实现得很好了。具体可以看一下fck源码\internals\fcktablehandler.js</p>
<p> <img src="/upload/attachment/110239/19a3dac6-d72b-3a3a-a8cf-08db73db9a78.jpg" alt=""></p>
</div>
<p>恩,是的,谢谢提示!</p>
18 楼
keyboard2000
2009-06-03
还是用控件吧,从底层写起太烦,且兼容性不好
17 楼
pub10
2009-06-02
<p>这个功能可以参考fckeditor代码,fck已经实现得很好了。具体可以看一下fck源码\internals\fcktablehandler.js</p>
<p> <img src="/upload/attachment/110239/19a3dac6-d72b-3a3a-a8cf-08db73db9a78.jpg" alt=""></p>
<p> <img src="/upload/attachment/110239/19a3dac6-d72b-3a3a-a8cf-08db73db9a78.jpg" alt=""></p>
发表评论
-
web页面调用window.print()函数实现打印的功能
2010-09-17 09:23 151771 在WEB上的打印通常的解决方法是用报表的方式,比较 ... -
jquery 排序插件 tablesorter
2010-09-06 09:19 4616分页的插件有很多,项目里面用的是jquery, ... -
正则表达式基础学习六:匹配字母和数字和下划线
2010-08-12 10:34 3809\w 匹配 ... -
正则表达式基础学习五:匹配数字
2010-08-12 10:11 13451 匹配数字:[0-9]是[012345 ... -
正则表达式学习基础四:空白元字符
2010-08-12 10:01 1374元字符有 .匹配任 ... -
正则表达式学习基础三:使用元字符.[]
2010-08-11 16:37 1277元字符是 regex里有特殊含义的字符,使用的时候 ... -
正则表达式学习基础二
2010-08-10 17:27 863主要学习[ ]集合的用法和取非。截图如下,备忘。- ... -
正则表达式基础学习一
2010-08-10 17:02 978在看正则表达式的东西。比较基础的一节课,接几个图贴下,备忘。 ... -
左边菜单隐藏,右边全屏
2010-01-06 17:12 2456<html> <head> ... -
setTimeout 和 setInterval 的区别
2009-12-14 09:58 1155window对象有两个主要的定时方法,分别是setTimeou ... -
js+html类似QQ右下角弹出提示的效果
2009-12-14 09:53 3380js部分 <script type="tex ... -
jquery jmpopups 弹出新窗口,可以弹多个
2009-12-11 11:07 7332<!DOCTYPE html PUBLIC " ... -
Jquery Ingrid 表格插件的使用
2009-12-02 09:35 3325demo.jsp <%@ page language= ... -
html关闭“双击输入框出现提示”这个问题
2009-10-30 10:42 2507一般我们在填写网站得 注册或登录的时候,第 ... -
ajax学习笔记之一
2009-10-29 16:00 1134Aajax概述 0 ... -
firefox3不能获得html file的全路径的问题
2009-06-09 16:27 7931遇到这个问题以后, ... -
js添加一个新行,可以输入的Input,用于添加更多的业务
2009-06-09 09:59 4798<input type="butto ... -
获得select的innerText的值,在fireFox和IE里,Opera
2009-06-08 12:25 1210A 在IE里获得select的innerText的值用obj ... -
innerHTML IE bug未知的错误
2009-06-08 09:27 2125项目里要用到添加更 ... -
CSS样式学习笔记之五:表格的学习和表格的样式
2009-05-21 10:13 13881表格特有的元素:caption 和summary < ...
相关推荐
需要注意的是,当自动合并单元格时,开发者应该考虑表格的可访问性和数据的逻辑性,确保合并操作不会导致数据解读错误或者损害表格结构的完整性。例如,如果一个表格是用于数据导出或者数据分析的,那么合并单元格...
在这个“vue-easytable合并单元格”的主题下,我们将深入探讨如何利用Vue Easytable实现表格中的单元格合并。 在传统的HTML表格中,合并单元格通常使用`<td>`的`colspan`和`rowspan`属性来完成,但在Vue Easytable...
总的来说,JS实现动态修改table及合并单元格涉及的主要知识点包括: 1. DOM操作:通过`getElementById`获取元素,使用`rows`和`cells`属性遍历表格。 2. 遍历技巧:使用`for`循环遍历表格行和列,根据需求进行判断...
"layui table合并单元格.zip" 这个压缩包正是提供了关于如何在layui的表格中实现单元格合并的示例和资源。 首先,"layui table.txt" 文件可能包含了layui表格组件的基础用法和API介绍。layui的表格组件支持动态加载...
类功能描述:该插件生成一个具有行合并的列表数据,合并例由开发者指定。 开发者提供已排序的数据列表以及需要合并行的列名即可,无需后端二次处理数据。 该类以纯原生JS编写,无需引入任何第三方库。 调用方法:...
### JavaScript 实现 HTML Table 单元格合并及隐藏列功能详解 #### 一、背景介绍 在处理 HTML 表格时,我们经常会遇到需要合并相同数据的单元格以及根据需求显示或隐藏某些列的情况。例如,在报表展示或者数据汇总...
本js脚本完美的实现了table单元格的合并,合并后犹如交叉表的形式,非常完美,并在其中附带例子可以验证。
在表格(Table)设计中,有时我们需要合并单元格来达到特定的展示效果,例如创建标题行或列,或者为了美观和布局对齐。在HTML、CSS以及JavaScript中,都有多种方式可以实现单元格的合并。这里我们将详细探讨六种合并...
每次遍历时都会更新计数器 `count`,用于记录合并单元格所占据的行数。 ```javascript count++; ``` #### 三、JSP 示例代码解析 在 JSP 文件中,使用 `<s:iterator>` 标签来迭代列表,并为每个元素生成一个表格行...
本话题聚焦于LayUI中的Table组件,特别是如何实现相同参数的单元格合并功能,这在展示数据时能有效提高信息的可读性和美观性。 LayUI Table的单元格合并功能,主要是通过`parseData`方法和自定义模板来实现的。当...
本项目提供了一个解决方案,它支持合并单元格和合并行,无需依赖Microsoft Office,这对于那些无法安装Office环境或者希望在服务器端执行此操作的用户来说,具有很高的实用价值。 首先,我们要理解HTML表格...
"table-rowspan表格自动合并单元格插件"是专为HTML表格设计的一种工具,它允许开发者通过简单的操作实现单元格的动态合并、添加和删除,极大地提升了用户界面的可读性和交互性。以下是对这个插件及相关知识点的详细...
用户可以选择多个单元格,然后执行“合并单元格”操作,以实现这一效果。 5. **其他表格操作**:除了上述基本功能,富文本编辑器可能还包括拆分单元格、调整行高、排序数据、设置边框样式和颜色等高级功能,以满足...
综上所述,实现列表多行多列合并单元格涉及到HTML表格的基本操作,以及JavaScript动态计算和设置`colspan`和`rowspan`属性。在开发过程中,还需要考虑交互性、响应式设计和性能优化,确保在各种环境下都能提供良好的...
本文将深入探讨如何实现“合并table的行”这一功能,以及其背后的原理与应用场景。 ### 合并table的行:原理与实现 在Web开发中,`<table>`元素用于显示数据的表格形式,而合并行的功能主要通过`<td>`或`<th>`标签...
对表格的行和列进行插入/删除,并对每行添加行号
只要输入table的id,就可以自动合并单元格,只要上下相邻的单元格相同的,都会合并 html版比较好,点下面的 http://download.csdn.net/source/1276574
通过Datatables的`drawCallback`或`initComplete`事件,在表格渲染完成后合并单元格。遍历预处理得到的合并信息,使用DOM操作修改表格结构。 ```javascript $('#example').DataTable({ // ...其他配置... ...
利用js合并table相同内容单元格并js方式自动生成,把文本内容复制进js中,应该就知道大概咋用了
Bootstrap Table是一款基于...通过以上步骤,我们就能在使用Bootstrap Table时实现导出合并单元格的功能,提高数据展示的效率和质量。在实际开发中,可以根据项目需求调整和定制这些方法,以满足更复杂的需求。