table.core.js 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354
  1. /**
  2. * Created with JetBrains WebStorm.
  3. * User: taoqili
  4. * Date: 13-1-18
  5. * Time: 上午11:09
  6. * To change this template use File | Settings | File Templates.
  7. */
  8. /**
  9. * UE表格操作类
  10. * @param table
  11. * @constructor
  12. */
  13. (function() {
  14. var UETable = (UE.UETable = function(table) {
  15. this.table = table;
  16. this.indexTable = [];
  17. this.selectedTds = [];
  18. this.cellsRange = {};
  19. this.update(table);
  20. });
  21. //===以下为静态工具方法===
  22. UETable.removeSelectedClass = function(cells) {
  23. utils.each(cells, function(cell) {
  24. domUtils.removeClasses(cell, "selectTdClass");
  25. });
  26. };
  27. UETable.addSelectedClass = function(cells) {
  28. utils.each(cells, function(cell) {
  29. domUtils.addClass(cell, "selectTdClass");
  30. });
  31. };
  32. UETable.isEmptyBlock = function(node) {
  33. var reg = new RegExp(domUtils.fillChar, "g");
  34. if (
  35. node[browser.ie ? "innerText" : "textContent"]
  36. .replace(/^\s*$/, "")
  37. .replace(reg, "").length > 0
  38. ) {
  39. return 0;
  40. }
  41. for (var i in dtd.$isNotEmpty)
  42. if (dtd.$isNotEmpty.hasOwnProperty(i)) {
  43. if (node.getElementsByTagName(i).length) {
  44. return 0;
  45. }
  46. }
  47. return 1;
  48. };
  49. UETable.getWidth = function(cell) {
  50. if (!cell) return 0;
  51. return parseInt(domUtils.getComputedStyle(cell, "width"), 10);
  52. };
  53. /**
  54. * 获取单元格或者单元格组的“对齐”状态。 如果当前的检测对象是一个单元格组, 只有在满足所有单元格的 水平和竖直 对齐属性都相同的
  55. * 条件时才会返回其状态值,否则将返回null; 如果当前只检测了一个单元格, 则直接返回当前单元格的对齐状态;
  56. * @param table cell or table cells , 支持单个单元格dom对象 或者 单元格dom对象数组
  57. * @return { align: 'left' || 'right' || 'center', valign: 'top' || 'middle' || 'bottom' } 或者 null
  58. */
  59. UETable.getTableCellAlignState = function(cells) {
  60. !utils.isArray(cells) && (cells = [cells]);
  61. var result = {},
  62. status = ["align", "valign"],
  63. tempStatus = null,
  64. isSame = true; //状态是否相同
  65. utils.each(cells, function(cellNode) {
  66. utils.each(status, function(currentState) {
  67. tempStatus = cellNode.getAttribute(currentState);
  68. if (!result[currentState] && tempStatus) {
  69. result[currentState] = tempStatus;
  70. } else if (
  71. !result[currentState] ||
  72. tempStatus !== result[currentState]
  73. ) {
  74. isSame = false;
  75. return false;
  76. }
  77. });
  78. return isSame;
  79. });
  80. return isSame ? result : null;
  81. };
  82. /**
  83. * 根据当前选区获取相关的table信息
  84. * @return {Object}
  85. */
  86. UETable.getTableItemsByRange = function(editor) {
  87. var start = editor.selection.getStart();
  88. //ff下会选中bookmark
  89. if (
  90. start &&
  91. start.id &&
  92. start.id.indexOf("_baidu_bookmark_start_") === 0 &&
  93. start.nextSibling
  94. ) {
  95. start = start.nextSibling;
  96. }
  97. //在table或者td边缘有可能存在选中tr的情况
  98. var cell = start && domUtils.findParentByTagName(start, ["td", "th"], true),
  99. tr = cell && cell.parentNode,
  100. table = tr && domUtils.findParentByTagName(tr, ["table"]),
  101. caption = table && table.getElementsByTagName("caption")[0];
  102. return {
  103. cell: cell,
  104. tr: tr,
  105. table: table,
  106. caption: caption
  107. };
  108. };
  109. UETable.getUETableBySelected = function(editor) {
  110. var table = UETable.getTableItemsByRange(editor).table;
  111. if (table && table.ueTable && table.ueTable.selectedTds.length) {
  112. return table.ueTable;
  113. }
  114. return null;
  115. };
  116. UETable.getDefaultValue = function(editor, table) {
  117. var borderMap = {
  118. thin: "0px",
  119. medium: "1px",
  120. thick: "2px"
  121. },
  122. tableBorder,
  123. tdPadding,
  124. tdBorder,
  125. tmpValue;
  126. if (!table) {
  127. table = editor.document.createElement("table");
  128. table.insertRow(0).insertCell(0).innerHTML = "xxx";
  129. editor.body.appendChild(table);
  130. var td = table.getElementsByTagName("td")[0];
  131. tmpValue = domUtils.getComputedStyle(table, "border-left-width");
  132. tableBorder = parseInt(borderMap[tmpValue] || tmpValue, 10);
  133. tmpValue = domUtils.getComputedStyle(td, "padding-left");
  134. tdPadding = parseInt(borderMap[tmpValue] || tmpValue, 10);
  135. tmpValue = domUtils.getComputedStyle(td, "border-left-width");
  136. tdBorder = parseInt(borderMap[tmpValue] || tmpValue, 10);
  137. domUtils.remove(table);
  138. return {
  139. tableBorder: tableBorder,
  140. tdPadding: tdPadding,
  141. tdBorder: tdBorder
  142. };
  143. } else {
  144. td = table.getElementsByTagName("td")[0];
  145. tmpValue = domUtils.getComputedStyle(table, "border-left-width");
  146. tableBorder = parseInt(borderMap[tmpValue] || tmpValue, 10);
  147. tmpValue = domUtils.getComputedStyle(td, "padding-left");
  148. tdPadding = parseInt(borderMap[tmpValue] || tmpValue, 10);
  149. tmpValue = domUtils.getComputedStyle(td, "border-left-width");
  150. tdBorder = parseInt(borderMap[tmpValue] || tmpValue, 10);
  151. return {
  152. tableBorder: tableBorder,
  153. tdPadding: tdPadding,
  154. tdBorder: tdBorder
  155. };
  156. }
  157. };
  158. /**
  159. * 根据当前点击的td或者table获取索引对象
  160. * @param tdOrTable
  161. */
  162. UETable.getUETable = function(tdOrTable) {
  163. var tag = tdOrTable.tagName.toLowerCase();
  164. tdOrTable = tag == "td" || tag == "th" || tag == "caption"
  165. ? domUtils.findParentByTagName(tdOrTable, "table", true)
  166. : tdOrTable;
  167. if (!tdOrTable.ueTable) {
  168. tdOrTable.ueTable = new UETable(tdOrTable);
  169. }
  170. return tdOrTable.ueTable;
  171. };
  172. UETable.cloneCell = function(cell, ignoreMerge, keepPro) {
  173. if (!cell || utils.isString(cell)) {
  174. return this.table.ownerDocument.createElement(cell || "td");
  175. }
  176. var flag = domUtils.hasClass(cell, "selectTdClass");
  177. flag && domUtils.removeClasses(cell, "selectTdClass");
  178. var tmpCell = cell.cloneNode(true);
  179. if (ignoreMerge) {
  180. tmpCell.rowSpan = tmpCell.colSpan = 1;
  181. }
  182. //去掉宽高
  183. !keepPro && domUtils.removeAttributes(tmpCell, "width height");
  184. !keepPro && domUtils.removeAttributes(tmpCell, "style");
  185. tmpCell.style.borderLeftStyle = "";
  186. tmpCell.style.borderTopStyle = "";
  187. tmpCell.style.borderLeftColor = cell.style.borderRightColor;
  188. tmpCell.style.borderLeftWidth = cell.style.borderRightWidth;
  189. tmpCell.style.borderTopColor = cell.style.borderBottomColor;
  190. tmpCell.style.borderTopWidth = cell.style.borderBottomWidth;
  191. flag && domUtils.addClass(cell, "selectTdClass");
  192. return tmpCell;
  193. };
  194. UETable.prototype = {
  195. getMaxRows: function() {
  196. var rows = this.table.rows,
  197. maxLen = 1;
  198. for (var i = 0, row; (row = rows[i]); i++) {
  199. var currentMax = 1;
  200. for (var j = 0, cj; (cj = row.cells[j++]); ) {
  201. currentMax = Math.max(cj.rowSpan || 1, currentMax);
  202. }
  203. maxLen = Math.max(currentMax + i, maxLen);
  204. }
  205. return maxLen;
  206. },
  207. /**
  208. * 获取当前表格的最大列数
  209. */
  210. getMaxCols: function() {
  211. var rows = this.table.rows,
  212. maxLen = 0,
  213. cellRows = {};
  214. for (var i = 0, row; (row = rows[i]); i++) {
  215. var cellsNum = 0;
  216. for (var j = 0, cj; (cj = row.cells[j++]); ) {
  217. cellsNum += cj.colSpan || 1;
  218. if (cj.rowSpan && cj.rowSpan > 1) {
  219. for (var k = 1; k < cj.rowSpan; k++) {
  220. if (!cellRows["row_" + (i + k)]) {
  221. cellRows["row_" + (i + k)] = cj.colSpan || 1;
  222. } else {
  223. cellRows["row_" + (i + k)]++;
  224. }
  225. }
  226. }
  227. }
  228. cellsNum += cellRows["row_" + i] || 0;
  229. maxLen = Math.max(cellsNum, maxLen);
  230. }
  231. return maxLen;
  232. },
  233. getCellColIndex: function(cell) {},
  234. /**
  235. * 获取当前cell旁边的单元格,
  236. * @param cell
  237. * @param right
  238. */
  239. getHSideCell: function(cell, right) {
  240. try {
  241. var cellInfo = this.getCellInfo(cell),
  242. previewRowIndex,
  243. previewColIndex;
  244. var len = this.selectedTds.length,
  245. range = this.cellsRange;
  246. //首行或者首列没有前置单元格
  247. if (
  248. (!right && (!len ? !cellInfo.colIndex : !range.beginColIndex)) ||
  249. (right &&
  250. (!len
  251. ? cellInfo.colIndex == this.colsNum - 1
  252. : range.endColIndex == this.colsNum - 1))
  253. )
  254. return null;
  255. previewRowIndex = !len ? cellInfo.rowIndex : range.beginRowIndex;
  256. previewColIndex = !right
  257. ? !len
  258. ? cellInfo.colIndex < 1 ? 0 : cellInfo.colIndex - 1
  259. : range.beginColIndex - 1
  260. : !len ? cellInfo.colIndex + 1 : range.endColIndex + 1;
  261. return this.getCell(
  262. this.indexTable[previewRowIndex][previewColIndex].rowIndex,
  263. this.indexTable[previewRowIndex][previewColIndex].cellIndex
  264. );
  265. } catch (e) {
  266. showError(e);
  267. }
  268. },
  269. getTabNextCell: function(cell, preRowIndex) {
  270. var cellInfo = this.getCellInfo(cell),
  271. rowIndex = preRowIndex || cellInfo.rowIndex,
  272. colIndex = cellInfo.colIndex + 1 + (cellInfo.colSpan - 1),
  273. nextCell;
  274. try {
  275. nextCell = this.getCell(
  276. this.indexTable[rowIndex][colIndex].rowIndex,
  277. this.indexTable[rowIndex][colIndex].cellIndex
  278. );
  279. } catch (e) {
  280. try {
  281. rowIndex = rowIndex * 1 + 1;
  282. colIndex = 0;
  283. nextCell = this.getCell(
  284. this.indexTable[rowIndex][colIndex].rowIndex,
  285. this.indexTable[rowIndex][colIndex].cellIndex
  286. );
  287. } catch (e) {}
  288. }
  289. return nextCell;
  290. },
  291. /**
  292. * 获取视觉上的后置单元格
  293. * @param cell
  294. * @param bottom
  295. */
  296. getVSideCell: function(cell, bottom, ignoreRange) {
  297. try {
  298. var cellInfo = this.getCellInfo(cell),
  299. nextRowIndex,
  300. nextColIndex;
  301. var len = this.selectedTds.length && !ignoreRange,
  302. range = this.cellsRange;
  303. //末行或者末列没有后置单元格
  304. if (
  305. (!bottom && cellInfo.rowIndex == 0) ||
  306. (bottom &&
  307. (!len
  308. ? cellInfo.rowIndex + cellInfo.rowSpan > this.rowsNum - 1
  309. : range.endRowIndex == this.rowsNum - 1))
  310. )
  311. return null;
  312. nextRowIndex = !bottom
  313. ? !len ? cellInfo.rowIndex - 1 : range.beginRowIndex - 1
  314. : !len ? cellInfo.rowIndex + cellInfo.rowSpan : range.endRowIndex + 1;
  315. nextColIndex = !len ? cellInfo.colIndex : range.beginColIndex;
  316. return this.getCell(
  317. this.indexTable[nextRowIndex][nextColIndex].rowIndex,
  318. this.indexTable[nextRowIndex][nextColIndex].cellIndex
  319. );
  320. } catch (e) {
  321. showError(e);
  322. }
  323. },
  324. /**
  325. * 获取相同结束位置的单元格,xOrY指代了是获取x轴相同还是y轴相同
  326. */
  327. getSameEndPosCells: function(cell, xOrY) {
  328. try {
  329. var flag = xOrY.toLowerCase() === "x",
  330. end =
  331. domUtils.getXY(cell)[flag ? "x" : "y"] +
  332. cell["offset" + (flag ? "Width" : "Height")],
  333. rows = this.table.rows,
  334. cells = null,
  335. returns = [];
  336. for (var i = 0; i < this.rowsNum; i++) {
  337. cells = rows[i].cells;
  338. for (var j = 0, tmpCell; (tmpCell = cells[j++]); ) {
  339. var tmpEnd =
  340. domUtils.getXY(tmpCell)[flag ? "x" : "y"] +
  341. tmpCell["offset" + (flag ? "Width" : "Height")];
  342. //对应行的td已经被上面行rowSpan了
  343. if (tmpEnd > end && flag) break;
  344. if (cell == tmpCell || end == tmpEnd) {
  345. //只获取单一的单元格
  346. //todo 仅获取单一单元格在特定情况下会造成returns为空,从而影响后续的拖拽实现,修正这个。需考虑性能
  347. if (tmpCell[flag ? "colSpan" : "rowSpan"] == 1) {
  348. returns.push(tmpCell);
  349. }
  350. if (flag) break;
  351. }
  352. }
  353. }
  354. return returns;
  355. } catch (e) {
  356. showError(e);
  357. }
  358. },
  359. setCellContent: function(cell, content) {
  360. cell.innerHTML = content || (browser.ie ? domUtils.fillChar : "<br />");
  361. },
  362. cloneCell: UETable.cloneCell,
  363. /**
  364. * 获取跟当前单元格的右边竖线为左边的所有未合并单元格
  365. */
  366. getSameStartPosXCells: function(cell) {
  367. try {
  368. var start = domUtils.getXY(cell).x + cell.offsetWidth,
  369. rows = this.table.rows,
  370. cells,
  371. returns = [];
  372. for (var i = 0; i < this.rowsNum; i++) {
  373. cells = rows[i].cells;
  374. for (var j = 0, tmpCell; (tmpCell = cells[j++]); ) {
  375. var tmpStart = domUtils.getXY(tmpCell).x;
  376. if (tmpStart > start) break;
  377. if (tmpStart == start && tmpCell.colSpan == 1) {
  378. returns.push(tmpCell);
  379. break;
  380. }
  381. }
  382. }
  383. return returns;
  384. } catch (e) {
  385. showError(e);
  386. }
  387. },
  388. /**
  389. * 更新table对应的索引表
  390. */
  391. update: function(table) {
  392. this.table = table || this.table;
  393. this.selectedTds = [];
  394. this.cellsRange = {};
  395. this.indexTable = [];
  396. var rows = this.table.rows,
  397. rowsNum = this.getMaxRows(),
  398. dNum = rowsNum - rows.length,
  399. colsNum = this.getMaxCols();
  400. while (dNum--) {
  401. this.table.insertRow(rows.length);
  402. }
  403. this.rowsNum = rowsNum;
  404. this.colsNum = colsNum;
  405. for (var i = 0, len = rows.length; i < len; i++) {
  406. this.indexTable[i] = new Array(colsNum);
  407. }
  408. //填充索引表
  409. for (var rowIndex = 0, row; (row = rows[rowIndex]); rowIndex++) {
  410. for (
  411. var cellIndex = 0, cell, cells = row.cells;
  412. (cell = cells[cellIndex]);
  413. cellIndex++
  414. ) {
  415. //修正整行被rowSpan时导致的行数计算错误
  416. if (cell.rowSpan > rowsNum) {
  417. cell.rowSpan = rowsNum;
  418. }
  419. var colIndex = cellIndex,
  420. rowSpan = cell.rowSpan || 1,
  421. colSpan = cell.colSpan || 1;
  422. //当已经被上一行rowSpan或者被前一列colSpan了,则跳到下一个单元格进行
  423. while (this.indexTable[rowIndex][colIndex]) colIndex++;
  424. for (var j = 0; j < rowSpan; j++) {
  425. for (var k = 0; k < colSpan; k++) {
  426. this.indexTable[rowIndex + j][colIndex + k] = {
  427. rowIndex: rowIndex,
  428. cellIndex: cellIndex,
  429. colIndex: colIndex,
  430. rowSpan: rowSpan,
  431. colSpan: colSpan
  432. };
  433. }
  434. }
  435. }
  436. }
  437. //修复残缺td
  438. for (j = 0; j < rowsNum; j++) {
  439. for (k = 0; k < colsNum; k++) {
  440. if (this.indexTable[j][k] === undefined) {
  441. row = rows[j];
  442. cell = row.cells[row.cells.length - 1];
  443. cell = cell
  444. ? cell.cloneNode(true)
  445. : this.table.ownerDocument.createElement("td");
  446. this.setCellContent(cell);
  447. if (cell.colSpan !== 1) cell.colSpan = 1;
  448. if (cell.rowSpan !== 1) cell.rowSpan = 1;
  449. row.appendChild(cell);
  450. this.indexTable[j][k] = {
  451. rowIndex: j,
  452. cellIndex: cell.cellIndex,
  453. colIndex: k,
  454. rowSpan: 1,
  455. colSpan: 1
  456. };
  457. }
  458. }
  459. }
  460. //当框选后删除行或者列后撤销,需要重建选区。
  461. var tds = domUtils.getElementsByTagName(this.table, "td"),
  462. selectTds = [];
  463. utils.each(tds, function(td) {
  464. if (domUtils.hasClass(td, "selectTdClass")) {
  465. selectTds.push(td);
  466. }
  467. });
  468. if (selectTds.length) {
  469. var start = selectTds[0],
  470. end = selectTds[selectTds.length - 1],
  471. startInfo = this.getCellInfo(start),
  472. endInfo = this.getCellInfo(end);
  473. this.selectedTds = selectTds;
  474. this.cellsRange = {
  475. beginRowIndex: startInfo.rowIndex,
  476. beginColIndex: startInfo.colIndex,
  477. endRowIndex: endInfo.rowIndex + endInfo.rowSpan - 1,
  478. endColIndex: endInfo.colIndex + endInfo.colSpan - 1
  479. };
  480. }
  481. //给第一行设置firstRow的样式名称,在排序图标的样式上使用到
  482. if (!domUtils.hasClass(this.table.rows[0], "firstRow")) {
  483. domUtils.addClass(this.table.rows[0], "firstRow");
  484. for (var i = 1; i < this.table.rows.length; i++) {
  485. domUtils.removeClasses(this.table.rows[i], "firstRow");
  486. }
  487. }
  488. },
  489. /**
  490. * 获取单元格的索引信息
  491. */
  492. getCellInfo: function(cell) {
  493. if (!cell) return;
  494. var cellIndex = cell.cellIndex,
  495. rowIndex = cell.parentNode.rowIndex,
  496. rowInfo = this.indexTable[rowIndex],
  497. numCols = this.colsNum;
  498. for (var colIndex = cellIndex; colIndex < numCols; colIndex++) {
  499. var cellInfo = rowInfo[colIndex];
  500. if (
  501. cellInfo.rowIndex === rowIndex &&
  502. cellInfo.cellIndex === cellIndex
  503. ) {
  504. return cellInfo;
  505. }
  506. }
  507. },
  508. /**
  509. * 根据行列号获取单元格
  510. */
  511. getCell: function(rowIndex, cellIndex) {
  512. return (
  513. (rowIndex < this.rowsNum &&
  514. this.table.rows[rowIndex].cells[cellIndex]) ||
  515. null
  516. );
  517. },
  518. /**
  519. * 删除单元格
  520. */
  521. deleteCell: function(cell, rowIndex) {
  522. rowIndex = typeof rowIndex == "number"
  523. ? rowIndex
  524. : cell.parentNode.rowIndex;
  525. var row = this.table.rows[rowIndex];
  526. row.deleteCell(cell.cellIndex);
  527. },
  528. /**
  529. * 根据始末两个单元格获取被框选的所有单元格范围
  530. */
  531. getCellsRange: function(cellA, cellB) {
  532. function checkRange(
  533. beginRowIndex,
  534. beginColIndex,
  535. endRowIndex,
  536. endColIndex
  537. ) {
  538. var tmpBeginRowIndex = beginRowIndex,
  539. tmpBeginColIndex = beginColIndex,
  540. tmpEndRowIndex = endRowIndex,
  541. tmpEndColIndex = endColIndex,
  542. cellInfo,
  543. colIndex,
  544. rowIndex;
  545. // 通过indexTable检查是否存在超出TableRange上边界的情况
  546. if (beginRowIndex > 0) {
  547. for (colIndex = beginColIndex; colIndex < endColIndex; colIndex++) {
  548. cellInfo = me.indexTable[beginRowIndex][colIndex];
  549. rowIndex = cellInfo.rowIndex;
  550. if (rowIndex < beginRowIndex) {
  551. tmpBeginRowIndex = Math.min(rowIndex, tmpBeginRowIndex);
  552. }
  553. }
  554. }
  555. // 通过indexTable检查是否存在超出TableRange右边界的情况
  556. if (endColIndex < me.colsNum) {
  557. for (rowIndex = beginRowIndex; rowIndex < endRowIndex; rowIndex++) {
  558. cellInfo = me.indexTable[rowIndex][endColIndex];
  559. colIndex = cellInfo.colIndex + cellInfo.colSpan - 1;
  560. if (colIndex > endColIndex) {
  561. tmpEndColIndex = Math.max(colIndex, tmpEndColIndex);
  562. }
  563. }
  564. }
  565. // 检查是否有超出TableRange下边界的情况
  566. if (endRowIndex < me.rowsNum) {
  567. for (colIndex = beginColIndex; colIndex < endColIndex; colIndex++) {
  568. cellInfo = me.indexTable[endRowIndex][colIndex];
  569. rowIndex = cellInfo.rowIndex + cellInfo.rowSpan - 1;
  570. if (rowIndex > endRowIndex) {
  571. tmpEndRowIndex = Math.max(rowIndex, tmpEndRowIndex);
  572. }
  573. }
  574. }
  575. // 检查是否有超出TableRange左边界的情况
  576. if (beginColIndex > 0) {
  577. for (rowIndex = beginRowIndex; rowIndex < endRowIndex; rowIndex++) {
  578. cellInfo = me.indexTable[rowIndex][beginColIndex];
  579. colIndex = cellInfo.colIndex;
  580. if (colIndex < beginColIndex) {
  581. tmpBeginColIndex = Math.min(cellInfo.colIndex, tmpBeginColIndex);
  582. }
  583. }
  584. }
  585. //递归调用直至所有完成所有框选单元格的扩展
  586. if (
  587. tmpBeginRowIndex != beginRowIndex ||
  588. tmpBeginColIndex != beginColIndex ||
  589. tmpEndRowIndex != endRowIndex ||
  590. tmpEndColIndex != endColIndex
  591. ) {
  592. return checkRange(
  593. tmpBeginRowIndex,
  594. tmpBeginColIndex,
  595. tmpEndRowIndex,
  596. tmpEndColIndex
  597. );
  598. } else {
  599. // 不需要扩展TableRange的情况
  600. return {
  601. beginRowIndex: beginRowIndex,
  602. beginColIndex: beginColIndex,
  603. endRowIndex: endRowIndex,
  604. endColIndex: endColIndex
  605. };
  606. }
  607. }
  608. try {
  609. var me = this,
  610. cellAInfo = me.getCellInfo(cellA);
  611. if (cellA === cellB) {
  612. return {
  613. beginRowIndex: cellAInfo.rowIndex,
  614. beginColIndex: cellAInfo.colIndex,
  615. endRowIndex: cellAInfo.rowIndex + cellAInfo.rowSpan - 1,
  616. endColIndex: cellAInfo.colIndex + cellAInfo.colSpan - 1
  617. };
  618. }
  619. var cellBInfo = me.getCellInfo(cellB);
  620. // 计算TableRange的四个边
  621. var beginRowIndex = Math.min(cellAInfo.rowIndex, cellBInfo.rowIndex),
  622. beginColIndex = Math.min(cellAInfo.colIndex, cellBInfo.colIndex),
  623. endRowIndex = Math.max(
  624. cellAInfo.rowIndex + cellAInfo.rowSpan - 1,
  625. cellBInfo.rowIndex + cellBInfo.rowSpan - 1
  626. ),
  627. endColIndex = Math.max(
  628. cellAInfo.colIndex + cellAInfo.colSpan - 1,
  629. cellBInfo.colIndex + cellBInfo.colSpan - 1
  630. );
  631. return checkRange(
  632. beginRowIndex,
  633. beginColIndex,
  634. endRowIndex,
  635. endColIndex
  636. );
  637. } catch (e) {
  638. //throw e;
  639. }
  640. },
  641. /**
  642. * 依据cellsRange获取对应的单元格集合
  643. */
  644. getCells: function(range) {
  645. //每次获取cells之前必须先清除上次的选择,否则会对后续获取操作造成影响
  646. this.clearSelected();
  647. var beginRowIndex = range.beginRowIndex,
  648. beginColIndex = range.beginColIndex,
  649. endRowIndex = range.endRowIndex,
  650. endColIndex = range.endColIndex,
  651. cellInfo,
  652. rowIndex,
  653. colIndex,
  654. tdHash = {},
  655. returnTds = [];
  656. for (var i = beginRowIndex; i <= endRowIndex; i++) {
  657. for (var j = beginColIndex; j <= endColIndex; j++) {
  658. cellInfo = this.indexTable[i][j];
  659. rowIndex = cellInfo.rowIndex;
  660. colIndex = cellInfo.colIndex;
  661. // 如果Cells里已经包含了此Cell则跳过
  662. var key = rowIndex + "|" + colIndex;
  663. if (tdHash[key]) continue;
  664. tdHash[key] = 1;
  665. if (
  666. rowIndex < i ||
  667. colIndex < j ||
  668. rowIndex + cellInfo.rowSpan - 1 > endRowIndex ||
  669. colIndex + cellInfo.colSpan - 1 > endColIndex
  670. ) {
  671. return null;
  672. }
  673. returnTds.push(this.getCell(rowIndex, cellInfo.cellIndex));
  674. }
  675. }
  676. return returnTds;
  677. },
  678. /**
  679. * 清理已经选中的单元格
  680. */
  681. clearSelected: function() {
  682. UETable.removeSelectedClass(this.selectedTds);
  683. this.selectedTds = [];
  684. this.cellsRange = {};
  685. },
  686. /**
  687. * 根据range设置已经选中的单元格
  688. */
  689. setSelected: function(range) {
  690. var cells = this.getCells(range);
  691. UETable.addSelectedClass(cells);
  692. this.selectedTds = cells;
  693. this.cellsRange = range;
  694. },
  695. isFullRow: function() {
  696. var range = this.cellsRange;
  697. return range.endColIndex - range.beginColIndex + 1 == this.colsNum;
  698. },
  699. isFullCol: function() {
  700. var range = this.cellsRange,
  701. table = this.table,
  702. ths = table.getElementsByTagName("th"),
  703. rows = range.endRowIndex - range.beginRowIndex + 1;
  704. return !ths.length
  705. ? rows == this.rowsNum
  706. : rows == this.rowsNum || rows == this.rowsNum - 1;
  707. },
  708. /**
  709. * 获取视觉上的前置单元格,默认是左边,top传入时
  710. * @param cell
  711. * @param top
  712. */
  713. getNextCell: function(cell, bottom, ignoreRange) {
  714. try {
  715. var cellInfo = this.getCellInfo(cell),
  716. nextRowIndex,
  717. nextColIndex;
  718. var len = this.selectedTds.length && !ignoreRange,
  719. range = this.cellsRange;
  720. //末行或者末列没有后置单元格
  721. if (
  722. (!bottom && cellInfo.rowIndex == 0) ||
  723. (bottom &&
  724. (!len
  725. ? cellInfo.rowIndex + cellInfo.rowSpan > this.rowsNum - 1
  726. : range.endRowIndex == this.rowsNum - 1))
  727. )
  728. return null;
  729. nextRowIndex = !bottom
  730. ? !len ? cellInfo.rowIndex - 1 : range.beginRowIndex - 1
  731. : !len ? cellInfo.rowIndex + cellInfo.rowSpan : range.endRowIndex + 1;
  732. nextColIndex = !len ? cellInfo.colIndex : range.beginColIndex;
  733. return this.getCell(
  734. this.indexTable[nextRowIndex][nextColIndex].rowIndex,
  735. this.indexTable[nextRowIndex][nextColIndex].cellIndex
  736. );
  737. } catch (e) {
  738. showError(e);
  739. }
  740. },
  741. getPreviewCell: function(cell, top) {
  742. try {
  743. var cellInfo = this.getCellInfo(cell),
  744. previewRowIndex,
  745. previewColIndex;
  746. var len = this.selectedTds.length,
  747. range = this.cellsRange;
  748. //首行或者首列没有前置单元格
  749. if (
  750. (!top && (!len ? !cellInfo.colIndex : !range.beginColIndex)) ||
  751. (top &&
  752. (!len
  753. ? cellInfo.rowIndex > this.colsNum - 1
  754. : range.endColIndex == this.colsNum - 1))
  755. )
  756. return null;
  757. previewRowIndex = !top
  758. ? !len ? cellInfo.rowIndex : range.beginRowIndex
  759. : !len
  760. ? cellInfo.rowIndex < 1 ? 0 : cellInfo.rowIndex - 1
  761. : range.beginRowIndex;
  762. previewColIndex = !top
  763. ? !len
  764. ? cellInfo.colIndex < 1 ? 0 : cellInfo.colIndex - 1
  765. : range.beginColIndex - 1
  766. : !len ? cellInfo.colIndex : range.endColIndex + 1;
  767. return this.getCell(
  768. this.indexTable[previewRowIndex][previewColIndex].rowIndex,
  769. this.indexTable[previewRowIndex][previewColIndex].cellIndex
  770. );
  771. } catch (e) {
  772. showError(e);
  773. }
  774. },
  775. /**
  776. * 移动单元格中的内容
  777. */
  778. moveContent: function(cellTo, cellFrom) {
  779. if (UETable.isEmptyBlock(cellFrom)) return;
  780. if (UETable.isEmptyBlock(cellTo)) {
  781. cellTo.innerHTML = cellFrom.innerHTML;
  782. return;
  783. }
  784. var child = cellTo.lastChild;
  785. if (child.nodeType == 3 || !dtd.$block[child.tagName]) {
  786. cellTo.appendChild(cellTo.ownerDocument.createElement("br"));
  787. }
  788. while ((child = cellFrom.firstChild)) {
  789. cellTo.appendChild(child);
  790. }
  791. },
  792. /**
  793. * 向右合并单元格
  794. */
  795. mergeRight: function(cell) {
  796. var cellInfo = this.getCellInfo(cell),
  797. rightColIndex = cellInfo.colIndex + cellInfo.colSpan,
  798. rightCellInfo = this.indexTable[cellInfo.rowIndex][rightColIndex],
  799. rightCell = this.getCell(
  800. rightCellInfo.rowIndex,
  801. rightCellInfo.cellIndex
  802. );
  803. //合并
  804. cell.colSpan = cellInfo.colSpan + rightCellInfo.colSpan;
  805. //被合并的单元格不应存在宽度属性
  806. cell.removeAttribute("width");
  807. //移动内容
  808. this.moveContent(cell, rightCell);
  809. //删掉被合并的Cell
  810. this.deleteCell(rightCell, rightCellInfo.rowIndex);
  811. this.update();
  812. },
  813. /**
  814. * 向下合并单元格
  815. */
  816. mergeDown: function(cell) {
  817. var cellInfo = this.getCellInfo(cell),
  818. downRowIndex = cellInfo.rowIndex + cellInfo.rowSpan,
  819. downCellInfo = this.indexTable[downRowIndex][cellInfo.colIndex],
  820. downCell = this.getCell(downCellInfo.rowIndex, downCellInfo.cellIndex);
  821. cell.rowSpan = cellInfo.rowSpan + downCellInfo.rowSpan;
  822. cell.removeAttribute("height");
  823. this.moveContent(cell, downCell);
  824. this.deleteCell(downCell, downCellInfo.rowIndex);
  825. this.update();
  826. },
  827. /**
  828. * 合并整个range中的内容
  829. */
  830. mergeRange: function() {
  831. //由于合并操作可以在任意时刻进行,所以无法通过鼠标位置等信息实时生成range,只能通过缓存实例中的cellsRange对象来访问
  832. var range = this.cellsRange,
  833. leftTopCell = this.getCell(
  834. range.beginRowIndex,
  835. this.indexTable[range.beginRowIndex][range.beginColIndex].cellIndex
  836. );
  837. // 这段关于行表头或者列表头的特殊处理会导致表头合并范围错误
  838. // 为什么有这段代码的原因未明,暂且注释掉,希望原作者看到后出面说明下
  839. // if (
  840. // leftTopCell.tagName == "TH" &&
  841. // range.endRowIndex !== range.beginRowIndex
  842. // ) {
  843. // var index = this.indexTable,
  844. // info = this.getCellInfo(leftTopCell);
  845. // leftTopCell = this.getCell(1, index[1][info.colIndex].cellIndex);
  846. // range = this.getCellsRange(
  847. // leftTopCell,
  848. // this.getCell(
  849. // index[this.rowsNum - 1][info.colIndex].rowIndex,
  850. // index[this.rowsNum - 1][info.colIndex].cellIndex
  851. // )
  852. // );
  853. // }
  854. // 删除剩余的Cells
  855. var cells = this.getCells(range);
  856. for (var i = 0, ci; (ci = cells[i++]); ) {
  857. if (ci !== leftTopCell) {
  858. this.moveContent(leftTopCell, ci);
  859. this.deleteCell(ci);
  860. }
  861. }
  862. // 修改左上角Cell的rowSpan和colSpan,并调整宽度属性设置
  863. leftTopCell.rowSpan = range.endRowIndex - range.beginRowIndex + 1;
  864. leftTopCell.rowSpan > 1 && leftTopCell.removeAttribute("height");
  865. leftTopCell.colSpan = range.endColIndex - range.beginColIndex + 1;
  866. leftTopCell.colSpan > 1 && leftTopCell.removeAttribute("width");
  867. if (leftTopCell.rowSpan == this.rowsNum && leftTopCell.colSpan != 1) {
  868. leftTopCell.colSpan = 1;
  869. }
  870. if (leftTopCell.colSpan == this.colsNum && leftTopCell.rowSpan != 1) {
  871. var rowIndex = leftTopCell.parentNode.rowIndex;
  872. //解决IE下的表格操作问题
  873. if (this.table.deleteRow) {
  874. for (
  875. var i = rowIndex + 1,
  876. curIndex = rowIndex + 1,
  877. len = leftTopCell.rowSpan;
  878. i < len;
  879. i++
  880. ) {
  881. this.table.deleteRow(curIndex);
  882. }
  883. } else {
  884. for (var i = 0, len = leftTopCell.rowSpan - 1; i < len; i++) {
  885. var row = this.table.rows[rowIndex + 1];
  886. row.parentNode.removeChild(row);
  887. }
  888. }
  889. leftTopCell.rowSpan = 1;
  890. }
  891. this.update();
  892. },
  893. /**
  894. * 插入一行单元格
  895. */
  896. insertRow: function(rowIndex, sourceCell) {
  897. var numCols = this.colsNum,
  898. table = this.table,
  899. row = table.insertRow(rowIndex),
  900. cell,
  901. thead = null,
  902. isInsertTitle =
  903. typeof sourceCell == "string" && sourceCell.toUpperCase() == "TH";
  904. function replaceTdToTh(colIndex, cell, tableRow) {
  905. if (colIndex == 0) {
  906. var tr = tableRow.nextSibling || tableRow.previousSibling,
  907. th = tr.cells[colIndex];
  908. if (th.tagName == "TH") {
  909. th = cell.ownerDocument.createElement("th");
  910. th.appendChild(cell.firstChild);
  911. tableRow.insertBefore(th, cell);
  912. domUtils.remove(cell);
  913. }
  914. } else {
  915. if (cell.tagName == "TH") {
  916. var td = cell.ownerDocument.createElement("td");
  917. td.appendChild(cell.firstChild);
  918. tableRow.insertBefore(td, cell);
  919. domUtils.remove(cell);
  920. }
  921. }
  922. }
  923. //首行直接插入,无需考虑部分单元格被rowspan的情况
  924. if (rowIndex == 0 || rowIndex == this.rowsNum) {
  925. for (var colIndex = 0; colIndex < numCols; colIndex++) {
  926. cell = this.cloneCell(sourceCell, true);
  927. this.setCellContent(cell);
  928. cell.getAttribute("vAlign") &&
  929. cell.setAttribute("vAlign", cell.getAttribute("vAlign"));
  930. row.appendChild(cell);
  931. if (!isInsertTitle) replaceTdToTh(colIndex, cell, row);
  932. }
  933. if (isInsertTitle) {
  934. thead = table.createTHead();
  935. thead.insertBefore(row, thead.firstChild);
  936. }
  937. } else {
  938. var infoRow = this.indexTable[rowIndex],
  939. cellIndex = 0;
  940. for (colIndex = 0; colIndex < numCols; colIndex++) {
  941. var cellInfo = infoRow[colIndex];
  942. //如果存在某个单元格的rowspan穿过待插入行的位置,则修改该单元格的rowspan即可,无需插入单元格
  943. if (cellInfo.rowIndex < rowIndex) {
  944. cell = this.getCell(cellInfo.rowIndex, cellInfo.cellIndex);
  945. cell.rowSpan = cellInfo.rowSpan + 1;
  946. } else {
  947. cell = this.cloneCell(sourceCell, true);
  948. this.setCellContent(cell);
  949. row.appendChild(cell);
  950. }
  951. if (!isInsertTitle) replaceTdToTh(colIndex, cell, row);
  952. }
  953. }
  954. //框选时插入不触发contentchange,需要手动更新索引。
  955. this.update();
  956. return row;
  957. },
  958. /**
  959. * 删除一行单元格
  960. * @param rowIndex
  961. */
  962. deleteRow: function(rowIndex) {
  963. var row = this.table.rows[rowIndex],
  964. infoRow = this.indexTable[rowIndex],
  965. colsNum = this.colsNum,
  966. count = 0; //处理计数
  967. for (var colIndex = 0; colIndex < colsNum; ) {
  968. var cellInfo = infoRow[colIndex],
  969. cell = this.getCell(cellInfo.rowIndex, cellInfo.cellIndex);
  970. if (cell.rowSpan > 1) {
  971. if (cellInfo.rowIndex == rowIndex) {
  972. var clone = cell.cloneNode(true);
  973. clone.rowSpan = cell.rowSpan - 1;
  974. clone.innerHTML = "";
  975. cell.rowSpan = 1;
  976. var nextRowIndex = rowIndex + 1,
  977. nextRow = this.table.rows[nextRowIndex],
  978. insertCellIndex,
  979. preMerged =
  980. this.getPreviewMergedCellsNum(nextRowIndex, colIndex) - count;
  981. if (preMerged < colIndex) {
  982. insertCellIndex = colIndex - preMerged - 1;
  983. //nextRow.insertCell(insertCellIndex);
  984. domUtils.insertAfter(nextRow.cells[insertCellIndex], clone);
  985. } else {
  986. if (nextRow.cells.length)
  987. nextRow.insertBefore(clone, nextRow.cells[0]);
  988. }
  989. count += 1;
  990. //cell.parentNode.removeChild(cell);
  991. }
  992. }
  993. colIndex += cell.colSpan || 1;
  994. }
  995. var deleteTds = [],
  996. cacheMap = {};
  997. for (colIndex = 0; colIndex < colsNum; colIndex++) {
  998. var tmpRowIndex = infoRow[colIndex].rowIndex,
  999. tmpCellIndex = infoRow[colIndex].cellIndex,
  1000. key = tmpRowIndex + "_" + tmpCellIndex;
  1001. if (cacheMap[key]) continue;
  1002. cacheMap[key] = 1;
  1003. cell = this.getCell(tmpRowIndex, tmpCellIndex);
  1004. deleteTds.push(cell);
  1005. }
  1006. var mergeTds = [];
  1007. utils.each(deleteTds, function(td) {
  1008. if (td.rowSpan == 1) {
  1009. td.parentNode.removeChild(td);
  1010. } else {
  1011. mergeTds.push(td);
  1012. }
  1013. });
  1014. utils.each(mergeTds, function(td) {
  1015. td.rowSpan--;
  1016. });
  1017. row.parentNode.removeChild(row);
  1018. //浏览器方法本身存在bug,采用自定义方法删除
  1019. //this.table.deleteRow(rowIndex);
  1020. this.update();
  1021. },
  1022. insertCol: function(colIndex, sourceCell, defaultValue) {
  1023. var rowsNum = this.rowsNum,
  1024. rowIndex = 0,
  1025. tableRow,
  1026. cell,
  1027. backWidth = parseInt(
  1028. (this.table.offsetWidth -
  1029. (this.colsNum + 1) * 20 -
  1030. (this.colsNum + 1)) /
  1031. (this.colsNum + 1),
  1032. 10
  1033. ),
  1034. isInsertTitleCol =
  1035. typeof sourceCell == "string" && sourceCell.toUpperCase() == "TH";
  1036. function replaceTdToTh(rowIndex, cell, tableRow) {
  1037. if (rowIndex == 0) {
  1038. var th = cell.nextSibling || cell.previousSibling;
  1039. if (th.tagName == "TH") {
  1040. th = cell.ownerDocument.createElement("th");
  1041. th.appendChild(cell.firstChild);
  1042. tableRow.insertBefore(th, cell);
  1043. domUtils.remove(cell);
  1044. }
  1045. } else {
  1046. if (cell.tagName == "TH") {
  1047. var td = cell.ownerDocument.createElement("td");
  1048. td.appendChild(cell.firstChild);
  1049. tableRow.insertBefore(td, cell);
  1050. domUtils.remove(cell);
  1051. }
  1052. }
  1053. }
  1054. var preCell;
  1055. if (colIndex == 0 || colIndex == this.colsNum) {
  1056. for (; rowIndex < rowsNum; rowIndex++) {
  1057. tableRow = this.table.rows[rowIndex];
  1058. preCell =
  1059. tableRow.cells[colIndex == 0 ? colIndex : tableRow.cells.length];
  1060. cell = this.cloneCell(sourceCell, true); //tableRow.insertCell(colIndex == 0 ? colIndex : tableRow.cells.length);
  1061. this.setCellContent(cell);
  1062. cell.setAttribute("vAlign", cell.getAttribute("vAlign"));
  1063. preCell && cell.setAttribute("width", preCell.getAttribute("width"));
  1064. if (!colIndex) {
  1065. tableRow.insertBefore(cell, tableRow.cells[0]);
  1066. } else {
  1067. domUtils.insertAfter(
  1068. tableRow.cells[tableRow.cells.length - 1],
  1069. cell
  1070. );
  1071. }
  1072. if (!isInsertTitleCol) replaceTdToTh(rowIndex, cell, tableRow);
  1073. }
  1074. } else {
  1075. for (; rowIndex < rowsNum; rowIndex++) {
  1076. var cellInfo = this.indexTable[rowIndex][colIndex];
  1077. if (cellInfo.colIndex < colIndex) {
  1078. cell = this.getCell(cellInfo.rowIndex, cellInfo.cellIndex);
  1079. cell.colSpan = cellInfo.colSpan + 1;
  1080. } else {
  1081. tableRow = this.table.rows[rowIndex];
  1082. preCell = tableRow.cells[cellInfo.cellIndex];
  1083. cell = this.cloneCell(sourceCell, true); //tableRow.insertCell(cellInfo.cellIndex);
  1084. this.setCellContent(cell);
  1085. cell.setAttribute("vAlign", cell.getAttribute("vAlign"));
  1086. preCell &&
  1087. cell.setAttribute("width", preCell.getAttribute("width"));
  1088. //防止IE下报错
  1089. preCell
  1090. ? tableRow.insertBefore(cell, preCell)
  1091. : tableRow.appendChild(cell);
  1092. }
  1093. if (!isInsertTitleCol) replaceTdToTh(rowIndex, cell, tableRow);
  1094. }
  1095. }
  1096. //框选时插入不触发contentchange,需要手动更新索引
  1097. this.update();
  1098. this.updateWidth(
  1099. backWidth,
  1100. defaultValue || { tdPadding: 10, tdBorder: 1 }
  1101. );
  1102. },
  1103. updateWidth: function(width, defaultValue) {
  1104. var table = this.table,
  1105. tmpWidth =
  1106. UETable.getWidth(table) -
  1107. defaultValue.tdPadding * 2 -
  1108. defaultValue.tdBorder +
  1109. width;
  1110. if (tmpWidth < table.ownerDocument.body.offsetWidth) {
  1111. table.setAttribute("width", tmpWidth);
  1112. return;
  1113. }
  1114. var tds = domUtils.getElementsByTagName(this.table, "td th");
  1115. utils.each(tds, function(td) {
  1116. td.setAttribute("width", width);
  1117. });
  1118. },
  1119. deleteCol: function(colIndex) {
  1120. var indexTable = this.indexTable,
  1121. tableRows = this.table.rows,
  1122. backTableWidth = this.table.getAttribute("width"),
  1123. backTdWidth = 0,
  1124. rowsNum = this.rowsNum,
  1125. cacheMap = {};
  1126. for (var rowIndex = 0; rowIndex < rowsNum; ) {
  1127. var infoRow = indexTable[rowIndex],
  1128. cellInfo = infoRow[colIndex],
  1129. key = cellInfo.rowIndex + "_" + cellInfo.colIndex;
  1130. // 跳过已经处理过的Cell
  1131. if (cacheMap[key]) continue;
  1132. cacheMap[key] = 1;
  1133. var cell = this.getCell(cellInfo.rowIndex, cellInfo.cellIndex);
  1134. if (!backTdWidth)
  1135. backTdWidth =
  1136. cell && parseInt(cell.offsetWidth / cell.colSpan, 10).toFixed(0);
  1137. // 如果Cell的colSpan大于1, 就修改colSpan, 否则就删掉这个Cell
  1138. if (cell.colSpan > 1) {
  1139. cell.colSpan--;
  1140. } else {
  1141. tableRows[rowIndex].deleteCell(cellInfo.cellIndex);
  1142. }
  1143. rowIndex += cellInfo.rowSpan || 1;
  1144. }
  1145. this.table.setAttribute("width", backTableWidth - backTdWidth);
  1146. this.update();
  1147. },
  1148. splitToCells: function(cell) {
  1149. var me = this,
  1150. cells = this.splitToRows(cell);
  1151. utils.each(cells, function(cell) {
  1152. me.splitToCols(cell);
  1153. });
  1154. },
  1155. splitToRows: function(cell) {
  1156. var cellInfo = this.getCellInfo(cell),
  1157. rowIndex = cellInfo.rowIndex,
  1158. colIndex = cellInfo.colIndex,
  1159. results = [];
  1160. // 修改Cell的rowSpan
  1161. cell.rowSpan = 1;
  1162. results.push(cell);
  1163. // 补齐单元格
  1164. for (
  1165. var i = rowIndex, endRow = rowIndex + cellInfo.rowSpan;
  1166. i < endRow;
  1167. i++
  1168. ) {
  1169. if (i == rowIndex) continue;
  1170. var tableRow = this.table.rows[i],
  1171. tmpCell = tableRow.insertCell(
  1172. colIndex - this.getPreviewMergedCellsNum(i, colIndex)
  1173. );
  1174. tmpCell.colSpan = cellInfo.colSpan;
  1175. this.setCellContent(tmpCell);
  1176. tmpCell.setAttribute("vAlign", cell.getAttribute("vAlign"));
  1177. tmpCell.setAttribute("align", cell.getAttribute("align"));
  1178. if (cell.style.cssText) {
  1179. tmpCell.style.cssText = cell.style.cssText;
  1180. }
  1181. results.push(tmpCell);
  1182. }
  1183. this.update();
  1184. return results;
  1185. },
  1186. getPreviewMergedCellsNum: function(rowIndex, colIndex) {
  1187. var indexRow = this.indexTable[rowIndex],
  1188. num = 0;
  1189. for (var i = 0; i < colIndex; ) {
  1190. var colSpan = indexRow[i].colSpan,
  1191. tmpRowIndex = indexRow[i].rowIndex;
  1192. num += colSpan - (tmpRowIndex == rowIndex ? 1 : 0);
  1193. i += colSpan;
  1194. }
  1195. return num;
  1196. },
  1197. splitToCols: function(cell) {
  1198. var backWidth = (cell.offsetWidth / cell.colSpan - 22).toFixed(0),
  1199. cellInfo = this.getCellInfo(cell),
  1200. rowIndex = cellInfo.rowIndex,
  1201. colIndex = cellInfo.colIndex,
  1202. results = [];
  1203. // 修改Cell的rowSpan
  1204. cell.colSpan = 1;
  1205. cell.setAttribute("width", backWidth);
  1206. results.push(cell);
  1207. // 补齐单元格
  1208. for (
  1209. var j = colIndex, endCol = colIndex + cellInfo.colSpan;
  1210. j < endCol;
  1211. j++
  1212. ) {
  1213. if (j == colIndex) continue;
  1214. var tableRow = this.table.rows[rowIndex],
  1215. tmpCell = tableRow.insertCell(
  1216. this.indexTable[rowIndex][j].cellIndex + 1
  1217. );
  1218. tmpCell.rowSpan = cellInfo.rowSpan;
  1219. this.setCellContent(tmpCell);
  1220. tmpCell.setAttribute("vAlign", cell.getAttribute("vAlign"));
  1221. tmpCell.setAttribute("align", cell.getAttribute("align"));
  1222. tmpCell.setAttribute("width", backWidth);
  1223. if (cell.style.cssText) {
  1224. tmpCell.style.cssText = cell.style.cssText;
  1225. }
  1226. //处理th的情况
  1227. if (cell.tagName == "TH") {
  1228. var th = cell.ownerDocument.createElement("th");
  1229. th.appendChild(tmpCell.firstChild);
  1230. th.setAttribute("vAlign", cell.getAttribute("vAlign"));
  1231. th.rowSpan = tmpCell.rowSpan;
  1232. tableRow.insertBefore(th, tmpCell);
  1233. domUtils.remove(tmpCell);
  1234. }
  1235. results.push(tmpCell);
  1236. }
  1237. this.update();
  1238. return results;
  1239. },
  1240. isLastCell: function(cell, rowsNum, colsNum) {
  1241. rowsNum = rowsNum || this.rowsNum;
  1242. colsNum = colsNum || this.colsNum;
  1243. var cellInfo = this.getCellInfo(cell);
  1244. return (
  1245. cellInfo.rowIndex + cellInfo.rowSpan == rowsNum &&
  1246. cellInfo.colIndex + cellInfo.colSpan == colsNum
  1247. );
  1248. },
  1249. getLastCell: function(cells) {
  1250. cells = cells || this.table.getElementsByTagName("td");
  1251. var firstInfo = this.getCellInfo(cells[0]);
  1252. var me = this,
  1253. last = cells[0],
  1254. tr = last.parentNode,
  1255. cellsNum = 0,
  1256. cols = 0,
  1257. rows;
  1258. utils.each(cells, function(cell) {
  1259. if (cell.parentNode == tr) cols += cell.colSpan || 1;
  1260. cellsNum += cell.rowSpan * cell.colSpan || 1;
  1261. });
  1262. rows = cellsNum / cols;
  1263. utils.each(cells, function(cell) {
  1264. if (me.isLastCell(cell, rows, cols)) {
  1265. last = cell;
  1266. return false;
  1267. }
  1268. });
  1269. return last;
  1270. },
  1271. selectRow: function(rowIndex) {
  1272. var indexRow = this.indexTable[rowIndex],
  1273. start = this.getCell(indexRow[0].rowIndex, indexRow[0].cellIndex),
  1274. end = this.getCell(
  1275. indexRow[this.colsNum - 1].rowIndex,
  1276. indexRow[this.colsNum - 1].cellIndex
  1277. ),
  1278. range = this.getCellsRange(start, end);
  1279. this.setSelected(range);
  1280. },
  1281. selectTable: function() {
  1282. var tds = this.table.getElementsByTagName("td"),
  1283. range = this.getCellsRange(tds[0], tds[tds.length - 1]);
  1284. this.setSelected(range);
  1285. },
  1286. setBackground: function(cells, value) {
  1287. if (typeof value === "string") {
  1288. utils.each(cells, function(cell) {
  1289. cell.style.backgroundColor = value;
  1290. });
  1291. } else if (typeof value === "object") {
  1292. value = utils.extend(
  1293. {
  1294. repeat: true,
  1295. colorList: ["#ddd", "#fff"]
  1296. },
  1297. value
  1298. );
  1299. var rowIndex = this.getCellInfo(cells[0]).rowIndex,
  1300. count = 0,
  1301. colors = value.colorList,
  1302. getColor = function(list, index, repeat) {
  1303. return list[index]
  1304. ? list[index]
  1305. : repeat ? list[index % list.length] : "";
  1306. };
  1307. for (var i = 0, cell; (cell = cells[i++]); ) {
  1308. var cellInfo = this.getCellInfo(cell);
  1309. cell.style.backgroundColor = getColor(
  1310. colors,
  1311. rowIndex + count == cellInfo.rowIndex ? count : ++count,
  1312. value.repeat
  1313. );
  1314. }
  1315. }
  1316. },
  1317. removeBackground: function(cells) {
  1318. utils.each(cells, function(cell) {
  1319. cell.style.backgroundColor = "";
  1320. });
  1321. }
  1322. };
  1323. function showError(e) {}
  1324. })();