inital git commit
[phpns.git] / inc / js / tinymce / plugins / table / editor_plugin_src.js
blob75aaa4deca39fde0d08c9e49c63ce59eec6428f0
1 /**\r
2  * $Id: editor_plugin_src.js 201 2007-02-12 15:56:56Z spocke $\r
3  *\r
4  * @author Moxiecode\r
5  * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.\r
6  */\r
7 \r
8 /* Import plugin specific language pack */\r
9 tinyMCE.importPluginLanguagePack('table');\r
11 var TinyMCE_TablePlugin = {\r
12         getInfo : function() {\r
13                 return {\r
14                         longname : 'Tables',\r
15                         author : 'Moxiecode Systems AB',\r
16                         authorurl : 'http://tinymce.moxiecode.com',\r
17                         infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/table',\r
18                         version : tinyMCE.majorVersion + "." + tinyMCE.minorVersion\r
19                 };\r
20         },\r
22         initInstance : function(inst) {\r
23                 if (tinyMCE.isGecko) {\r
24                         var doc = inst.getDoc();\r
25                         tinyMCE.addEvent(doc, "mouseup", TinyMCE_TablePlugin._mouseDownHandler);\r
26                 }\r
28                 inst.tableRowClipboard = null;\r
29         },\r
31         /**\r
32          * Returns the HTML contents of the table control.\r
33          */\r
34         getControlHTML : function(control_name) {\r
35                 var controls = new Array(\r
36                         ['table', 'table.gif', 'lang_table_desc', 'mceInsertTable', true],\r
37                         ['delete_table', 'table_delete.gif', 'lang_table_del', 'mceTableDelete'],\r
38                         ['delete_col', 'table_delete_col.gif', 'lang_table_delete_col_desc', 'mceTableDeleteCol'],\r
39                         ['delete_row', 'table_delete_row.gif', 'lang_table_delete_row_desc', 'mceTableDeleteRow'],\r
40                         ['col_after', 'table_insert_col_after.gif', 'lang_table_col_after_desc', 'mceTableInsertColAfter'],\r
41                         ['col_before', 'table_insert_col_before.gif', 'lang_table_col_before_desc', 'mceTableInsertColBefore'],\r
42                         ['row_after', 'table_insert_row_after.gif', 'lang_table_row_after_desc', 'mceTableInsertRowAfter'],\r
43                         ['row_before', 'table_insert_row_before.gif', 'lang_table_row_before_desc', 'mceTableInsertRowBefore'],\r
44                         ['row_props', 'table_row_props.gif', 'lang_table_row_desc', 'mceTableRowProps', true],\r
45                         ['cell_props', 'table_cell_props.gif', 'lang_table_cell_desc', 'mceTableCellProps', true],\r
46                         ['split_cells', 'table_split_cells.gif', 'lang_table_split_cells_desc', 'mceTableSplitCells', true],\r
47                         ['merge_cells', 'table_merge_cells.gif', 'lang_table_merge_cells_desc', 'mceTableMergeCells', true]);\r
49                 // Render table control\r
50                 for (var i=0; i<controls.length; i++) {\r
51                         var but = controls[i];\r
52                         var cmd = 'tinyMCE.execInstanceCommand(\'{$editor_id}\',\'' + but[3] + '\', ' + (but.length > 4 ? but[4] : false) + (but.length > 5 ? ', \'' + but[5] + '\'' : '') + ');return false;';\r
54                         if (but[0] == control_name)\r
55                                 return tinyMCE.getButtonHTML(control_name, but[2], '{$pluginurl}/images/'+ but[1], but[3], (but.length > 4 ? but[4] : false));\r
56                 }\r
58                 // Special tablecontrols\r
59                 if (control_name == "tablecontrols") {\r
60                         var html = "";\r
62                         html += tinyMCE.getControlHTML("table");\r
63                         html += tinyMCE.getControlHTML("separator");\r
64                         html += tinyMCE.getControlHTML("row_props");\r
65                         html += tinyMCE.getControlHTML("cell_props");\r
66                         html += tinyMCE.getControlHTML("separator");\r
67                         html += tinyMCE.getControlHTML("row_before");\r
68                         html += tinyMCE.getControlHTML("row_after");\r
69                         html += tinyMCE.getControlHTML("delete_row");\r
70                         html += tinyMCE.getControlHTML("separator");\r
71                         html += tinyMCE.getControlHTML("col_before");\r
72                         html += tinyMCE.getControlHTML("col_after");\r
73                         html += tinyMCE.getControlHTML("delete_col");\r
74                         html += tinyMCE.getControlHTML("separator");\r
75                         html += tinyMCE.getControlHTML("split_cells");\r
76                         html += tinyMCE.getControlHTML("merge_cells");\r
78                         return html;\r
79                 }\r
81                 return "";\r
82         },\r
84         /**\r
85          * Executes the table commands.\r
86          */\r
87         execCommand : function(editor_id, element, command, user_interface, value) {\r
88                 // Is table command\r
89                 switch (command) {\r
90                         case "mceInsertTable":\r
91                         case "mceTableRowProps":\r
92                         case "mceTableCellProps":\r
93                         case "mceTableSplitCells":\r
94                         case "mceTableMergeCells":\r
95                         case "mceTableInsertRowBefore":\r
96                         case "mceTableInsertRowAfter":\r
97                         case "mceTableDeleteRow":\r
98                         case "mceTableInsertColBefore":\r
99                         case "mceTableInsertColAfter":\r
100                         case "mceTableDeleteCol":\r
101                         case "mceTableCutRow":\r
102                         case "mceTableCopyRow":\r
103                         case "mceTablePasteRowBefore":\r
104                         case "mceTablePasteRowAfter":\r
105                         case "mceTableDelete":\r
106                                 var inst = tinyMCE.getInstanceById(editor_id);\r
108                                 inst.execCommand('mceBeginUndoLevel');\r
109                                 TinyMCE_TablePlugin._doExecCommand(editor_id, element, command, user_interface, value);\r
110                                 inst.execCommand('mceEndUndoLevel');\r
112                                 return true;\r
113                 }\r
115                 // Pass to next handler in chain\r
116                 return false;\r
117         },\r
119         handleNodeChange : function(editor_id, node, undo_index, undo_levels, visual_aid, any_selection) {\r
120                 var colspan = "1", rowspan = "1", tdElm;\r
122                 var inst = tinyMCE.getInstanceById(editor_id);\r
124                 // Reset table controls\r
125                 tinyMCE.switchClass(editor_id + '_table', 'mceButtonNormal');\r
126                 tinyMCE.switchClass(editor_id + '_delete_table', 'mceButtonDisabled');\r
127                 tinyMCE.switchClass(editor_id + '_row_props', 'mceButtonDisabled');\r
128                 tinyMCE.switchClass(editor_id + '_cell_props', 'mceButtonDisabled');\r
129                 tinyMCE.switchClass(editor_id + '_row_before', 'mceButtonDisabled');\r
130                 tinyMCE.switchClass(editor_id + '_row_after', 'mceButtonDisabled');\r
131                 tinyMCE.switchClass(editor_id + '_delete_row', 'mceButtonDisabled');\r
132                 tinyMCE.switchClass(editor_id + '_col_before', 'mceButtonDisabled');\r
133                 tinyMCE.switchClass(editor_id + '_col_after', 'mceButtonDisabled');\r
134                 tinyMCE.switchClass(editor_id + '_delete_col', 'mceButtonDisabled');\r
135                 tinyMCE.switchClass(editor_id + '_split_cells', 'mceButtonDisabled');\r
136                 tinyMCE.switchClass(editor_id + '_merge_cells', 'mceButtonDisabled');\r
138                 // Within a td element\r
139                 if (tdElm = tinyMCE.getParentElement(node, "td,th")) {\r
140                         tinyMCE.switchClass(editor_id + '_cell_props', 'mceButtonSelected');\r
141                         tinyMCE.switchClass(editor_id + '_delete_table', 'mceButtonNormal');\r
142                         tinyMCE.switchClass(editor_id + '_row_before', 'mceButtonNormal');\r
143                         tinyMCE.switchClass(editor_id + '_row_after', 'mceButtonNormal');\r
144                         tinyMCE.switchClass(editor_id + '_delete_row', 'mceButtonNormal');\r
145                         tinyMCE.switchClass(editor_id + '_col_before', 'mceButtonNormal');\r
146                         tinyMCE.switchClass(editor_id + '_col_after', 'mceButtonNormal');\r
147                         tinyMCE.switchClass(editor_id + '_delete_col', 'mceButtonNormal');\r
149                         colspan = tinyMCE.getAttrib(tdElm, "colspan");\r
150                         rowspan = tinyMCE.getAttrib(tdElm, "rowspan");\r
152                         colspan = colspan == "" ? "1" : colspan;\r
153                         rowspan = rowspan == "" ? "1" : rowspan;\r
155                         if (colspan != "1" || rowspan != "1")\r
156                                 tinyMCE.switchClass(editor_id + '_split_cells', 'mceButtonNormal');\r
157                 }\r
159                 // Within a tr element\r
160                 if (tinyMCE.getParentElement(node, "tr"))\r
161                         tinyMCE.switchClass(editor_id + '_row_props', 'mceButtonSelected');\r
163                 // Within table\r
164                 if (tinyMCE.getParentElement(node, "table")) {\r
165                         tinyMCE.switchClass(editor_id + '_table', 'mceButtonSelected');\r
166                         tinyMCE.switchClass(editor_id + '_merge_cells', 'mceButtonNormal');\r
167                 }\r
168         },\r
170         // Private plugin internal methods\r
172         _mouseDownHandler : function(e) {\r
173                 var elm = tinyMCE.isMSIE ? event.srcElement : e.target;\r
174                 var focusElm = tinyMCE.selectedInstance.getFocusElement();\r
176                 // If press on special Mozilla create TD/TR thingie\r
177                 if (elm.nodeName == "BODY" && (focusElm.nodeName == "TD" || focusElm.nodeName == "TH" || (focusElm.parentNode && focusElm.parentNode.nodeName == "TD") ||(focusElm.parentNode && focusElm.parentNode.nodeName == "TH") )) {\r
178                         window.setTimeout(function() {\r
179                                 var tableElm = tinyMCE.getParentElement(focusElm, "table");\r
180                                 tinyMCE.handleVisualAid(tableElm, true, tinyMCE.settings['visual'], tinyMCE.selectedInstance);\r
181                         }, 10);\r
182                 }\r
183         },\r
185         /**\r
186          * Executes the table commands.\r
187          */\r
188         _doExecCommand : function(editor_id, element, command, user_interface, value) {\r
189                 var inst = tinyMCE.getInstanceById(editor_id);\r
190                 var focusElm = inst.getFocusElement();\r
191                 var trElm = tinyMCE.getParentElement(focusElm, "tr");\r
192                 var tdElm = tinyMCE.getParentElement(focusElm, "td,th");\r
193                 var tableElm = tinyMCE.getParentElement(focusElm, "table");\r
194                 var doc = inst.contentWindow.document;\r
195                 var tableBorder = tableElm ? tableElm.getAttribute("border") : "";\r
197                 // Get first TD if no TD found\r
198                 if (trElm && tdElm == null)\r
199                         tdElm = trElm.cells[0];\r
201                 // ------- Inner functions ---------\r
202                 function inArray(ar, v) {\r
203                         for (var i=0; i<ar.length; i++) {\r
204                                 // Is array\r
205                                 if (ar[i].length > 0 && inArray(ar[i], v))\r
206                                         return true;\r
208                                 // Found value\r
209                                 if (ar[i] == v)\r
210                                         return true;\r
211                         }\r
213                         return false;\r
214                 }\r
216                 function makeTD() {\r
217                         var newTD = doc.createElement("td");\r
218                         newTD.innerHTML = "&nbsp;";\r
219                 }\r
221                 function getColRowSpan(td) {\r
222                         var colspan = tinyMCE.getAttrib(td, "colspan");\r
223                         var rowspan = tinyMCE.getAttrib(td, "rowspan");\r
225                         colspan = colspan == "" ? 1 : parseInt(colspan);\r
226                         rowspan = rowspan == "" ? 1 : parseInt(rowspan);\r
228                         return {colspan : colspan, rowspan : rowspan};\r
229                 }\r
231                 function getCellPos(grid, td) {\r
232                         var x, y;\r
234                         for (y=0; y<grid.length; y++) {\r
235                                 for (x=0; x<grid[y].length; x++) {\r
236                                         if (grid[y][x] == td)\r
237                                                 return {cellindex : x, rowindex : y};\r
238                                 }\r
239                         }\r
241                         return null;\r
242                 }\r
244                 function getCell(grid, row, col) {\r
245                         if (grid[row] && grid[row][col])\r
246                                 return grid[row][col];\r
248                         return null;\r
249                 }\r
251                 function getTableGrid(table) {\r
252                         var grid = new Array(), rows = table.rows, x, y, td, sd, xstart, x2, y2;\r
254                         for (y=0; y<rows.length; y++) {\r
255                                 for (x=0; x<rows[y].cells.length; x++) {\r
256                                         td = rows[y].cells[x];\r
257                                         sd = getColRowSpan(td);\r
259                                         // All ready filled\r
260                                         for (xstart = x; grid[y] && grid[y][xstart]; xstart++) ;\r
262                                         // Fill box\r
263                                         for (y2=y; y2<y+sd['rowspan']; y2++) {\r
264                                                 if (!grid[y2])\r
265                                                         grid[y2] = new Array();\r
267                                                 for (x2=xstart; x2<xstart+sd['colspan']; x2++)\r
268                                                         grid[y2][x2] = td;\r
269                                         }\r
270                                 }\r
271                         }\r
273                         return grid;\r
274                 }\r
276                 function trimRow(table, tr, td, new_tr) {\r
277                         var grid = getTableGrid(table), cpos = getCellPos(grid, td);\r
278                         var cells, lastElm;\r
280                         // Time to crop away some\r
281                         if (new_tr.cells.length != tr.childNodes.length) {\r
282                                 cells = tr.childNodes;\r
283                                 lastElm = null;\r
285                                 for (var x=0; td = getCell(grid, cpos.rowindex, x); x++) {\r
286                                         var remove = true;\r
287                                         var sd = getColRowSpan(td);\r
289                                         // Remove due to rowspan\r
290                                         if (inArray(cells, td)) {\r
291                                                 new_tr.childNodes[x]._delete = true;\r
292                                         } else if ((lastElm == null || td != lastElm) && sd.colspan > 1) { // Remove due to colspan\r
293                                                 for (var i=x; i<x+td.colSpan; i++)\r
294                                                         new_tr.childNodes[i]._delete = true;\r
295                                         }\r
297                                         if ((lastElm == null || td != lastElm) && sd.rowspan > 1)\r
298                                                 td.rowSpan = sd.rowspan + 1;\r
300                                         lastElm = td;\r
301                                 }\r
303                                 deleteMarked(tableElm);\r
304                         }\r
305                 }\r
307                 function prevElm(node, name) {\r
308                         while ((node = node.previousSibling) != null) {\r
309                                 if (node.nodeName == name)\r
310                                         return node;\r
311                         }\r
313                         return null;\r
314                 }\r
316                 function nextElm(node, names) {\r
317                         var namesAr = names.split(',');\r
319                         while ((node = node.nextSibling) != null) {\r
320                                 for (var i=0; i<namesAr.length; i++) {\r
321                                         if (node.nodeName.toLowerCase() == namesAr[i].toLowerCase() )\r
322                                                 return node;\r
323                                 }\r
324                         }\r
326                         return null;\r
327                 }\r
329                 function deleteMarked(tbl) {\r
330                         if (tbl.rows == 0)\r
331                                 return;\r
333                         var tr = tbl.rows[0];\r
334                         do {\r
335                                 var next = nextElm(tr, "TR");\r
337                                 // Delete row\r
338                                 if (tr._delete) {\r
339                                         tr.parentNode.removeChild(tr);\r
340                                         continue;\r
341                                 }\r
343                                 // Delete cells\r
344                                 var td = tr.cells[0];\r
345                                 if (td.cells > 1) {\r
346                                         do {\r
347                                                 var nexttd = nextElm(td, "TD,TH");\r
349                                                 if (td._delete)\r
350                                                         td.parentNode.removeChild(td);\r
351                                         } while ((td = nexttd) != null);\r
352                                 }\r
353                         } while ((tr = next) != null);\r
354                 }\r
356                 function addRows(td_elm, tr_elm, rowspan) {\r
357                         // Add rows\r
358                         td_elm.rowSpan = 1;\r
359                         var trNext = nextElm(tr_elm, "TR");\r
360                         for (var i=1; i<rowspan && trNext; i++) {\r
361                                 var newTD = doc.createElement("td");\r
362                                 newTD.innerHTML = "&nbsp;";\r
364                                 if (tinyMCE.isMSIE)\r
365                                         trNext.insertBefore(newTD, trNext.cells(td_elm.cellIndex));\r
366                                 else\r
367                                         trNext.insertBefore(newTD, trNext.cells[td_elm.cellIndex]);\r
369                                 trNext = nextElm(trNext, "TR");\r
370                         }\r
371                 }\r
373                 function copyRow(doc, table, tr) {\r
374                         var grid = getTableGrid(table);\r
375                         var newTR = tr.cloneNode(false);\r
376                         var cpos = getCellPos(grid, tr.cells[0]);\r
377                         var lastCell = null;\r
378                         var tableBorder = tinyMCE.getAttrib(table, "border");\r
379                         var tdElm = null;\r
381                         for (var x=0; tdElm = getCell(grid, cpos.rowindex, x); x++) {\r
382                                 var newTD = null;\r
384                                 if (lastCell != tdElm) {\r
385                                         for (var i=0; i<tr.cells.length; i++) {\r
386                                                 if (tdElm == tr.cells[i]) {\r
387                                                         newTD = tdElm.cloneNode(true);\r
388                                                         break;\r
389                                                 }\r
390                                         }\r
391                                 }\r
393                                 if (newTD == null) {\r
394                                         newTD = doc.createElement("td");\r
395                                         newTD.innerHTML = "&nbsp;";\r
396                                 }\r
398                                 // Reset col/row span\r
399                                 newTD.colSpan = 1;\r
400                                 newTD.rowSpan = 1;\r
402                                 newTR.appendChild(newTD);\r
404                                 lastCell = tdElm;\r
405                         }\r
407                         return newTR;\r
408                 }\r
410                 // ---- Commands -----\r
412                 // Handle commands\r
413                 switch (command) {\r
414                         case "mceTableRowProps":\r
415                                 if (trElm == null)\r
416                                         return true;\r
418                                 if (user_interface) {\r
419                                         // Setup template\r
420                                         var template = new Array();\r
422                                         template['file'] = '../../plugins/table/row.htm';\r
423                                         template['width'] = 380;\r
424                                         template['height'] = 295;\r
426                                         // Language specific width and height addons\r
427                                         template['width'] += tinyMCE.getLang('lang_table_rowprops_delta_width', 0);\r
428                                         template['height'] += tinyMCE.getLang('lang_table_rowprops_delta_height', 0);\r
430                                         // Open window\r
431                                         tinyMCE.openWindow(template, {editor_id : inst.editorId, inline : "yes"});\r
432                                 }\r
434                                 return true;\r
436                         case "mceTableCellProps":\r
437                                 if (tdElm == null)\r
438                                         return true;\r
440                                 if (user_interface) {\r
441                                         // Setup template\r
442                                         var template = new Array();\r
444                                         template['file'] = '../../plugins/table/cell.htm';\r
445                                         template['width'] = 380;\r
446                                         template['height'] = 295;\r
448                                         // Language specific width and height addons\r
449                                         template['width'] += tinyMCE.getLang('lang_table_cellprops_delta_width', 0);\r
450                                         template['height'] += tinyMCE.getLang('lang_table_cellprops_delta_height', 0);\r
452                                         // Open window\r
453                                         tinyMCE.openWindow(template, {editor_id : inst.editorId, inline : "yes"});\r
454                                 }\r
456                                 return true;\r
458                         case "mceInsertTable":\r
459                                 if (user_interface) {\r
460                                         // Setup template\r
461                                         var template = new Array();\r
463                                         template['file'] = '../../plugins/table/table.htm';\r
464                                         template['width'] = 380;\r
465                                         template['height'] = 295;\r
467                                         // Language specific width and height addons\r
468                                         template['width'] += tinyMCE.getLang('lang_table_table_delta_width', 0);\r
469                                         template['height'] += tinyMCE.getLang('lang_table_table_delta_height', 0);\r
471                                         // Open window\r
472                                         tinyMCE.openWindow(template, {editor_id : inst.editorId, inline : "yes", action : value});\r
473                                 }\r
475                                 return true;\r
477                         case "mceTableDelete":\r
478                                 var table = tinyMCE.getParentElement(inst.getFocusElement(), "table");\r
479                                 if (table) {\r
480                                         table.parentNode.removeChild(table);\r
481                                         inst.repaint();\r
482                                 }\r
483                                 return true;\r
485                         case "mceTableSplitCells":\r
486                         case "mceTableMergeCells":\r
487                         case "mceTableInsertRowBefore":\r
488                         case "mceTableInsertRowAfter":\r
489                         case "mceTableDeleteRow":\r
490                         case "mceTableInsertColBefore":\r
491                         case "mceTableInsertColAfter":\r
492                         case "mceTableDeleteCol":\r
493                         case "mceTableCutRow":\r
494                         case "mceTableCopyRow":\r
495                         case "mceTablePasteRowBefore":\r
496                         case "mceTablePasteRowAfter":\r
497                                 // No table just return (invalid command)\r
498                                 if (!tableElm)\r
499                                         return true;\r
501                                 // Table has a tbody use that reference\r
502                                 // Changed logic by ApTest 2005.07.12 (www.aptest.com)\r
503                                 // Now lookk at the focused element and take its parentNode.  That will be a tbody or a table.\r
504                                 if (trElm && tableElm != trElm.parentNode)\r
505                                         tableElm = trElm.parentNode;\r
507                                 if (tableElm && trElm) {\r
508                                         switch (command) {\r
509                                                 case "mceTableCutRow":\r
510                                                         if (!trElm || !tdElm)\r
511                                                                 return true;\r
513                                                         inst.tableRowClipboard = copyRow(doc, tableElm, trElm);\r
514                                                         inst.execCommand("mceTableDeleteRow");\r
515                                                         break;\r
517                                                 case "mceTableCopyRow":\r
518                                                         if (!trElm || !tdElm)\r
519                                                                 return true;\r
521                                                         inst.tableRowClipboard = copyRow(doc, tableElm, trElm);\r
522                                                         break;\r
524                                                 case "mceTablePasteRowBefore":\r
525                                                         if (!trElm || !tdElm)\r
526                                                                 return true;\r
528                                                         var newTR = inst.tableRowClipboard.cloneNode(true);\r
530                                                         var prevTR = prevElm(trElm, "TR");\r
531                                                         if (prevTR != null)\r
532                                                                 trimRow(tableElm, prevTR, prevTR.cells[0], newTR);\r
534                                                         trElm.parentNode.insertBefore(newTR, trElm);\r
535                                                         break;\r
537                                                 case "mceTablePasteRowAfter":\r
538                                                         if (!trElm || !tdElm)\r
539                                                                 return true;\r
540                                                         \r
541                                                         var nextTR = nextElm(trElm, "TR");\r
542                                                         var newTR = inst.tableRowClipboard.cloneNode(true);\r
544                                                         trimRow(tableElm, trElm, tdElm, newTR);\r
546                                                         if (nextTR == null)\r
547                                                                 trElm.parentNode.appendChild(newTR);\r
548                                                         else\r
549                                                                 nextTR.parentNode.insertBefore(newTR, nextTR);\r
551                                                         break;\r
553                                                 case "mceTableInsertRowBefore":\r
554                                                         if (!trElm || !tdElm)\r
555                                                                 return true;\r
557                                                         var grid = getTableGrid(tableElm);\r
558                                                         var cpos = getCellPos(grid, tdElm);\r
559                                                         var newTR = doc.createElement("tr");\r
560                                                         var lastTDElm = null;\r
562                                                         cpos.rowindex--;\r
563                                                         if (cpos.rowindex < 0)\r
564                                                                 cpos.rowindex = 0;\r
566                                                         // Create cells\r
567                                                         for (var x=0; tdElm = getCell(grid, cpos.rowindex, x); x++) {\r
568                                                                 if (tdElm != lastTDElm) {\r
569                                                                         var sd = getColRowSpan(tdElm);\r
571                                                                         if (sd['rowspan'] == 1) {\r
572                                                                                 var newTD = doc.createElement("td");\r
574                                                                                 newTD.innerHTML = "&nbsp;";\r
575                                                                                 newTD.colSpan = tdElm.colSpan;\r
577                                                                                 newTR.appendChild(newTD);\r
578                                                                         } else\r
579                                                                                 tdElm.rowSpan = sd['rowspan'] + 1;\r
581                                                                         lastTDElm = tdElm;\r
582                                                                 }\r
583                                                         }\r
585                                                         trElm.parentNode.insertBefore(newTR, trElm);\r
587                                                         grid = getTableGrid(tableElm);\r
588                                                         inst.selection.selectNode(getCell(grid, cpos.rowindex + 1, cpos.cellindex), tinyMCE.isGecko, true); // Only collape on gecko\r
589                                                 break;\r
591                                                 case "mceTableInsertRowAfter":\r
592                                                         if (!trElm || !tdElm)\r
593                                                                 return true;\r
595                                                         var grid = getTableGrid(tableElm);\r
596                                                         var cpos = getCellPos(grid, tdElm);\r
597                                                         var newTR = doc.createElement("tr");\r
598                                                         var lastTDElm = null;\r
600                                                         // Create cells\r
601                                                         for (var x=0; tdElm = getCell(grid, cpos.rowindex, x); x++) {\r
602                                                                 if (tdElm != lastTDElm) {\r
603                                                                         var sd = getColRowSpan(tdElm);\r
605                                                                         if (sd['rowspan'] == 1) {\r
606                                                                                 var newTD = doc.createElement("td");\r
608                                                                                 newTD.innerHTML = "&nbsp;";\r
609                                                                                 newTD.colSpan = tdElm.colSpan;\r
611                                                                                 newTR.appendChild(newTD);\r
612                                                                         } else\r
613                                                                                 tdElm.rowSpan = sd['rowspan'] + 1;\r
615                                                                         lastTDElm = tdElm;\r
616                                                                 }\r
617                                                         }\r
619                                                         if (newTR.hasChildNodes()) {\r
620                                                                 var nextTR = nextElm(trElm, "TR");\r
621                                                                 if (nextTR)\r
622                                                                         nextTR.parentNode.insertBefore(newTR, nextTR);\r
623                                                                 else\r
624                                                                         tableElm.appendChild(newTR);\r
625                                                         }\r
627                                                         grid = getTableGrid(tableElm);\r
628                                                         inst.selection.selectNode(getCell(grid, cpos.rowindex, cpos.cellindex), tinyMCE.isGecko, true); // Only collape on gecko\r
629                                                 break;\r
631                                                 case "mceTableDeleteRow":\r
632                                                         if (!trElm || !tdElm)\r
633                                                                 return true;\r
635                                                         var grid = getTableGrid(tableElm);\r
636                                                         var cpos = getCellPos(grid, tdElm);\r
638                                                         // Only one row, remove whole table\r
639                                                         if (grid.length == 1) {\r
640                                                                 tableElm = tinyMCE.getParentElement(tableElm, "table"); // Look for table instead of tbody\r
641                                                                 tableElm.parentNode.removeChild(tableElm);\r
642                                                                 return true;\r
643                                                         }\r
645                                                         // Move down row spanned cells\r
646                                                         var cells = trElm.cells;\r
647                                                         var nextTR = nextElm(trElm, "TR");\r
648                                                         for (var x=0; x<cells.length; x++) {\r
649                                                                 if (cells[x].rowSpan > 1) {\r
650                                                                         var newTD = cells[x].cloneNode(true);\r
651                                                                         var sd = getColRowSpan(cells[x]);\r
653                                                                         newTD.rowSpan = sd.rowspan - 1;\r
655                                                                         var nextTD = nextTR.cells[x];\r
657                                                                         if (nextTD == null)\r
658                                                                                 nextTR.appendChild(newTD);\r
659                                                                         else\r
660                                                                                 nextTR.insertBefore(newTD, nextTD);\r
661                                                                 }\r
662                                                         }\r
664                                                         // Delete cells\r
665                                                         var lastTDElm = null;\r
666                                                         for (var x=0; tdElm = getCell(grid, cpos.rowindex, x); x++) {\r
667                                                                 if (tdElm != lastTDElm) {\r
668                                                                         var sd = getColRowSpan(tdElm);\r
670                                                                         if (sd.rowspan > 1) {\r
671                                                                                 tdElm.rowSpan = sd.rowspan - 1;\r
672                                                                         } else {\r
673                                                                                 trElm = tdElm.parentNode;\r
675                                                                                 if (trElm.parentNode)\r
676                                                                                         trElm._delete = true;\r
677                                                                         }\r
679                                                                         lastTDElm = tdElm;\r
680                                                                 }\r
681                                                         }\r
683                                                         deleteMarked(tableElm);\r
685                                                         cpos.rowindex--;\r
686                                                         if (cpos.rowindex < 0)\r
687                                                                 cpos.rowindex = 0;\r
689                                                         // Recalculate grid and select\r
690                                                         grid = getTableGrid(tableElm);\r
691                                                         inst.selection.selectNode(getCell(grid, cpos.rowindex, 0), tinyMCE.isGecko, true); // Only collape on gecko\r
692                                                 break;\r
694                                                 case "mceTableInsertColBefore":\r
695                                                         if (!trElm || !tdElm)\r
696                                                                 return true;\r
698                                                         var grid = getTableGrid(tableElm);\r
699                                                         var cpos = getCellPos(grid, tdElm);\r
700                                                         var lastTDElm = null;\r
702                                                         for (var y=0; tdElm = getCell(grid, y, cpos.cellindex); y++) {\r
703                                                                 if (tdElm != lastTDElm) {\r
704                                                                         var sd = getColRowSpan(tdElm);\r
706                                                                         if (sd['colspan'] == 1) {\r
707                                                                                 var newTD = doc.createElement(tdElm.nodeName);\r
709                                                                                 newTD.innerHTML = "&nbsp;";\r
710                                                                                 newTD.rowSpan = tdElm.rowSpan;\r
712                                                                                 tdElm.parentNode.insertBefore(newTD, tdElm);\r
713                                                                         } else\r
714                                                                                 tdElm.colSpan++;\r
716                                                                         lastTDElm = tdElm;\r
717                                                                 }\r
718                                                         }\r
720                                                         grid = getTableGrid(tableElm);\r
721                                                         inst.selection.selectNode(getCell(grid, cpos.rowindex, cpos.cellindex + 1), tinyMCE.isGecko, true); // Only collape on gecko\r
722                                                 break;\r
724                                                 case "mceTableInsertColAfter":\r
725                                                         if (!trElm || !tdElm)\r
726                                                                 return true;\r
728                                                         var grid = getTableGrid(tableElm);\r
729                                                         var cpos = getCellPos(grid, tdElm);\r
730                                                         var lastTDElm = null;\r
732                                                         for (var y=0; tdElm = getCell(grid, y, cpos.cellindex); y++) {\r
733                                                                 if (tdElm != lastTDElm) {\r
734                                                                         var sd = getColRowSpan(tdElm);\r
736                                                                         if (sd['colspan'] == 1) {\r
737                                                                                 var newTD = doc.createElement(tdElm.nodeName);\r
739                                                                                 newTD.innerHTML = "&nbsp;";\r
740                                                                                 newTD.rowSpan = tdElm.rowSpan;\r
742                                                                                 var nextTD = nextElm(tdElm, "TD,TH");\r
743                                                                                 if (nextTD == null)\r
744                                                                                         tdElm.parentNode.appendChild(newTD);\r
745                                                                                 else\r
746                                                                                         nextTD.parentNode.insertBefore(newTD, nextTD);\r
747                                                                         } else\r
748                                                                                 tdElm.colSpan++;\r
750                                                                         lastTDElm = tdElm;\r
751                                                                 }\r
752                                                         }\r
754                                                         grid = getTableGrid(tableElm);\r
755                                                         inst.selection.selectNode(getCell(grid, cpos.rowindex, cpos.cellindex), tinyMCE.isGecko, true); // Only collape on gecko\r
756                                                 break;\r
758                                                 case "mceTableDeleteCol":\r
759                                                         if (!trElm || !tdElm)\r
760                                                                 return true;\r
762                                                         var grid = getTableGrid(tableElm);\r
763                                                         var cpos = getCellPos(grid, tdElm);\r
764                                                         var lastTDElm = null;\r
766                                                         // Only one col, remove whole table\r
767                                                         if (grid.length > 1 && grid[0].length <= 1) {\r
768                                                                 tableElm = tinyMCE.getParentElement(tableElm, "table"); // Look for table instead of tbody\r
769                                                                 tableElm.parentNode.removeChild(tableElm);\r
770                                                                 return true;\r
771                                                         }\r
773                                                         // Delete cells\r
774                                                         for (var y=0; tdElm = getCell(grid, y, cpos.cellindex); y++) {\r
775                                                                 if (tdElm != lastTDElm) {\r
776                                                                         var sd = getColRowSpan(tdElm);\r
778                                                                         if (sd['colspan'] > 1)\r
779                                                                                 tdElm.colSpan = sd['colspan'] - 1;\r
780                                                                         else {\r
781                                                                                 if (tdElm.parentNode)\r
782                                                                                         tdElm.parentNode.removeChild(tdElm);\r
783                                                                         }\r
785                                                                         lastTDElm = tdElm;\r
786                                                                 }\r
787                                                         }\r
789                                                         cpos.cellindex--;\r
790                                                         if (cpos.cellindex < 0)\r
791                                                                 cpos.cellindex = 0;\r
793                                                         // Recalculate grid and select\r
794                                                         grid = getTableGrid(tableElm);\r
795                                                         inst.selection.selectNode(getCell(grid, cpos.rowindex, 0), tinyMCE.isGecko, true); // Only collape on gecko\r
796                                                 break;\r
798                                         case "mceTableSplitCells":\r
799                                                 if (!trElm || !tdElm)\r
800                                                         return true;\r
802                                                 var spandata = getColRowSpan(tdElm);\r
804                                                 var colspan = spandata["colspan"];\r
805                                                 var rowspan = spandata["rowspan"];\r
807                                                 // Needs splitting\r
808                                                 if (colspan > 1 || rowspan > 1) {\r
809                                                         // Generate cols\r
810                                                         tdElm.colSpan = 1;\r
811                                                         for (var i=1; i<colspan; i++) {\r
812                                                                 var newTD = doc.createElement("td");\r
814                                                                 newTD.innerHTML = "&nbsp;";\r
816                                                                 trElm.insertBefore(newTD, nextElm(tdElm, "TD,TH"));\r
818                                                                 if (rowspan > 1)\r
819                                                                         addRows(newTD, trElm, rowspan);\r
820                                                         }\r
822                                                         addRows(tdElm, trElm, rowspan);\r
823                                                 }\r
825                                                 // Apply visual aids\r
826                                                 tableElm = tinyMCE.getParentElement(inst.getFocusElement(), "table");\r
827                                                 break;\r
829                                         case "mceTableMergeCells":\r
830                                                 var rows = new Array();\r
831                                                 var sel = inst.getSel();\r
832                                                 var grid = getTableGrid(tableElm);\r
834                                                 if (tinyMCE.isMSIE || sel.rangeCount == 1) {\r
835                                                         if (user_interface) {\r
836                                                                 // Setup template\r
837                                                                 var template = new Array();\r
838                                                                 var sp = getColRowSpan(tdElm);\r
840                                                                 template['file'] = '../../plugins/table/merge_cells.htm';\r
841                                                                 template['width'] = 250;\r
842                                                                 template['height'] = 105 + (tinyMCE.isNS7 ? 25 : 0);\r
844                                                                 // Language specific width and height addons\r
845                                                                 template['width'] += tinyMCE.getLang('lang_table_merge_cells_delta_width', 0);\r
846                                                                 template['height'] += tinyMCE.getLang('lang_table_merge_cells_delta_height', 0);\r
848                                                                 // Open window\r
849                                                                 tinyMCE.openWindow(template, {editor_id : inst.editorId, inline : "yes", action : "update", numcols : sp.colspan, numrows : sp.rowspan});\r
851                                                                 return true;\r
852                                                         } else {\r
853                                                                 var numRows = parseInt(value['numrows']);\r
854                                                                 var numCols = parseInt(value['numcols']);\r
855                                                                 var cpos = getCellPos(grid, tdElm);\r
857                                                                 if (("" + numRows) == "NaN")\r
858                                                                         numRows = 1;\r
860                                                                 if (("" + numCols) == "NaN")\r
861                                                                         numCols = 1;\r
863                                                                 // Get rows and cells\r
864                                                                 var tRows = tableElm.rows;\r
865                                                                 for (var y=cpos.rowindex; y<grid.length; y++) {\r
866                                                                         var rowCells = new Array();\r
868                                                                         for (var x=cpos.cellindex; x<grid[y].length; x++) {\r
869                                                                                 var td = getCell(grid, y, x);\r
871                                                                                 if (td && !inArray(rows, td) && !inArray(rowCells, td)) {\r
872                                                                                         var cp = getCellPos(grid, td);\r
874                                                                                         // Within range\r
875                                                                                         if (cp.cellindex < cpos.cellindex+numCols && cp.rowindex < cpos.rowindex+numRows)\r
876                                                                                                 rowCells[rowCells.length] = td;\r
877                                                                                 }\r
878                                                                         }\r
880                                                                         if (rowCells.length > 0)\r
881                                                                                 rows[rows.length] = rowCells;\r
882                                                                 }\r
884                                                                 //return true;\r
885                                                         }\r
886                                                 } else {\r
887                                                         var cells = new Array();\r
888                                                         var sel = inst.getSel();\r
889                                                         var lastTR = null;\r
890                                                         var curRow = null;\r
891                                                         var x1 = -1, y1 = -1, x2, y2;\r
893                                                         // Only one cell selected, whats the point?\r
894                                                         if (sel.rangeCount < 2)\r
895                                                                 return true;\r
897                                                         // Get all selected cells\r
898                                                         for (var i=0; i<sel.rangeCount; i++) {\r
899                                                                 var rng = sel.getRangeAt(i);\r
900                                                                 var tdElm = rng.startContainer.childNodes[rng.startOffset];\r
902                                                                 if (!tdElm)\r
903                                                                         break;\r
905                                                                 if (tdElm.nodeName == "TD")\r
906                                                                         cells[cells.length] = tdElm;\r
907                                                         }\r
909                                                         // Get rows and cells\r
910                                                         var tRows = tableElm.rows;\r
911                                                         for (var y=0; y<tRows.length; y++) {\r
912                                                                 var rowCells = new Array();\r
914                                                                 for (var x=0; x<tRows[y].cells.length; x++) {\r
915                                                                         var td = tRows[y].cells[x];\r
917                                                                         for (var i=0; i<cells.length; i++) {\r
918                                                                                 if (td == cells[i]) {\r
919                                                                                         rowCells[rowCells.length] = td;\r
920                                                                                 }\r
921                                                                         }\r
922                                                                 }\r
924                                                                 if (rowCells.length > 0)\r
925                                                                         rows[rows.length] = rowCells;\r
926                                                         }\r
928                                                         // Find selected cells in grid and box\r
929                                                         var curRow = new Array();\r
930                                                         var lastTR = null;\r
931                                                         for (var y=0; y<grid.length; y++) {\r
932                                                                 for (var x=0; x<grid[y].length; x++) {\r
933                                                                         grid[y][x]._selected = false;\r
935                                                                         for (var i=0; i<cells.length; i++) {\r
936                                                                                 if (grid[y][x] == cells[i]) {\r
937                                                                                         // Get start pos\r
938                                                                                         if (x1 == -1) {\r
939                                                                                                 x1 = x;\r
940                                                                                                 y1 = y;\r
941                                                                                         }\r
943                                                                                         // Get end pos\r
944                                                                                         x2 = x;\r
945                                                                                         y2 = y;\r
947                                                                                         grid[y][x]._selected = true;\r
948                                                                                 }\r
949                                                                         }\r
950                                                                 }\r
951                                                         }\r
953                                                         // Is there gaps, if so deny\r
954                                                         for (var y=y1; y<=y2; y++) {\r
955                                                                 for (var x=x1; x<=x2; x++) {\r
956                                                                         if (!grid[y][x]._selected) {\r
957                                                                                 alert("Invalid selection for merge.");\r
958                                                                                 return true;\r
959                                                                         }\r
960                                                                 }\r
961                                                         }\r
962                                                 }\r
964                                                 // Validate selection and get total rowspan and colspan\r
965                                                 var rowSpan = 1, colSpan = 1;\r
967                                                 // Validate horizontal and get total colspan\r
968                                                 var lastRowSpan = -1;\r
969                                                 for (var y=0; y<rows.length; y++) {\r
970                                                         var rowColSpan = 0;\r
972                                                         for (var x=0; x<rows[y].length; x++) {\r
973                                                                 var sd = getColRowSpan(rows[y][x]);\r
975                                                                 rowColSpan += sd['colspan'];\r
977                                                                 if (lastRowSpan != -1 && sd['rowspan'] != lastRowSpan) {\r
978                                                                         alert("Invalid selection for merge.");\r
979                                                                         return true;\r
980                                                                 }\r
982                                                                 lastRowSpan = sd['rowspan'];\r
983                                                         }\r
985                                                         if (rowColSpan > colSpan)\r
986                                                                 colSpan = rowColSpan;\r
988                                                         lastRowSpan = -1;\r
989                                                 }\r
991                                                 // Validate vertical and get total rowspan\r
992                                                 var lastColSpan = -1;\r
993                                                 for (var x=0; x<rows[0].length; x++) {\r
994                                                         var colRowSpan = 0;\r
996                                                         for (var y=0; y<rows.length; y++) {\r
997                                                                 var sd = getColRowSpan(rows[y][x]);\r
999                                                                 colRowSpan += sd['rowspan'];\r
1001                                                                 if (lastColSpan != -1 && sd['colspan'] != lastColSpan) {\r
1002                                                                         alert("Invalid selection for merge.");\r
1003                                                                         return true;\r
1004                                                                 }\r
1006                                                                 lastColSpan = sd['colspan'];\r
1007                                                         }\r
1009                                                         if (colRowSpan > rowSpan)\r
1010                                                                 rowSpan = colRowSpan;\r
1012                                                         lastColSpan = -1;\r
1013                                                 }\r
1015                                                 // Setup td\r
1016                                                 tdElm = rows[0][0];\r
1017                                                 tdElm.rowSpan = rowSpan;\r
1018                                                 tdElm.colSpan = colSpan;\r
1020                                                 // Merge cells\r
1021                                                 for (var y=0; y<rows.length; y++) {\r
1022                                                         for (var x=0; x<rows[y].length; x++) {\r
1023                                                                 var html = rows[y][x].innerHTML;\r
1024                                                                 var chk = tinyMCE.regexpReplace(html, "[ \t\r\n]", "");\r
1026                                                                 if (chk != "<br/>" && chk != "<br>" && chk != "&nbsp;" && (x+y > 0))\r
1027                                                                         tdElm.innerHTML += html;\r
1029                                                                 // Not current cell\r
1030                                                                 if (rows[y][x] != tdElm && !rows[y][x]._deleted) {\r
1031                                                                         var cpos = getCellPos(grid, rows[y][x]);\r
1032                                                                         var tr = rows[y][x].parentNode;\r
1034                                                                         tr.removeChild(rows[y][x]);\r
1035                                                                         rows[y][x]._deleted = true;\r
1037                                                                         // Empty TR, remove it\r
1038                                                                         if (!tr.hasChildNodes()) {\r
1039                                                                                 tr.parentNode.removeChild(tr);\r
1041                                                                                 var lastCell = null;\r
1042                                                                                 for (var x=0; cellElm = getCell(grid, cpos.rowindex, x); x++) {\r
1043                                                                                         if (cellElm != lastCell && cellElm.rowSpan > 1)\r
1044                                                                                                 cellElm.rowSpan--;\r
1046                                                                                         lastCell = cellElm;\r
1047                                                                                 }\r
1049                                                                                 if (tdElm.rowSpan > 1)\r
1050                                                                                         tdElm.rowSpan--;\r
1051                                                                         }\r
1052                                                                 }\r
1053                                                         }\r
1054                                                 }\r
1056                                                 break;\r
1057                                         }\r
1059                                         tableElm = tinyMCE.getParentElement(inst.getFocusElement(), "table");\r
1060                                         tinyMCE.handleVisualAid(tableElm, true, tinyMCE.settings['visual'], tinyMCE.selectedInstance);\r
1061                                         tinyMCE.triggerNodeChange();\r
1062                                         inst.repaint();\r
1063                                 }\r
1065                         return true;\r
1066                 }\r
1068                 // Pass to next handler in chain\r
1069                 return false;\r
1070         }\r
1071 };\r
1073 tinyMCE.addPlugin("table", TinyMCE_TablePlugin);\r