table.action.js 67 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875
  1. /**
  2. * Created with JetBrains PhpStorm.
  3. * User: taoqili
  4. * Date: 12-10-12
  5. * Time: 上午10:05
  6. * To change this template use File | Settings | File Templates.
  7. */
  8. UE.plugins['table'] = function () {
  9. var me = this,
  10. tabTimer = null,
  11. //拖动计时器
  12. tableDragTimer = null,
  13. //双击计时器
  14. tableResizeTimer = null,
  15. //单元格最小宽度
  16. cellMinWidth = 5,
  17. isInResizeBuffer = false,
  18. //单元格边框大小
  19. cellBorderWidth = 5,
  20. //鼠标偏移距离
  21. offsetOfTableCell = 10,
  22. //记录在有限时间内的点击状态, 共有3个取值, 0, 1, 2。 0代表未初始化, 1代表单击了1次,2代表2次
  23. singleClickState = 0,
  24. userActionStatus = null,
  25. //双击允许的时间范围
  26. dblclickTime = 360,
  27. UT = UE.UETable,
  28. getUETable = function (tdOrTable) {
  29. return UT.getUETable(tdOrTable);
  30. },
  31. getUETableBySelected = function (editor) {
  32. return UT.getUETableBySelected(editor);
  33. },
  34. getDefaultValue = function (editor, table) {
  35. return UT.getDefaultValue(editor, table);
  36. },
  37. removeSelectedClass = function (cells) {
  38. return UT.removeSelectedClass(cells);
  39. };
  40. function showError(e) {
  41. // throw e;
  42. }
  43. me.ready(function(){
  44. var me = this;
  45. var orgGetText = me.selection.getText;
  46. me.selection.getText = function(){
  47. var table = getUETableBySelected(me);
  48. if(table){
  49. var str = '';
  50. utils.each(table.selectedTds,function(td){
  51. str += td[browser.ie?'innerText':'textContent'];
  52. })
  53. return str;
  54. }else{
  55. return orgGetText.call(me.selection)
  56. }
  57. }
  58. })
  59. //处理拖动及框选相关方法
  60. var startTd = null, //鼠标按下时的锚点td
  61. currentTd = null, //当前鼠标经过时的td
  62. onDrag = "", //指示当前拖动状态,其值可为"","h","v" ,分别表示未拖动状态,横向拖动状态,纵向拖动状态,用于鼠标移动过程中的判断
  63. onBorder = false, //检测鼠标按下时是否处在单元格边缘位置
  64. dragButton = null,
  65. dragOver = false,
  66. dragLine = null, //模拟的拖动线
  67. dragTd = null; //发生拖动的目标td
  68. var mousedown = false,
  69. //todo 判断混乱模式
  70. needIEHack = true;
  71. me.setOpt({
  72. 'maxColNum':20,
  73. 'maxRowNum':100,
  74. 'defaultCols':5,
  75. 'defaultRows':5,
  76. 'tdvalign':'top',
  77. 'cursorpath':me.options.UEDITOR_HOME_URL + "themes/default/images/cursor_",
  78. 'tableDragable':false,
  79. 'classList':["ue-table-interlace-color-single","ue-table-interlace-color-double"]
  80. });
  81. me.getUETable = getUETable;
  82. var commands = {
  83. 'deletetable':1,
  84. 'inserttable':1,
  85. 'cellvalign':1,
  86. 'insertcaption':1,
  87. 'deletecaption':1,
  88. 'inserttitle':1,
  89. 'deletetitle':1,
  90. "mergeright":1,
  91. "mergedown":1,
  92. "mergecells":1,
  93. "insertrow":1,
  94. "insertrownext":1,
  95. "deleterow":1,
  96. "insertcol":1,
  97. "insertcolnext":1,
  98. "deletecol":1,
  99. "splittocells":1,
  100. "splittorows":1,
  101. "splittocols":1,
  102. "adaptbytext":1,
  103. "adaptbywindow":1,
  104. "adaptbycustomer":1,
  105. "insertparagraph":1,
  106. "insertparagraphbeforetable":1,
  107. "averagedistributecol":1,
  108. "averagedistributerow":1
  109. };
  110. me.ready(function () {
  111. utils.cssRule('table',
  112. //选中的td上的样式
  113. '.selectTdClass{background-color:#edf5fa !important}' +
  114. 'table.noBorderTable td,table.noBorderTable th,table.noBorderTable caption{border:1px dashed #ddd !important}' +
  115. //插入的表格的默认样式
  116. 'table{margin-bottom:10px;border-collapse:collapse;display:table;}' +
  117. 'td,th{padding: 5px 10px;border: 1px solid #DDD;}' +
  118. 'caption{border:1px dashed #DDD;border-bottom:0;padding:3px;text-align:center;}' +
  119. 'th{border-top:1px solid #BBB;background-color:#F7F7F7;}' +
  120. 'table tr.firstRow th{border-top-width:2px;}' +
  121. '.ue-table-interlace-color-single{ background-color: #fcfcfc; } .ue-table-interlace-color-double{ background-color: #f7faff; }' +
  122. 'td p{margin:0;padding:0;}', me.document);
  123. var tableCopyList, isFullCol, isFullRow;
  124. //注册del/backspace事件
  125. me.addListener('keydown', function (cmd, evt) {
  126. var me = this;
  127. var keyCode = evt.keyCode || evt.which;
  128. if (keyCode == 8) {
  129. var ut = getUETableBySelected(me);
  130. if (ut && ut.selectedTds.length) {
  131. if (ut.isFullCol()) {
  132. me.execCommand('deletecol')
  133. } else if (ut.isFullRow()) {
  134. me.execCommand('deleterow')
  135. } else {
  136. me.fireEvent('delcells');
  137. }
  138. domUtils.preventDefault(evt);
  139. }
  140. var caption = domUtils.findParentByTagName(me.selection.getStart(), 'caption', true),
  141. range = me.selection.getRange();
  142. if (range.collapsed && caption && isEmptyBlock(caption)) {
  143. me.fireEvent('saveScene');
  144. var table = caption.parentNode;
  145. domUtils.remove(caption);
  146. if (table) {
  147. range.setStart(table.rows[0].cells[0], 0).setCursor(false, true);
  148. }
  149. me.fireEvent('saveScene');
  150. }
  151. }
  152. if (keyCode == 46) {
  153. ut = getUETableBySelected(me);
  154. if (ut) {
  155. me.fireEvent('saveScene');
  156. for (var i = 0, ci; ci = ut.selectedTds[i++];) {
  157. domUtils.fillNode(me.document, ci)
  158. }
  159. me.fireEvent('saveScene');
  160. domUtils.preventDefault(evt);
  161. }
  162. }
  163. if (keyCode == 13) {
  164. var rng = me.selection.getRange(),
  165. caption = domUtils.findParentByTagName(rng.startContainer, 'caption', true);
  166. if (caption) {
  167. var table = domUtils.findParentByTagName(caption, 'table');
  168. if (!rng.collapsed) {
  169. rng.deleteContents();
  170. me.fireEvent('saveScene');
  171. } else {
  172. if (caption) {
  173. rng.setStart(table.rows[0].cells[0], 0).setCursor(false, true);
  174. }
  175. }
  176. domUtils.preventDefault(evt);
  177. return;
  178. }
  179. if (rng.collapsed) {
  180. var table = domUtils.findParentByTagName(rng.startContainer, 'table');
  181. if (table) {
  182. var cell = table.rows[0].cells[0],
  183. start = domUtils.findParentByTagName(me.selection.getStart(), ['td', 'th'], true),
  184. preNode = table.previousSibling;
  185. if (cell === start && (!preNode || preNode.nodeType == 1 && preNode.tagName == 'TABLE' ) && domUtils.isStartInblock(rng)) {
  186. var first = domUtils.findParent(me.selection.getStart(), function(n){return domUtils.isBlockElm(n)}, true);
  187. if(first && ( /t(h|d)/i.test(first.tagName) || first === start.firstChild )){
  188. me.execCommand('insertparagraphbeforetable');
  189. domUtils.preventDefault(evt);
  190. }
  191. }
  192. }
  193. }
  194. }
  195. if ((evt.ctrlKey || evt.metaKey) && evt.keyCode == '67') {
  196. tableCopyList = null;
  197. var ut = getUETableBySelected(me);
  198. if (ut) {
  199. var tds = ut.selectedTds;
  200. isFullCol = ut.isFullCol();
  201. isFullRow = ut.isFullRow();
  202. tableCopyList = [
  203. [ut.cloneCell(tds[0],null,true)]
  204. ];
  205. for (var i = 1, ci; ci = tds[i]; i++) {
  206. if (ci.parentNode !== tds[i - 1].parentNode) {
  207. tableCopyList.push([ut.cloneCell(ci,null,true)]);
  208. } else {
  209. tableCopyList[tableCopyList.length - 1].push(ut.cloneCell(ci,null,true));
  210. }
  211. }
  212. }
  213. }
  214. });
  215. me.addListener("tablehasdeleted",function(){
  216. toggleDraggableState(this, false, "", null);
  217. if (dragButton)domUtils.remove(dragButton);
  218. });
  219. me.addListener('beforepaste', function (cmd, html) {
  220. var me = this;
  221. var rng = me.selection.getRange();
  222. if (domUtils.findParentByTagName(rng.startContainer, 'caption', true)) {
  223. var div = me.document.createElement("div");
  224. div.innerHTML = html.html;
  225. //trace:3729
  226. html.html = div[browser.ie9below ? 'innerText' : 'textContent'];
  227. return;
  228. }
  229. var table = getUETableBySelected(me);
  230. if (tableCopyList) {
  231. me.fireEvent('saveScene');
  232. var rng = me.selection.getRange();
  233. var td = domUtils.findParentByTagName(rng.startContainer, ['td', 'th'], true), tmpNode, preNode;
  234. if (td) {
  235. var ut = getUETable(td);
  236. if (isFullRow) {
  237. var rowIndex = ut.getCellInfo(td).rowIndex;
  238. if (td.tagName == 'TH') {
  239. rowIndex++;
  240. }
  241. for (var i = 0, ci; ci = tableCopyList[i++];) {
  242. var tr = ut.insertRow(rowIndex++, "td");
  243. for (var j = 0, cj; cj = ci[j]; j++) {
  244. var cell = tr.cells[j];
  245. if (!cell) {
  246. cell = tr.insertCell(j)
  247. }
  248. cell.innerHTML = cj.innerHTML;
  249. cj.getAttribute('width') && cell.setAttribute('width', cj.getAttribute('width'));
  250. cj.getAttribute('vAlign') && cell.setAttribute('vAlign', cj.getAttribute('vAlign'));
  251. cj.getAttribute('align') && cell.setAttribute('align', cj.getAttribute('align'));
  252. cj.style.cssText && (cell.style.cssText = cj.style.cssText)
  253. }
  254. for (var j = 0, cj; cj = tr.cells[j]; j++) {
  255. if (!ci[j])
  256. break;
  257. cj.innerHTML = ci[j].innerHTML;
  258. ci[j].getAttribute('width') && cj.setAttribute('width', ci[j].getAttribute('width'));
  259. ci[j].getAttribute('vAlign') && cj.setAttribute('vAlign', ci[j].getAttribute('vAlign'));
  260. ci[j].getAttribute('align') && cj.setAttribute('align', ci[j].getAttribute('align'));
  261. ci[j].style.cssText && (cj.style.cssText = ci[j].style.cssText)
  262. }
  263. }
  264. } else {
  265. if (isFullCol) {
  266. cellInfo = ut.getCellInfo(td);
  267. var maxColNum = 0;
  268. for (var j = 0, ci = tableCopyList[0], cj; cj = ci[j++];) {
  269. maxColNum += cj.colSpan || 1;
  270. }
  271. me.__hasEnterExecCommand = true;
  272. for (i = 0; i < maxColNum; i++) {
  273. me.execCommand('insertcol');
  274. }
  275. me.__hasEnterExecCommand = false;
  276. td = ut.table.rows[0].cells[cellInfo.cellIndex];
  277. if (td.tagName == 'TH') {
  278. td = ut.table.rows[1].cells[cellInfo.cellIndex];
  279. }
  280. }
  281. for (var i = 0, ci; ci = tableCopyList[i++];) {
  282. tmpNode = td;
  283. for (var j = 0, cj; cj = ci[j++];) {
  284. if (td) {
  285. td.innerHTML = cj.innerHTML;
  286. //todo 定制处理
  287. cj.getAttribute('width') && td.setAttribute('width', cj.getAttribute('width'));
  288. cj.getAttribute('vAlign') && td.setAttribute('vAlign', cj.getAttribute('vAlign'));
  289. cj.getAttribute('align') && td.setAttribute('align', cj.getAttribute('align'));
  290. cj.style.cssText && (td.style.cssText = cj.style.cssText);
  291. preNode = td;
  292. td = td.nextSibling;
  293. } else {
  294. var cloneTd = cj.cloneNode(true);
  295. domUtils.removeAttributes(cloneTd, ['class', 'rowSpan', 'colSpan']);
  296. preNode.parentNode.appendChild(cloneTd)
  297. }
  298. }
  299. td = ut.getNextCell(tmpNode, true, true);
  300. if (!tableCopyList[i])
  301. break;
  302. if (!td) {
  303. var cellInfo = ut.getCellInfo(tmpNode);
  304. ut.table.insertRow(ut.table.rows.length);
  305. ut.update();
  306. td = ut.getVSideCell(tmpNode, true);
  307. }
  308. }
  309. }
  310. ut.update();
  311. } else {
  312. table = me.document.createElement('table');
  313. for (var i = 0, ci; ci = tableCopyList[i++];) {
  314. var tr = table.insertRow(table.rows.length);
  315. for (var j = 0, cj; cj = ci[j++];) {
  316. cloneTd = UT.cloneCell(cj,null,true);
  317. domUtils.removeAttributes(cloneTd, ['class']);
  318. tr.appendChild(cloneTd)
  319. }
  320. if (j == 2 && cloneTd.rowSpan > 1) {
  321. cloneTd.rowSpan = 1;
  322. }
  323. }
  324. var defaultValue = getDefaultValue(me),
  325. width = me.body.offsetWidth -
  326. (needIEHack ? parseInt(domUtils.getComputedStyle(me.body, 'margin-left'), 10) * 2 : 0) - defaultValue.tableBorder * 2 - (me.options.offsetWidth || 0);
  327. me.execCommand('insertHTML', '<table ' +
  328. ( isFullCol && isFullRow ? 'width="' + width + '"' : '') +
  329. '>' + table.innerHTML.replace(/>\s*</g, '><').replace(/\bth\b/gi, "td") + '</table>')
  330. }
  331. me.fireEvent('contentchange');
  332. me.fireEvent('saveScene');
  333. html.html = '';
  334. return true;
  335. } else {
  336. var div = me.document.createElement("div"), tables;
  337. div.innerHTML = html.html;
  338. tables = div.getElementsByTagName("table");
  339. if (domUtils.findParentByTagName(me.selection.getStart(), 'table')) {
  340. utils.each(tables, function (t) {
  341. domUtils.remove(t)
  342. });
  343. if (domUtils.findParentByTagName(me.selection.getStart(), 'caption', true)) {
  344. div.innerHTML = div[browser.ie ? 'innerText' : 'textContent'];
  345. }
  346. } else {
  347. utils.each(tables, function (table) {
  348. removeStyleSize(table, true);
  349. domUtils.removeAttributes(table, ['style', 'border']);
  350. utils.each(domUtils.getElementsByTagName(table, "td"), function (td) {
  351. if (isEmptyBlock(td)) {
  352. domUtils.fillNode(me.document, td);
  353. }
  354. removeStyleSize(td, true);
  355. // domUtils.removeAttributes(td, ['style'])
  356. });
  357. });
  358. }
  359. html.html = div.innerHTML;
  360. }
  361. });
  362. me.addListener('afterpaste', function () {
  363. utils.each(domUtils.getElementsByTagName(me.body, "table"), function (table) {
  364. if (table.offsetWidth > me.body.offsetWidth) {
  365. var defaultValue = getDefaultValue(me, table);
  366. table.style.width = me.body.offsetWidth - (needIEHack ? parseInt(domUtils.getComputedStyle(me.body, 'margin-left'), 10) * 2 : 0) - defaultValue.tableBorder * 2 - (me.options.offsetWidth || 0) + 'px'
  367. }
  368. })
  369. });
  370. me.addListener('blur', function () {
  371. tableCopyList = null;
  372. });
  373. var timer;
  374. me.addListener('keydown', function () {
  375. clearTimeout(timer);
  376. timer = setTimeout(function () {
  377. var rng = me.selection.getRange(),
  378. cell = domUtils.findParentByTagName(rng.startContainer, ['th', 'td'], true);
  379. if (cell) {
  380. var table = cell.parentNode.parentNode.parentNode;
  381. if (table.offsetWidth > table.getAttribute("width")) {
  382. cell.style.wordBreak = "break-all";
  383. }
  384. }
  385. }, 100);
  386. });
  387. me.addListener("selectionchange", function () {
  388. toggleDraggableState(me, false, "", null);
  389. });
  390. //内容变化时触发索引更新
  391. //todo 可否考虑标记检测,如果不涉及表格的变化就不进行索引重建和更新
  392. me.addListener("contentchange", function () {
  393. var me = this;
  394. //尽可能排除一些不需要更新的状况
  395. hideDragLine(me);
  396. if (getUETableBySelected(me))return;
  397. var rng = me.selection.getRange();
  398. var start = rng.startContainer;
  399. start = domUtils.findParentByTagName(start, ['td', 'th'], true);
  400. utils.each(domUtils.getElementsByTagName(me.document, 'table'), function (table) {
  401. if (me.fireEvent("excludetable", table) === true) return;
  402. table.ueTable = new UT(table);
  403. //trace:3742
  404. // utils.each(domUtils.getElementsByTagName(me.document, 'td'), function (td) {
  405. //
  406. // if (domUtils.isEmptyBlock(td) && td !== start) {
  407. // domUtils.fillNode(me.document, td);
  408. // if (browser.ie && browser.version == 6) {
  409. // td.innerHTML = '&nbsp;'
  410. // }
  411. // }
  412. // });
  413. // utils.each(domUtils.getElementsByTagName(me.document, 'th'), function (th) {
  414. // if (domUtils.isEmptyBlock(th) && th !== start) {
  415. // domUtils.fillNode(me.document, th);
  416. // if (browser.ie && browser.version == 6) {
  417. // th.innerHTML = '&nbsp;'
  418. // }
  419. // }
  420. // });
  421. table.onmouseover = function () {
  422. me.fireEvent('tablemouseover', table);
  423. };
  424. table.onmousemove = function () {
  425. me.fireEvent('tablemousemove', table);
  426. me.options.tableDragable && toggleDragButton(true, this, me);
  427. utils.defer(function(){
  428. me.fireEvent('contentchange',50)
  429. },true)
  430. };
  431. table.onmouseout = function () {
  432. me.fireEvent('tablemouseout', table);
  433. toggleDraggableState(me, false, "", null);
  434. hideDragLine(me);
  435. };
  436. table.onclick = function (evt) {
  437. evt = me.window.event || evt;
  438. var target = getParentTdOrTh(evt.target || evt.srcElement);
  439. if (!target)return;
  440. var ut = getUETable(target),
  441. table = ut.table,
  442. cellInfo = ut.getCellInfo(target),
  443. cellsRange,
  444. rng = me.selection.getRange();
  445. // if ("topLeft" == inPosition(table, mouseCoords(evt))) {
  446. // cellsRange = ut.getCellsRange(ut.table.rows[0].cells[0], ut.getLastCell());
  447. // ut.setSelected(cellsRange);
  448. // return;
  449. // }
  450. // if ("bottomRight" == inPosition(table, mouseCoords(evt))) {
  451. //
  452. // return;
  453. // }
  454. if (inTableSide(table, target, evt, true)) {
  455. var endTdCol = ut.getCell(ut.indexTable[ut.rowsNum - 1][cellInfo.colIndex].rowIndex, ut.indexTable[ut.rowsNum - 1][cellInfo.colIndex].cellIndex);
  456. if (evt.shiftKey && ut.selectedTds.length) {
  457. if (ut.selectedTds[0] !== endTdCol) {
  458. cellsRange = ut.getCellsRange(ut.selectedTds[0], endTdCol);
  459. ut.setSelected(cellsRange);
  460. } else {
  461. rng && rng.selectNodeContents(endTdCol).select();
  462. }
  463. } else {
  464. if (target !== endTdCol) {
  465. cellsRange = ut.getCellsRange(target, endTdCol);
  466. ut.setSelected(cellsRange);
  467. } else {
  468. rng && rng.selectNodeContents(endTdCol).select();
  469. }
  470. }
  471. return;
  472. }
  473. if (inTableSide(table, target, evt)) {
  474. var endTdRow = ut.getCell(ut.indexTable[cellInfo.rowIndex][ut.colsNum - 1].rowIndex, ut.indexTable[cellInfo.rowIndex][ut.colsNum - 1].cellIndex);
  475. if (evt.shiftKey && ut.selectedTds.length) {
  476. if (ut.selectedTds[0] !== endTdRow) {
  477. cellsRange = ut.getCellsRange(ut.selectedTds[0], endTdRow);
  478. ut.setSelected(cellsRange);
  479. } else {
  480. rng && rng.selectNodeContents(endTdRow).select();
  481. }
  482. } else {
  483. if (target !== endTdRow) {
  484. cellsRange = ut.getCellsRange(target, endTdRow);
  485. ut.setSelected(cellsRange);
  486. } else {
  487. rng && rng.selectNodeContents(endTdRow).select();
  488. }
  489. }
  490. }
  491. };
  492. });
  493. switchBorderColor(me, true);
  494. });
  495. domUtils.on(me.document, "mousemove", mouseMoveEvent);
  496. domUtils.on(me.document, "mouseout", function (evt) {
  497. var target = evt.target || evt.srcElement;
  498. if (target.tagName == "TABLE") {
  499. toggleDraggableState(me, false, "", null);
  500. }
  501. });
  502. /**
  503. * 表格隔行变色
  504. */
  505. me.addListener("interlacetable",function(type,table,classList){
  506. if(!table) return;
  507. var me = this,
  508. rows = table.rows,
  509. len = rows.length,
  510. getClass = function(list,index,repeat){
  511. return list[index] ? list[index] : repeat ? list[index % list.length]: "";
  512. };
  513. for(var i = 0;i<len;i++){
  514. rows[i].className = getClass( classList|| me.options.classList,i,true);
  515. }
  516. });
  517. me.addListener("uninterlacetable",function(type,table){
  518. if(!table) return;
  519. var me = this,
  520. rows = table.rows,
  521. classList = me.options.classList,
  522. len = rows.length;
  523. for(var i = 0;i<len;i++){
  524. domUtils.removeClasses( rows[i], classList );
  525. }
  526. });
  527. me.addListener("mousedown", mouseDownEvent);
  528. me.addListener("mouseup", mouseUpEvent);
  529. //拖动的时候触发mouseup
  530. domUtils.on( me.body, 'dragstart', function( evt ){
  531. mouseUpEvent.call( me, 'dragstart', evt );
  532. });
  533. me.addOutputRule(function(root){
  534. utils.each(root.getNodesByTagName('div'),function(n){
  535. if (n.getAttr('id') == 'ue_tableDragLine') {
  536. n.parentNode.removeChild(n);
  537. }
  538. });
  539. });
  540. var currentRowIndex = 0;
  541. me.addListener("mousedown", function () {
  542. currentRowIndex = 0;
  543. });
  544. me.addListener('tabkeydown', function () {
  545. var range = this.selection.getRange(),
  546. common = range.getCommonAncestor(true, true),
  547. table = domUtils.findParentByTagName(common, 'table');
  548. if (table) {
  549. if (domUtils.findParentByTagName(common, 'caption', true)) {
  550. var cell = domUtils.getElementsByTagName(table, 'th td');
  551. if (cell && cell.length) {
  552. range.setStart(cell[0], 0).setCursor(false, true)
  553. }
  554. } else {
  555. var cell = domUtils.findParentByTagName(common, ['td', 'th'], true),
  556. ua = getUETable(cell);
  557. currentRowIndex = cell.rowSpan > 1 ? currentRowIndex : ua.getCellInfo(cell).rowIndex;
  558. var nextCell = ua.getTabNextCell(cell, currentRowIndex);
  559. if (nextCell) {
  560. if (isEmptyBlock(nextCell)) {
  561. range.setStart(nextCell, 0).setCursor(false, true)
  562. } else {
  563. range.selectNodeContents(nextCell).select()
  564. }
  565. } else {
  566. me.fireEvent('saveScene');
  567. me.__hasEnterExecCommand = true;
  568. this.execCommand('insertrownext');
  569. me.__hasEnterExecCommand = false;
  570. range = this.selection.getRange();
  571. range.setStart(table.rows[table.rows.length - 1].cells[0], 0).setCursor();
  572. me.fireEvent('saveScene');
  573. }
  574. }
  575. return true;
  576. }
  577. });
  578. browser.ie && me.addListener('selectionchange', function () {
  579. toggleDraggableState(this, false, "", null);
  580. });
  581. me.addListener("keydown", function (type, evt) {
  582. var me = this;
  583. //处理在表格的最后一个输入tab产生新的表格
  584. var keyCode = evt.keyCode || evt.which;
  585. if (keyCode == 8 || keyCode == 46) {
  586. return;
  587. }
  588. var notCtrlKey = !evt.ctrlKey && !evt.metaKey && !evt.shiftKey && !evt.altKey;
  589. notCtrlKey && removeSelectedClass(domUtils.getElementsByTagName(me.body, "td"));
  590. var ut = getUETableBySelected(me);
  591. if (!ut) return;
  592. notCtrlKey && ut.clearSelected();
  593. });
  594. me.addListener("beforegetcontent", function () {
  595. switchBorderColor(this, false);
  596. browser.ie && utils.each(this.document.getElementsByTagName('caption'), function (ci) {
  597. if (domUtils.isEmptyNode(ci)) {
  598. ci.innerHTML = '&nbsp;'
  599. }
  600. });
  601. });
  602. me.addListener("aftergetcontent", function () {
  603. switchBorderColor(this, true);
  604. });
  605. me.addListener("getAllHtml", function () {
  606. removeSelectedClass(me.document.getElementsByTagName("td"));
  607. });
  608. //修正全屏状态下插入的表格宽度在非全屏状态下撑开编辑器的情况
  609. me.addListener("fullscreenchanged", function (type, fullscreen) {
  610. if (!fullscreen) {
  611. var ratio = this.body.offsetWidth / document.body.offsetWidth,
  612. tables = domUtils.getElementsByTagName(this.body, "table");
  613. utils.each(tables, function (table) {
  614. if (table.offsetWidth < me.body.offsetWidth) return false;
  615. var tds = domUtils.getElementsByTagName(table, "td"),
  616. backWidths = [];
  617. utils.each(tds, function (td) {
  618. backWidths.push(td.offsetWidth);
  619. });
  620. for (var i = 0, td; td = tds[i]; i++) {
  621. td.setAttribute("width", Math.floor(backWidths[i] * ratio));
  622. }
  623. table.setAttribute("width", Math.floor(getTableWidth(me, needIEHack, getDefaultValue(me))))
  624. });
  625. }
  626. });
  627. //重写execCommand命令,用于处理框选时的处理
  628. var oldExecCommand = me.execCommand;
  629. me.execCommand = function (cmd, datatat) {
  630. var me = this,
  631. args = arguments;
  632. cmd = cmd.toLowerCase();
  633. var ut = getUETableBySelected(me), tds,
  634. range = new dom.Range(me.document),
  635. cmdFun = me.commands[cmd] || UE.commands[cmd],
  636. result;
  637. if (!cmdFun) return;
  638. if (ut && !commands[cmd] && !cmdFun.notNeedUndo && !me.__hasEnterExecCommand) {
  639. me.__hasEnterExecCommand = true;
  640. me.fireEvent("beforeexeccommand", cmd);
  641. tds = ut.selectedTds;
  642. var lastState = -2, lastValue = -2, value, state;
  643. for (var i = 0, td; td = tds[i]; i++) {
  644. if (isEmptyBlock(td)) {
  645. range.setStart(td, 0).setCursor(false, true)
  646. } else {
  647. range.selectNode(td).select(true);
  648. }
  649. state = me.queryCommandState(cmd);
  650. value = me.queryCommandValue(cmd);
  651. if (state != -1) {
  652. if (lastState !== state || lastValue !== value) {
  653. me._ignoreContentChange = true;
  654. result = oldExecCommand.apply(me, arguments);
  655. me._ignoreContentChange = false;
  656. }
  657. lastState = me.queryCommandState(cmd);
  658. lastValue = me.queryCommandValue(cmd);
  659. if (domUtils.isEmptyBlock(td)) {
  660. domUtils.fillNode(me.document, td)
  661. }
  662. }
  663. }
  664. range.setStart(tds[0], 0).shrinkBoundary(true).setCursor(false, true);
  665. me.fireEvent('contentchange');
  666. me.fireEvent("afterexeccommand", cmd);
  667. me.__hasEnterExecCommand = false;
  668. me._selectionChange();
  669. } else {
  670. result = oldExecCommand.apply(me, arguments);
  671. }
  672. return result;
  673. };
  674. });
  675. /**
  676. * 删除obj的宽高style,改成属性宽高
  677. * @param obj
  678. * @param replaceToProperty
  679. */
  680. function removeStyleSize(obj, replaceToProperty) {
  681. removeStyle(obj, "width", true);
  682. removeStyle(obj, "height", true);
  683. }
  684. function removeStyle(obj, styleName, replaceToProperty) {
  685. if (obj.style[styleName]) {
  686. replaceToProperty && obj.setAttribute(styleName, parseInt(obj.style[styleName], 10));
  687. obj.style[styleName] = "";
  688. }
  689. }
  690. function getParentTdOrTh(ele) {
  691. if (ele.tagName == "TD" || ele.tagName == "TH") return ele;
  692. var td;
  693. if (td = domUtils.findParentByTagName(ele, "td", true) || domUtils.findParentByTagName(ele, "th", true)) return td;
  694. return null;
  695. }
  696. function isEmptyBlock(node) {
  697. var reg = new RegExp(domUtils.fillChar, 'g');
  698. if (node[browser.ie ? 'innerText' : 'textContent'].replace(/^\s*$/, '').replace(reg, '').length > 0) {
  699. return 0;
  700. }
  701. for (var n in dtd.$isNotEmpty) {
  702. if (node.getElementsByTagName(n).length) {
  703. return 0;
  704. }
  705. }
  706. return 1;
  707. }
  708. function mouseCoords(evt) {
  709. if (evt.pageX || evt.pageY) {
  710. return { x:evt.pageX, y:evt.pageY };
  711. }
  712. return {
  713. x:evt.clientX + me.document.body.scrollLeft - me.document.body.clientLeft,
  714. y:evt.clientY + me.document.body.scrollTop - me.document.body.clientTop
  715. };
  716. }
  717. function mouseMoveEvent(evt) {
  718. if( isEditorDisabled() ) {
  719. return;
  720. }
  721. try {
  722. //普通状态下鼠标移动
  723. var target = getParentTdOrTh(evt.target || evt.srcElement),
  724. pos;
  725. //区分用户的行为是拖动还是双击
  726. if( isInResizeBuffer ) {
  727. me.body.style.webkitUserSelect = 'none';
  728. if( Math.abs( userActionStatus.x - evt.clientX ) > offsetOfTableCell || Math.abs( userActionStatus.y - evt.clientY ) > offsetOfTableCell ) {
  729. clearTableDragTimer();
  730. isInResizeBuffer = false;
  731. singleClickState = 0;
  732. //drag action
  733. tableBorderDrag(evt);
  734. }
  735. }
  736. //修改单元格大小时的鼠标移动
  737. if (onDrag && dragTd) {
  738. singleClickState = 0;
  739. me.body.style.webkitUserSelect = 'none';
  740. me.selection.getNative()[browser.ie9below ? 'empty' : 'removeAllRanges']();
  741. pos = mouseCoords(evt);
  742. toggleDraggableState(me, true, onDrag, pos, target);
  743. if (onDrag == "h") {
  744. dragLine.style.left = getPermissionX(dragTd, evt) + "px";
  745. } else if (onDrag == "v") {
  746. dragLine.style.top = getPermissionY(dragTd, evt) + "px";
  747. }
  748. return;
  749. }
  750. //当鼠标处于table上时,修改移动过程中的光标状态
  751. if (target) {
  752. //针对使用table作为容器的组件不触发拖拽效果
  753. if (me.fireEvent('excludetable', target) === true)
  754. return;
  755. pos = mouseCoords(evt);
  756. var state = getRelation(target, pos),
  757. table = domUtils.findParentByTagName(target, "table", true);
  758. if (inTableSide(table, target, evt, true)) {
  759. if (me.fireEvent("excludetable", table) === true) return;
  760. me.body.style.cursor = "url(" + me.options.cursorpath + "h.png),pointer";
  761. } else if (inTableSide(table, target, evt)) {
  762. if (me.fireEvent("excludetable", table) === true) return;
  763. me.body.style.cursor = "url(" + me.options.cursorpath + "v.png),pointer";
  764. } else {
  765. me.body.style.cursor = "text";
  766. var curCell = target;
  767. if (/\d/.test(state)) {
  768. state = state.replace(/\d/, '');
  769. target = getUETable(target).getPreviewCell(target, state == "v");
  770. }
  771. //位于第一行的顶部或者第一列的左边时不可拖动
  772. toggleDraggableState(me, target ? !!state : false, target ? state : '', pos, target);
  773. }
  774. } else {
  775. toggleDragButton(false, table, me);
  776. }
  777. } catch (e) {
  778. showError(e);
  779. }
  780. }
  781. var dragButtonTimer;
  782. function toggleDragButton(show, table, editor) {
  783. if (!show) {
  784. if (dragOver)return;
  785. dragButtonTimer = setTimeout(function () {
  786. !dragOver && dragButton && dragButton.parentNode && dragButton.parentNode.removeChild(dragButton);
  787. }, 2000);
  788. } else {
  789. createDragButton(table, editor);
  790. }
  791. }
  792. function createDragButton(table, editor) {
  793. var pos = domUtils.getXY(table),
  794. doc = table.ownerDocument;
  795. if (dragButton && dragButton.parentNode)return dragButton;
  796. dragButton = doc.createElement("div");
  797. dragButton.contentEditable = false;
  798. dragButton.innerHTML = "";
  799. dragButton.style.cssText = "width:15px;height:15px;background-image:url(" + editor.options.UEDITOR_HOME_URL + "dialogs/table/dragicon.png);position: absolute;cursor:move;top:" + (pos.y - 15) + "px;left:" + (pos.x) + "px;";
  800. domUtils.unSelectable(dragButton);
  801. dragButton.onmouseover = function (evt) {
  802. dragOver = true;
  803. };
  804. dragButton.onmouseout = function (evt) {
  805. dragOver = false;
  806. };
  807. domUtils.on(dragButton, 'click', function (type, evt) {
  808. doClick(evt, this);
  809. });
  810. domUtils.on(dragButton, 'dblclick', function (type, evt) {
  811. doDblClick(evt);
  812. });
  813. domUtils.on(dragButton, 'dragstart', function (type, evt) {
  814. domUtils.preventDefault(evt);
  815. });
  816. var timer;
  817. function doClick(evt, button) {
  818. // 部分浏览器下需要清理
  819. clearTimeout(timer);
  820. timer = setTimeout(function () {
  821. editor.fireEvent("tableClicked", table, button);
  822. }, 300);
  823. }
  824. function doDblClick(evt) {
  825. clearTimeout(timer);
  826. var ut = getUETable(table),
  827. start = table.rows[0].cells[0],
  828. end = ut.getLastCell(),
  829. range = ut.getCellsRange(start, end);
  830. editor.selection.getRange().setStart(start, 0).setCursor(false, true);
  831. ut.setSelected(range);
  832. }
  833. doc.body.appendChild(dragButton);
  834. }
  835. // function inPosition(table, pos) {
  836. // var tablePos = domUtils.getXY(table),
  837. // width = table.offsetWidth,
  838. // height = table.offsetHeight;
  839. // if (pos.x - tablePos.x < 5 && pos.y - tablePos.y < 5) {
  840. // return "topLeft";
  841. // } else if (tablePos.x + width - pos.x < 5 && tablePos.y + height - pos.y < 5) {
  842. // return "bottomRight";
  843. // }
  844. // }
  845. function inTableSide(table, cell, evt, top) {
  846. var pos = mouseCoords(evt),
  847. state = getRelation(cell, pos);
  848. if (top) {
  849. var caption = table.getElementsByTagName("caption")[0],
  850. capHeight = caption ? caption.offsetHeight : 0;
  851. return (state == "v1") && ((pos.y - domUtils.getXY(table).y - capHeight) < 8);
  852. } else {
  853. return (state == "h1") && ((pos.x - domUtils.getXY(table).x) < 8);
  854. }
  855. }
  856. /**
  857. * 获取拖动时允许的X轴坐标
  858. * @param dragTd
  859. * @param evt
  860. */
  861. function getPermissionX(dragTd, evt) {
  862. var ut = getUETable(dragTd);
  863. if (ut) {
  864. var preTd = ut.getSameEndPosCells(dragTd, "x")[0],
  865. nextTd = ut.getSameStartPosXCells(dragTd)[0],
  866. mouseX = mouseCoords(evt).x,
  867. left = (preTd ? domUtils.getXY(preTd).x : domUtils.getXY(ut.table).x) + 20 ,
  868. right = nextTd ? domUtils.getXY(nextTd).x + nextTd.offsetWidth - 20 : (me.body.offsetWidth + 5 || parseInt(domUtils.getComputedStyle(me.body, "width"), 10));
  869. left += cellMinWidth;
  870. right -= cellMinWidth;
  871. return mouseX < left ? left : mouseX > right ? right : mouseX;
  872. }
  873. }
  874. /**
  875. * 获取拖动时允许的Y轴坐标
  876. */
  877. function getPermissionY(dragTd, evt) {
  878. try {
  879. var top = domUtils.getXY(dragTd).y,
  880. mousePosY = mouseCoords(evt).y;
  881. return mousePosY < top ? top : mousePosY;
  882. } catch (e) {
  883. showError(e);
  884. }
  885. }
  886. /**
  887. * 移动状态切换
  888. */
  889. function toggleDraggableState(editor, draggable, dir, mousePos, cell) {
  890. try {
  891. editor.body.style.cursor = dir == "h" ? "col-resize" : dir == "v" ? "row-resize" : "text";
  892. if (browser.ie) {
  893. if (dir && !mousedown && !getUETableBySelected(editor)) {
  894. getDragLine(editor, editor.document);
  895. showDragLineAt(dir, cell);
  896. } else {
  897. hideDragLine(editor)
  898. }
  899. }
  900. onBorder = draggable;
  901. } catch (e) {
  902. showError(e);
  903. }
  904. }
  905. /**
  906. * 获取与UETable相关的resize line
  907. * @param uetable UETable对象
  908. */
  909. function getResizeLineByUETable() {
  910. var lineId = '_UETableResizeLine',
  911. line = this.document.getElementById( lineId );
  912. if( !line ) {
  913. line = this.document.createElement("div");
  914. line.id = lineId;
  915. line.contnetEditable = false;
  916. line.setAttribute("unselectable", "on");
  917. var styles = {
  918. width: 2*cellBorderWidth + 1 + 'px',
  919. position: 'absolute',
  920. 'z-index': 100000,
  921. cursor: 'col-resize',
  922. background: 'red',
  923. display: 'none'
  924. };
  925. //切换状态
  926. line.onmouseout = function(){
  927. this.style.display = 'none';
  928. };
  929. utils.extend( line.style, styles );
  930. this.document.body.appendChild( line );
  931. }
  932. return line;
  933. }
  934. /**
  935. * 更新resize-line
  936. */
  937. function updateResizeLine( cell, uetable ) {
  938. var line = getResizeLineByUETable.call( this ),
  939. table = uetable.table,
  940. styles = {
  941. top: domUtils.getXY( table ).y + 'px',
  942. left: domUtils.getXY( cell).x + cell.offsetWidth - cellBorderWidth + 'px',
  943. display: 'block',
  944. height: table.offsetHeight + 'px'
  945. };
  946. utils.extend( line.style, styles );
  947. }
  948. /**
  949. * 显示resize-line
  950. */
  951. function showResizeLine( cell ) {
  952. var uetable = getUETable( cell );
  953. updateResizeLine.call( this, cell, uetable );
  954. }
  955. /**
  956. * 获取鼠标与当前单元格的相对位置
  957. * @param ele
  958. * @param mousePos
  959. */
  960. function getRelation(ele, mousePos) {
  961. var elePos = domUtils.getXY(ele);
  962. if( !elePos ) {
  963. return '';
  964. }
  965. if (elePos.x + ele.offsetWidth - mousePos.x < cellBorderWidth) {
  966. return "h";
  967. }
  968. if (mousePos.x - elePos.x < cellBorderWidth) {
  969. return 'h1'
  970. }
  971. if (elePos.y + ele.offsetHeight - mousePos.y < cellBorderWidth) {
  972. return "v";
  973. }
  974. if (mousePos.y - elePos.y < cellBorderWidth) {
  975. return 'v1'
  976. }
  977. return '';
  978. }
  979. function mouseDownEvent(type, evt) {
  980. if( isEditorDisabled() ) {
  981. return ;
  982. }
  983. userActionStatus = {
  984. x: evt.clientX,
  985. y: evt.clientY
  986. };
  987. //右键菜单单独处理
  988. if (evt.button == 2) {
  989. var ut = getUETableBySelected(me),
  990. flag = false;
  991. if (ut) {
  992. var td = getTargetTd(me, evt);
  993. utils.each(ut.selectedTds, function (ti) {
  994. if (ti === td) {
  995. flag = true;
  996. }
  997. });
  998. if (!flag) {
  999. removeSelectedClass(domUtils.getElementsByTagName(me.body, "th td"));
  1000. ut.clearSelected()
  1001. } else {
  1002. td = ut.selectedTds[0];
  1003. setTimeout(function () {
  1004. me.selection.getRange().setStart(td, 0).setCursor(false, true);
  1005. }, 0);
  1006. }
  1007. }
  1008. } else {
  1009. tableClickHander( evt );
  1010. }
  1011. }
  1012. //清除表格的计时器
  1013. function clearTableTimer() {
  1014. tabTimer && clearTimeout( tabTimer );
  1015. tabTimer = null;
  1016. }
  1017. //双击收缩
  1018. function tableDbclickHandler(evt) {
  1019. singleClickState = 0;
  1020. evt = evt || me.window.event;
  1021. var target = getParentTdOrTh(evt.target || evt.srcElement);
  1022. if (target) {
  1023. var h;
  1024. if (h = getRelation(target, mouseCoords(evt))) {
  1025. hideDragLine( me );
  1026. if (h == 'h1') {
  1027. h = 'h';
  1028. if (inTableSide(domUtils.findParentByTagName(target, "table"), target, evt)) {
  1029. me.execCommand('adaptbywindow');
  1030. } else {
  1031. target = getUETable(target).getPreviewCell(target);
  1032. if (target) {
  1033. var rng = me.selection.getRange();
  1034. rng.selectNodeContents(target).setCursor(true, true)
  1035. }
  1036. }
  1037. }
  1038. if (h == 'h') {
  1039. var ut = getUETable(target),
  1040. table = ut.table,
  1041. cells = getCellsByMoveBorder( target, table, true );
  1042. cells = extractArray( cells, 'left' );
  1043. ut.width = ut.offsetWidth;
  1044. var oldWidth = [],
  1045. newWidth = [];
  1046. utils.each( cells, function( cell ){
  1047. oldWidth.push( cell.offsetWidth );
  1048. } );
  1049. utils.each( cells, function( cell ){
  1050. cell.removeAttribute("width");
  1051. } );
  1052. window.setTimeout( function(){
  1053. //是否允许改变
  1054. var changeable = true;
  1055. utils.each( cells, function( cell, index ){
  1056. var width = cell.offsetWidth;
  1057. if( width > oldWidth[index] ) {
  1058. changeable = false;
  1059. return false;
  1060. }
  1061. newWidth.push( width );
  1062. } );
  1063. var change = changeable ? newWidth : oldWidth;
  1064. utils.each( cells, function( cell, index ){
  1065. cell.width = change[index] - getTabcellSpace();
  1066. } );
  1067. }, 0 );
  1068. // minWidth -= cellMinWidth;
  1069. //
  1070. // table.removeAttribute("width");
  1071. // utils.each(cells, function (cell) {
  1072. // cell.style.width = "";
  1073. // cell.width -= minWidth;
  1074. // });
  1075. }
  1076. }
  1077. }
  1078. }
  1079. function tableClickHander( evt ) {
  1080. removeSelectedClass(domUtils.getElementsByTagName(me.body, "td th"));
  1081. //trace:3113
  1082. //选中单元格,点击table外部,不会清掉table上挂的ueTable,会引起getUETableBySelected方法返回值
  1083. utils.each(me.document.getElementsByTagName('table'), function (t) {
  1084. t.ueTable = null;
  1085. });
  1086. startTd = getTargetTd(me, evt);
  1087. if( !startTd ) return;
  1088. var table = domUtils.findParentByTagName(startTd, "table", true);
  1089. ut = getUETable(table);
  1090. ut && ut.clearSelected();
  1091. //判断当前鼠标状态
  1092. if (!onBorder) {
  1093. me.document.body.style.webkitUserSelect = '';
  1094. mousedown = true;
  1095. me.addListener('mouseover', mouseOverEvent);
  1096. } else {
  1097. //边框上的动作处理
  1098. borderActionHandler( evt );
  1099. }
  1100. }
  1101. //处理表格边框上的动作, 这里做延时处理,避免两种动作互相影响
  1102. function borderActionHandler( evt ) {
  1103. if ( browser.ie ) {
  1104. evt = reconstruct(evt );
  1105. }
  1106. clearTableDragTimer();
  1107. //是否正在等待resize的缓冲中
  1108. isInResizeBuffer = true;
  1109. tableDragTimer = setTimeout(function(){
  1110. tableBorderDrag( evt );
  1111. }, dblclickTime);
  1112. }
  1113. function extractArray( originArr, key ) {
  1114. var result = [],
  1115. tmp = null;
  1116. for( var i = 0, len = originArr.length; i<len; i++ ) {
  1117. tmp = originArr[ i ][ key ];
  1118. if( tmp ) {
  1119. result.push( tmp );
  1120. }
  1121. }
  1122. return result;
  1123. }
  1124. function clearTableDragTimer() {
  1125. tableDragTimer && clearTimeout(tableDragTimer);
  1126. tableDragTimer = null;
  1127. }
  1128. function reconstruct( obj ) {
  1129. var attrs = ['pageX', 'pageY', 'clientX', 'clientY', 'srcElement', 'target'],
  1130. newObj = {};
  1131. if( obj ) {
  1132. for( var i = 0, key, val; key = attrs[i]; i++ ) {
  1133. val=obj[ key ];
  1134. val && (newObj[ key ] = val);
  1135. }
  1136. }
  1137. return newObj;
  1138. }
  1139. //边框拖动
  1140. function tableBorderDrag( evt ) {
  1141. isInResizeBuffer = false;
  1142. startTd = evt.target || evt.srcElement;
  1143. if( !startTd ) return;
  1144. var state = getRelation(startTd, mouseCoords(evt));
  1145. if (/\d/.test(state)) {
  1146. state = state.replace(/\d/, '');
  1147. startTd = getUETable(startTd).getPreviewCell(startTd, state == 'v');
  1148. }
  1149. hideDragLine(me);
  1150. getDragLine(me, me.document);
  1151. me.fireEvent('saveScene');
  1152. showDragLineAt(state, startTd);
  1153. mousedown = true;
  1154. //拖动开始
  1155. onDrag = state;
  1156. dragTd = startTd;
  1157. }
  1158. function mouseUpEvent(type, evt) {
  1159. if( isEditorDisabled() ) {
  1160. return ;
  1161. }
  1162. clearTableDragTimer();
  1163. isInResizeBuffer = false;
  1164. if( onBorder ) {
  1165. singleClickState = ++singleClickState % 3;
  1166. userActionStatus = {
  1167. x: evt.clientX,
  1168. y: evt.clientY
  1169. };
  1170. tableResizeTimer = setTimeout(function(){
  1171. singleClickState > 0 && singleClickState--;
  1172. }, dblclickTime );
  1173. if( singleClickState === 2 ) {
  1174. singleClickState = 0;
  1175. tableDbclickHandler(evt);
  1176. return;
  1177. }
  1178. }
  1179. if (evt.button == 2)return;
  1180. var me = this;
  1181. //清除表格上原生跨选问题
  1182. var range = me.selection.getRange(),
  1183. start = domUtils.findParentByTagName(range.startContainer, 'table', true),
  1184. end = domUtils.findParentByTagName(range.endContainer, 'table', true);
  1185. if (start || end) {
  1186. if (start === end) {
  1187. start = domUtils.findParentByTagName(range.startContainer, ['td', 'th', 'caption'], true);
  1188. end = domUtils.findParentByTagName(range.endContainer, ['td', 'th', 'caption'], true);
  1189. if (start !== end) {
  1190. me.selection.clearRange()
  1191. }
  1192. } else {
  1193. me.selection.clearRange()
  1194. }
  1195. }
  1196. mousedown = false;
  1197. me.document.body.style.webkitUserSelect = '';
  1198. //拖拽状态下的mouseUP
  1199. if ( onDrag && dragTd ) {
  1200. me.selection.getNative()[browser.ie9below ? 'empty' : 'removeAllRanges']();
  1201. singleClickState = 0;
  1202. dragLine = me.document.getElementById('ue_tableDragLine');
  1203. // trace 3973
  1204. if (dragLine) {
  1205. var dragTdPos = domUtils.getXY(dragTd),
  1206. dragLinePos = domUtils.getXY(dragLine);
  1207. switch (onDrag) {
  1208. case "h":
  1209. changeColWidth(dragTd, dragLinePos.x - dragTdPos.x);
  1210. break;
  1211. case "v":
  1212. changeRowHeight(dragTd, dragLinePos.y - dragTdPos.y - dragTd.offsetHeight);
  1213. break;
  1214. default:
  1215. }
  1216. onDrag = "";
  1217. dragTd = null;
  1218. hideDragLine(me);
  1219. me.fireEvent('saveScene');
  1220. return;
  1221. }
  1222. }
  1223. //正常状态下的mouseup
  1224. if (!startTd) {
  1225. var target = domUtils.findParentByTagName(evt.target || evt.srcElement, "td", true);
  1226. if (!target) target = domUtils.findParentByTagName(evt.target || evt.srcElement, "th", true);
  1227. if (target && (target.tagName == "TD" || target.tagName == "TH")) {
  1228. if (me.fireEvent("excludetable", target) === true) return;
  1229. range = new dom.Range(me.document);
  1230. range.setStart(target, 0).setCursor(false, true);
  1231. }
  1232. } else {
  1233. var ut = getUETable(startTd),
  1234. cell = ut ? ut.selectedTds[0] : null;
  1235. if (cell) {
  1236. range = new dom.Range(me.document);
  1237. if (domUtils.isEmptyBlock(cell)) {
  1238. range.setStart(cell, 0).setCursor(false, true);
  1239. } else {
  1240. range.selectNodeContents(cell).shrinkBoundary().setCursor(false, true);
  1241. }
  1242. } else {
  1243. range = me.selection.getRange().shrinkBoundary();
  1244. if (!range.collapsed) {
  1245. var start = domUtils.findParentByTagName(range.startContainer, ['td', 'th'], true),
  1246. end = domUtils.findParentByTagName(range.endContainer, ['td', 'th'], true);
  1247. //在table里边的不能清除
  1248. if (start && !end || !start && end || start && end && start !== end) {
  1249. range.setCursor(false, true);
  1250. }
  1251. }
  1252. }
  1253. startTd = null;
  1254. me.removeListener('mouseover', mouseOverEvent);
  1255. }
  1256. me._selectionChange(250, evt);
  1257. }
  1258. function mouseOverEvent(type, evt) {
  1259. if( isEditorDisabled() ) {
  1260. return;
  1261. }
  1262. var me = this,
  1263. tar = evt.target || evt.srcElement;
  1264. currentTd = domUtils.findParentByTagName(tar, "td", true) || domUtils.findParentByTagName(tar, "th", true);
  1265. //需要判断两个TD是否位于同一个表格内
  1266. if (startTd && currentTd &&
  1267. ((startTd.tagName == "TD" && currentTd.tagName == "TD") || (startTd.tagName == "TH" && currentTd.tagName == "TH")) &&
  1268. domUtils.findParentByTagName(startTd, 'table') == domUtils.findParentByTagName(currentTd, 'table')) {
  1269. var ut = getUETable(currentTd);
  1270. if (startTd != currentTd) {
  1271. me.document.body.style.webkitUserSelect = 'none';
  1272. me.selection.getNative()[browser.ie9below ? 'empty' : 'removeAllRanges']();
  1273. var range = ut.getCellsRange(startTd, currentTd);
  1274. ut.setSelected(range);
  1275. } else {
  1276. me.document.body.style.webkitUserSelect = '';
  1277. ut.clearSelected();
  1278. }
  1279. }
  1280. evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false);
  1281. }
  1282. function setCellHeight(cell, height, backHeight) {
  1283. var lineHight = parseInt(domUtils.getComputedStyle(cell, "line-height"), 10),
  1284. tmpHeight = backHeight + height;
  1285. height = tmpHeight < lineHight ? lineHight : tmpHeight;
  1286. if (cell.style.height) cell.style.height = "";
  1287. cell.rowSpan == 1 ? cell.setAttribute("height", height) : (cell.removeAttribute && cell.removeAttribute("height"));
  1288. }
  1289. function getWidth(cell) {
  1290. if (!cell)return 0;
  1291. return parseInt(domUtils.getComputedStyle(cell, "width"), 10);
  1292. }
  1293. function changeColWidth(cell, changeValue) {
  1294. var ut = getUETable(cell);
  1295. if (ut) {
  1296. //根据当前移动的边框获取相关的单元格
  1297. var table = ut.table,
  1298. cells = getCellsByMoveBorder( cell, table );
  1299. table.style.width = "";
  1300. table.removeAttribute("width");
  1301. //修正改变量
  1302. changeValue = correctChangeValue( changeValue, cell, cells );
  1303. if (cell.nextSibling) {
  1304. var i=0;
  1305. utils.each( cells, function( cellGroup ){
  1306. cellGroup.left.width = (+cellGroup.left.width)+changeValue;
  1307. cellGroup.right && ( cellGroup.right.width = (+cellGroup.right.width)-changeValue );
  1308. } );
  1309. } else {
  1310. utils.each( cells, function( cellGroup ){
  1311. cellGroup.left.width -= -changeValue;
  1312. } );
  1313. }
  1314. }
  1315. }
  1316. function isEditorDisabled() {
  1317. return me.body.contentEditable === "false";
  1318. }
  1319. function changeRowHeight(td, changeValue) {
  1320. if (Math.abs(changeValue) < 10) return;
  1321. var ut = getUETable(td);
  1322. if (ut) {
  1323. var cells = ut.getSameEndPosCells(td, "y"),
  1324. //备份需要连带变化的td的原始高度,否则后期无法获取正确的值
  1325. backHeight = cells[0] ? cells[0].offsetHeight : 0;
  1326. for (var i = 0, cell; cell = cells[i++];) {
  1327. setCellHeight(cell, changeValue, backHeight);
  1328. }
  1329. }
  1330. }
  1331. /**
  1332. * 获取调整单元格大小的相关单元格
  1333. * @isContainMergeCell 返回的结果中是否包含发生合并后的单元格
  1334. */
  1335. function getCellsByMoveBorder( cell, table, isContainMergeCell ) {
  1336. if( !table ) {
  1337. table = domUtils.findParentByTagName( cell, 'table' );
  1338. }
  1339. if( !table ) {
  1340. return null;
  1341. }
  1342. //获取到该单元格所在行的序列号
  1343. var index = domUtils.getNodeIndex( cell ),
  1344. temp = cell,
  1345. rows = table.rows,
  1346. colIndex = 0;
  1347. while( temp ) {
  1348. //获取到当前单元格在未发生单元格合并时的序列
  1349. if( temp.nodeType === 1 ) {
  1350. colIndex += (temp.colSpan || 1);
  1351. }
  1352. temp = temp.previousSibling;
  1353. }
  1354. temp = null;
  1355. //记录想关的单元格
  1356. var borderCells = [];
  1357. utils.each(rows, function( tabRow ){
  1358. var cells = tabRow.cells,
  1359. currIndex = 0;
  1360. utils.each( cells, function( tabCell ){
  1361. currIndex += (tabCell.colSpan || 1);
  1362. if( currIndex === colIndex ) {
  1363. borderCells.push({
  1364. left: tabCell,
  1365. right: tabCell.nextSibling || null
  1366. });
  1367. return false;
  1368. } else if( currIndex > colIndex ) {
  1369. if( isContainMergeCell ) {
  1370. borderCells.push({
  1371. left: tabCell
  1372. });
  1373. }
  1374. return false;
  1375. }
  1376. } );
  1377. });
  1378. return borderCells;
  1379. }
  1380. /**
  1381. * 通过给定的单元格集合获取最小的单元格width
  1382. */
  1383. function getMinWidthByTableCells( cells ) {
  1384. var minWidth = Number.MAX_VALUE;
  1385. for( var i = 0, curCell; curCell = cells[ i ] ; i++ ) {
  1386. minWidth = Math.min( minWidth, curCell.width || getTableCellWidth( curCell ) );
  1387. }
  1388. return minWidth;
  1389. }
  1390. function correctChangeValue( changeValue, relatedCell, cells ) {
  1391. //为单元格的paading预留空间
  1392. changeValue -= getTabcellSpace();
  1393. if( changeValue < 0 ) {
  1394. return 0;
  1395. }
  1396. changeValue -= getTableCellWidth( relatedCell );
  1397. //确定方向
  1398. var direction = changeValue < 0 ? 'left':'right';
  1399. changeValue = Math.abs(changeValue);
  1400. //只关心非最后一个单元格就可以
  1401. utils.each( cells, function( cellGroup ){
  1402. var curCell = cellGroup[direction];
  1403. //为单元格保留最小空间
  1404. if( curCell ) {
  1405. changeValue = Math.min( changeValue, getTableCellWidth( curCell )-cellMinWidth );
  1406. }
  1407. } );
  1408. //修正越界
  1409. changeValue = changeValue < 0 ? 0 : changeValue;
  1410. return direction === 'left' ? -changeValue : changeValue;
  1411. }
  1412. function getTableCellWidth( cell ) {
  1413. var width = 0,
  1414. //偏移纠正量
  1415. offset = 0,
  1416. width = cell.offsetWidth - getTabcellSpace();
  1417. //最后一个节点纠正一下
  1418. if( !cell.nextSibling ) {
  1419. width -= getTableCellOffset( cell );
  1420. }
  1421. width = width < 0 ? 0 : width;
  1422. try {
  1423. cell.width = width;
  1424. } catch(e) {
  1425. }
  1426. return width;
  1427. }
  1428. /**
  1429. * 获取单元格所在表格的最末单元格的偏移量
  1430. */
  1431. function getTableCellOffset( cell ) {
  1432. tab = domUtils.findParentByTagName( cell, "table", false);
  1433. if( tab.offsetVal === undefined ) {
  1434. var prev = cell.previousSibling;
  1435. if( prev ) {
  1436. //最后一个单元格和前一个单元格的width diff结果 如果恰好为一个border width, 则条件成立
  1437. tab.offsetVal = cell.offsetWidth - prev.offsetWidth === UT.borderWidth ? UT.borderWidth : 0;
  1438. } else {
  1439. tab.offsetVal = 0;
  1440. }
  1441. }
  1442. return tab.offsetVal;
  1443. }
  1444. function getTabcellSpace() {
  1445. if( UT.tabcellSpace === undefined ) {
  1446. var cell = null,
  1447. tab = me.document.createElement("table"),
  1448. tbody = me.document.createElement("tbody"),
  1449. trow = me.document.createElement("tr"),
  1450. tabcell = me.document.createElement("td"),
  1451. mirror = null;
  1452. tabcell.style.cssText = 'border: 0;';
  1453. tabcell.width = 1;
  1454. trow.appendChild( tabcell );
  1455. trow.appendChild( mirror = tabcell.cloneNode( false ) );
  1456. tbody.appendChild( trow );
  1457. tab.appendChild( tbody );
  1458. tab.style.cssText = "visibility: hidden;";
  1459. me.body.appendChild( tab );
  1460. UT.paddingSpace = tabcell.offsetWidth - 1;
  1461. var tmpTabWidth = tab.offsetWidth;
  1462. tabcell.style.cssText = '';
  1463. mirror.style.cssText = '';
  1464. UT.borderWidth = ( tab.offsetWidth - tmpTabWidth ) / 3;
  1465. UT.tabcellSpace = UT.paddingSpace + UT.borderWidth;
  1466. me.body.removeChild( tab );
  1467. }
  1468. getTabcellSpace = function(){ return UT.tabcellSpace; };
  1469. return UT.tabcellSpace;
  1470. }
  1471. function getDragLine(editor, doc) {
  1472. if (mousedown)return;
  1473. dragLine = editor.document.createElement("div");
  1474. domUtils.setAttributes(dragLine, {
  1475. id:"ue_tableDragLine",
  1476. unselectable:'on',
  1477. contenteditable:false,
  1478. 'onresizestart':'return false',
  1479. 'ondragstart':'return false',
  1480. 'onselectstart':'return false',
  1481. style:"background-color:blue;position:absolute;padding:0;margin:0;background-image:none;border:0px none;opacity:0;filter:alpha(opacity=0)"
  1482. });
  1483. editor.body.appendChild(dragLine);
  1484. }
  1485. function hideDragLine(editor) {
  1486. if (mousedown)return;
  1487. var line;
  1488. while (line = editor.document.getElementById('ue_tableDragLine')) {
  1489. domUtils.remove(line)
  1490. }
  1491. }
  1492. /**
  1493. * 依据state(v|h)在cell位置显示横线
  1494. * @param state
  1495. * @param cell
  1496. */
  1497. function showDragLineAt(state, cell) {
  1498. if (!cell) return;
  1499. var table = domUtils.findParentByTagName(cell, "table"),
  1500. caption = table.getElementsByTagName('caption'),
  1501. width = table.offsetWidth,
  1502. height = table.offsetHeight - (caption.length > 0 ? caption[0].offsetHeight : 0),
  1503. tablePos = domUtils.getXY(table),
  1504. cellPos = domUtils.getXY(cell), css;
  1505. switch (state) {
  1506. case "h":
  1507. css = 'height:' + height + 'px;top:' + (tablePos.y + (caption.length > 0 ? caption[0].offsetHeight : 0)) + 'px;left:' + (cellPos.x + cell.offsetWidth);
  1508. dragLine.style.cssText = css + 'px;position: absolute;display:block;background-color:blue;width:1px;border:0; color:blue;opacity:.3;filter:alpha(opacity=30)';
  1509. break;
  1510. case "v":
  1511. css = 'width:' + width + 'px;left:' + tablePos.x + 'px;top:' + (cellPos.y + cell.offsetHeight );
  1512. //必须加上border:0和color:blue,否则低版ie不支持背景色显示
  1513. dragLine.style.cssText = css + 'px;overflow:hidden;position: absolute;display:block;background-color:blue;height:1px;border:0;color:blue;opacity:.2;filter:alpha(opacity=20)';
  1514. break;
  1515. default:
  1516. }
  1517. }
  1518. /**
  1519. * 当表格边框颜色为白色时设置为虚线,true为添加虚线
  1520. * @param editor
  1521. * @param flag
  1522. */
  1523. function switchBorderColor(editor, flag) {
  1524. var tableArr = domUtils.getElementsByTagName(editor.body, "table"), color;
  1525. for (var i = 0, node; node = tableArr[i++];) {
  1526. var td = domUtils.getElementsByTagName(node, "td");
  1527. if (td[0]) {
  1528. if (flag) {
  1529. color = (td[0].style.borderColor).replace(/\s/g, "");
  1530. if (/(#ffffff)|(rgb\(255,255,255\))/ig.test(color))
  1531. domUtils.addClass(node, "noBorderTable")
  1532. } else {
  1533. domUtils.removeClasses(node, "noBorderTable")
  1534. }
  1535. }
  1536. }
  1537. }
  1538. function getTableWidth(editor, needIEHack, defaultValue) {
  1539. var body = editor.body;
  1540. return body.offsetWidth - (needIEHack ? parseInt(domUtils.getComputedStyle(body, 'margin-left'), 10) * 2 : 0) - defaultValue.tableBorder * 2 - (editor.options.offsetWidth || 0);
  1541. }
  1542. /**
  1543. * 获取当前拖动的单元格
  1544. */
  1545. function getTargetTd(editor, evt) {
  1546. var target = domUtils.findParentByTagName(evt.target || evt.srcElement, ["td", "th"], true),
  1547. dir = null;
  1548. if( !target ) {
  1549. return null;
  1550. }
  1551. dir = getRelation( target, mouseCoords( evt ) );
  1552. //如果有前一个节点, 需要做一个修正, 否则可能会得到一个错误的td
  1553. if( !target ) {
  1554. return null;
  1555. }
  1556. if( dir === 'h1' && target.previousSibling ) {
  1557. var position = domUtils.getXY( target),
  1558. cellWidth = target.offsetWidth;
  1559. if( Math.abs( position.x + cellWidth - evt.clientX ) > cellWidth / 3 ) {
  1560. target = target.previousSibling;
  1561. }
  1562. } else if( dir === 'v1' && target.parentNode.previousSibling ) {
  1563. var position = domUtils.getXY( target),
  1564. cellHeight = target.offsetHeight;
  1565. if( Math.abs( position.y + cellHeight - evt.clientY ) > cellHeight / 3 ) {
  1566. target = target.parentNode.previousSibling.firstChild;
  1567. }
  1568. }
  1569. //排除了非td内部以及用于代码高亮部分的td
  1570. return target && !(editor.fireEvent("excludetable", target) === true) ? target : null;
  1571. }
  1572. };