re-added binary
[citadel.git] / webcit / tiny_mce / plugins / table / editor_plugin_src.js
1 /* Import plugin specific language pack */\r
2 tinyMCE.importPluginLanguagePack('table', 'en,ar,cs,da,de,el,es,fi,fr_ca,hu,it,ja,ko,nl,no,pl,pt,sv,tw,zh_cn,fr,de,he,no');\r
3 \r
4 function TinyMCE_table_getInfo() {\r
5         return {\r
6                 longname : 'Tables',\r
7                 author : 'Moxiecode Systems',\r
8                 authorurl : 'http://tinymce.moxiecode.com',\r
9                 infourl : 'http://tinymce.moxiecode.com/tinymce/docs/plugin_table.html',\r
10                 version : tinyMCE.majorVersion + "." + tinyMCE.minorVersion\r
11         };\r
12 };\r
13 \r
14 function TinyMCE_table_initInstance(inst) {\r
15         if (tinyMCE.isGecko) {\r
16                 var doc = inst.getDoc();\r
17 \r
18                 tinyMCE.addEvent(doc, "mouseup", TinyMCE_table_mouseDownHandler);\r
19 \r
20                 try {\r
21                         // For future FF versions\r
22                         doc.execCommand('enableInlineTableEditing', false, false);\r
23                 } catch (e) {\r
24                         // Ignore\r
25                 }\r
26         }\r
27 \r
28         inst.tableRowClipboard = null;\r
29 }\r
30 \r
31 function TinyMCE_table_mouseDownHandler(e) {\r
32         var elm = tinyMCE.isMSIE ? event.srcElement : e.target;\r
33         var focusElm = tinyMCE.selectedInstance.getFocusElement();\r
34 \r
35         // If press on special Mozilla create TD/TR thingie\r
36         if (elm.nodeName == "BODY" && (focusElm.nodeName == "TD" || focusElm.nodeName == "TH" || (focusElm.parentNode && focusElm.parentNode.nodeName == "TD") ||(focusElm.parentNode && focusElm.parentNode.nodeName == "TH") )) {\r
37                 window.setTimeout(function() {\r
38                         var tableElm = tinyMCE.getParentElement(focusElm, "table");\r
39                         tinyMCE.handleVisualAid(tableElm, true, tinyMCE.settings['visual'], tinyMCE.selectedInstance);\r
40                 }, 10);\r
41         }\r
42 }\r
43 \r
44 /**\r
45  * Returns the HTML contents of the table control.\r
46  */\r
47 function TinyMCE_table_getControlHTML(control_name) {\r
48         var controls = new Array(\r
49                 ['table', 'table.gif', '{$lang_table_desc}', 'mceInsertTable', true],\r
50                 ['delete_col', 'table_delete_col.gif', '{$lang_table_delete_col_desc}', 'mceTableDeleteCol'],\r
51                 ['delete_row', 'table_delete_row.gif', '{$lang_table_delete_row_desc}', 'mceTableDeleteRow'],\r
52                 ['col_after', 'table_insert_col_after.gif', '{$lang_table_col_after_desc}', 'mceTableInsertColAfter'],\r
53                 ['col_before', 'table_insert_col_before.gif', '{$lang_table_col_before_desc}', 'mceTableInsertColBefore'],\r
54                 ['row_after', 'table_insert_row_after.gif', '{$lang_table_row_after_desc}', 'mceTableInsertRowAfter'],\r
55                 ['row_before', 'table_insert_row_before.gif', '{$lang_table_row_before_desc}', 'mceTableInsertRowBefore'],\r
56                 ['row_props', 'table_row_props.gif', '{$lang_table_row_desc}', 'mceTableRowProps', true],\r
57                 ['cell_props', 'table_cell_props.gif', '{$lang_table_cell_desc}', 'mceTableCellProps', true],\r
58                 ['split_cells', 'table_split_cells.gif', '{$lang_table_split_cells_desc}', 'mceTableSplitCells', true],\r
59                 ['merge_cells', 'table_merge_cells.gif', '{$lang_table_merge_cells_desc}', 'mceTableMergeCells', true]);\r
60 \r
61         // Render table control\r
62         for (var i=0; i<controls.length; i++) {\r
63                 var but = controls[i];\r
64 \r
65                 if (but[0] == control_name && (tinyMCE.isMSIE || !tinyMCE.settings['button_tile_map']))\r
66                         return '<a href="javascript:tinyMCE.execInstanceCommand(\'{$editor_id}\',\'' + but[3] + '\', ' + (but.length > 4 ? but[4] : false) + (but.length > 5 ? ', \'' + but[5] + '\'' : '') + ');" target="_self" onmousedown="return false;"><img id="{$editor_id}_' + but[0] + '" src="{$pluginurl}/images/' + but[1] + '" title="' + but[2] + '" width="20" height="20" class="mceButtonDisabled" onmouseover="tinyMCE.switchClass(this,\'mceButtonOver\');" onmouseout="tinyMCE.restoreClass(this);" onmousedown="tinyMCE.restoreAndSwitchClass(this,\'mceButtonDown\');" /></a>';\r
67                 else if (but[0] == control_name)\r
68                         return '<a href="javascript:tinyMCE.execInstanceCommand(\'{$editor_id}\',\'' + but[3] + '\', ' + (but.length > 4 ? but[4] : false) + (but.length > 5 ? ', \'' + but[5] + '\'' : '') + ');" target="_self" onmousedown="return false;"><img id="{$editor_id}_' + but[0] + '" src="{$themeurl}/images/spacer.gif" style="background-image:url({$pluginurl}/images/buttons.gif); background-position: ' + (0-(i*20)) + 'px 0px" title="' + but[2] + '" width="20" height="20" class="mceButtonDisabled" onmouseover="tinyMCE.switchClass(this,\'mceButtonOver\');" onmouseout="tinyMCE.restoreClass(this);" onmousedown="tinyMCE.restoreAndSwitchClass(this,\'mceButtonDown\');" /></a>';\r
69         }\r
70 \r
71         // Special tablecontrols\r
72         if (control_name == "tablecontrols") {\r
73                 var html = "";\r
74 \r
75                 html += tinyMCE.getControlHTML("table");\r
76                 html += tinyMCE.getControlHTML("separator");\r
77                 html += tinyMCE.getControlHTML("row_props");\r
78                 html += tinyMCE.getControlHTML("cell_props");\r
79                 html += tinyMCE.getControlHTML("separator");\r
80                 html += tinyMCE.getControlHTML("row_before");\r
81                 html += tinyMCE.getControlHTML("row_after");\r
82                 html += tinyMCE.getControlHTML("delete_row");\r
83                 html += tinyMCE.getControlHTML("separator");\r
84                 html += tinyMCE.getControlHTML("col_before");\r
85                 html += tinyMCE.getControlHTML("col_after");\r
86                 html += tinyMCE.getControlHTML("delete_col");\r
87                 html += tinyMCE.getControlHTML("separator");\r
88                 html += tinyMCE.getControlHTML("split_cells");\r
89                 html += tinyMCE.getControlHTML("merge_cells");\r
90 \r
91                 return html;\r
92         }\r
93 \r
94         return "";\r
95 }\r
96 \r
97 /**\r
98  * Executes the table commands.\r
99  */\r
100 function TinyMCE_table_execCommand(editor_id, element, command, user_interface, value) {\r
101         // Is table command\r
102         switch (command) {\r
103                 case "mceInsertTable":\r
104                 case "mceTableRowProps":\r
105                 case "mceTableCellProps":\r
106                 case "mceTableSplitCells":\r
107                 case "mceTableMergeCells":\r
108                 case "mceTableInsertRowBefore":\r
109                 case "mceTableInsertRowAfter":\r
110                 case "mceTableDeleteRow":\r
111                 case "mceTableInsertColBefore":\r
112                 case "mceTableInsertColAfter":\r
113                 case "mceTableDeleteCol":\r
114                 case "mceTableCutRow":\r
115                 case "mceTableCopyRow":\r
116                 case "mceTablePasteRowBefore":\r
117                 case "mceTablePasteRowAfter":\r
118                 case "mceTableDelete":\r
119                         var inst = tinyMCE.getInstanceById(editor_id);\r
120 \r
121                         inst.execCommand('mceBeginUndoLevel');\r
122                         TinyMCE_table_doExecCommand(editor_id, element, command, user_interface, value);\r
123                         inst.execCommand('mceEndUndoLevel');\r
124 \r
125                         return true;\r
126         }\r
127 \r
128         // Pass to next handler in chain\r
129         return false;\r
130 }\r
131 \r
132 /**\r
133  * Executes the table commands.\r
134  */\r
135 function TinyMCE_table_doExecCommand(editor_id, element, command, user_interface, value) {\r
136         var inst = tinyMCE.getInstanceById(editor_id);\r
137         var focusElm = inst.getFocusElement();\r
138         var trElm = tinyMCE.getParentElement(focusElm, "tr");\r
139         var tdElm = tinyMCE.getParentElement(focusElm, "td,th");\r
140         var tableElm = tinyMCE.getParentElement(focusElm, "table");\r
141         var doc = inst.contentWindow.document;\r
142         var tableBorder = tableElm ? tableElm.getAttribute("border") : "";\r
143 \r
144         // Get first TD if no TD found\r
145         if (trElm && tdElm == null)\r
146                 tdElm = trElm.cells[0];\r
147 \r
148         // ------- Inner functions ---------\r
149         function inArray(ar, v) {\r
150                 for (var i=0; i<ar.length; i++) {\r
151                         // Is array\r
152                         if (ar[i].length > 0 && inArray(ar[i], v))\r
153                                 return true;\r
154 \r
155                         // Found value\r
156                         if (ar[i] == v)\r
157                                 return true;\r
158                 }\r
159 \r
160                 return false;\r
161         }\r
162 \r
163         function makeTD() {\r
164                 var newTD = doc.createElement("td");\r
165                 newTD.innerHTML = "&nbsp;";\r
166         }\r
167 \r
168         function getColRowSpan(td) {\r
169                 var colspan = tinyMCE.getAttrib(td, "colspan");\r
170                 var rowspan = tinyMCE.getAttrib(td, "rowspan");\r
171 \r
172                 colspan = colspan == "" ? 1 : parseInt(colspan);\r
173                 rowspan = rowspan == "" ? 1 : parseInt(rowspan);\r
174 \r
175                 return {colspan : colspan, rowspan : rowspan};\r
176         }\r
177 \r
178         function getCellPos(grid, td) {\r
179                 for (var y=0; y<grid.length; y++) {\r
180                         for (var x=0; x<grid[y].length; x++) {\r
181                                 if (grid[y][x] == td)\r
182                                         return {cellindex : x, rowindex : y};\r
183                         }\r
184                 }\r
185 \r
186                 return null;\r
187         }\r
188 \r
189         function getCell(grid, row, col) {\r
190                 if (grid[row] && grid[row][col])\r
191                         return grid[row][col];\r
192 \r
193                 return null;\r
194         }\r
195 \r
196         function getTableGrid(table) {\r
197                 var grid = new Array();\r
198                 var rows = table.rows;\r
199 \r
200                 for (var y=0; y<rows.length; y++) {\r
201                         for (var x=0; x<rows[y].cells.length; x++) {\r
202                                 var td = rows[y].cells[x];\r
203                                 var sd = getColRowSpan(td);\r
204 \r
205                                 // All ready filled\r
206                                 for (xstart = x; grid[y] && grid[y][xstart]; xstart++) ;\r
207 \r
208                                 // Fill box\r
209                                 for (var y2=y; y2<y+sd['rowspan']; y2++) {\r
210                                         if (!grid[y2])\r
211                                                 grid[y2] = new Array();\r
212 \r
213                                         for (var x2=xstart; x2<xstart+sd['colspan']; x2++) {\r
214                                                 grid[y2][x2] = td;\r
215                                         }\r
216                                 }\r
217                         }\r
218                 }\r
219 \r
220                 return grid;\r
221         }\r
222 \r
223         function trimRow(table, tr, td, new_tr) {\r
224                 var grid = getTableGrid(table);\r
225                 var cpos = getCellPos(grid, td);\r
226 \r
227                 // Time to crop away some\r
228                 if (new_tr.cells.length != tr.childNodes.length) {\r
229                         var cells = tr.childNodes;\r
230                         var lastElm = null;\r
231 \r
232                         for (var x=0; td = getCell(grid, cpos.rowindex, x); x++) {\r
233                                 var remove = true;\r
234                                 var sd = getColRowSpan(td);\r
235 \r
236                                 // Remove due to rowspan\r
237                                 if (inArray(cells, td)) {\r
238                                         new_tr.childNodes[x]._delete = true;\r
239                                 } else if ((lastElm == null || td != lastElm) && sd.colspan > 1) { // Remove due to colspan\r
240                                         for (var i=x; i<x+td.colSpan; i++)\r
241                                                 new_tr.childNodes[i]._delete = true;\r
242                                 }\r
243 \r
244                                 if ((lastElm == null || td != lastElm) && sd.rowspan > 1)\r
245                                         td.rowSpan = sd.rowspan + 1;\r
246 \r
247                                 lastElm = td;\r
248                         }\r
249 \r
250                         deleteMarked(tableElm);\r
251                 }\r
252         }\r
253 \r
254         function prevElm(node, name) {\r
255                 while ((node = node.previousSibling) != null) {\r
256                         if (node.nodeName == name)\r
257                                 return node;\r
258                 }\r
259 \r
260                 return null;\r
261         }\r
262 \r
263         function nextElm(node, names) {\r
264 \r
265         var namesAr = names.split(',');\r
266 \r
267                 while ((node = node.nextSibling) != null) {\r
268             for (var i=0; i<namesAr.length; i++) {\r
269                 if (node.nodeName.toLowerCase() == namesAr[i].toLowerCase() )\r
270                     return node;\r
271             }\r
272                 }\r
273 \r
274                 return null;\r
275         }\r
276 \r
277         function deleteMarked(tbl) {\r
278                 if (tbl.rows == 0)\r
279                         return;\r
280 \r
281                 var tr = tbl.rows[0];\r
282                 do {\r
283                         var next = nextElm(tr, "TR");\r
284 \r
285                         // Delete row\r
286                         if (tr._delete) {\r
287                                 tr.parentNode.removeChild(tr);\r
288                                 continue;\r
289                         }\r
290 \r
291                         // Delete cells\r
292                         var td = tr.cells[0];\r
293                         if (td.cells > 1) {\r
294                                 do {\r
295                                         var nexttd = nextElm(td, "TD,TH");\r
296 \r
297                                         if (td._delete)\r
298                                                 td.parentNode.removeChild(td);\r
299                                 } while ((td = nexttd) != null);\r
300                         }\r
301                 } while ((tr = next) != null);\r
302         }\r
303 \r
304         function addRows(td_elm, tr_elm, rowspan) {\r
305                 // Add rows\r
306                 td_elm.rowSpan = 1;\r
307                 var trNext = nextElm(tr_elm, "TR");\r
308                 for (var i=1; i<rowspan && trNext; i++) {\r
309                         var newTD = doc.createElement("td");\r
310                         newTD.innerHTML = "&nbsp;";\r
311 \r
312                         if (tinyMCE.isMSIE)\r
313                                 trNext.insertBefore(newTD, trNext.cells(td_elm.cellIndex));\r
314                         else\r
315                                 trNext.insertBefore(newTD, trNext.cells[td_elm.cellIndex]);\r
316 \r
317                         trNext = nextElm(trNext, "TR");\r
318                 }\r
319         }\r
320 \r
321         function copyRow(doc, table, tr) {\r
322                 var grid = getTableGrid(table);\r
323                 var newTR = tr.cloneNode(false);\r
324                 var cpos = getCellPos(grid, tr.cells[0]);\r
325                 var lastCell = null;\r
326                 var tableBorder = tinyMCE.getAttrib(table, "border");\r
327                 var tdElm = null;\r
328 \r
329                 for (var x=0; tdElm = getCell(grid, cpos.rowindex, x); x++) {\r
330                         var newTD = null;\r
331 \r
332                         if (lastCell != tdElm) {\r
333                                 for (var i=0; i<tr.cells.length; i++) {\r
334                                         if (tdElm == tr.cells[i]) {\r
335                                                 newTD = tdElm.cloneNode(true);\r
336                                                 break;\r
337                                         }\r
338                                 }\r
339                         }\r
340 \r
341                         if (newTD == null) {\r
342                                 newTD = doc.createElement("td");\r
343                                 newTD.innerHTML = "&nbsp;";\r
344                         }\r
345 \r
346                         // Reset col/row span\r
347                         newTD.colSpan = 1;\r
348                         newTD.rowSpan = 1;\r
349 \r
350                         newTR.appendChild(newTD);\r
351 \r
352                         lastCell = tdElm;\r
353                 }\r
354 \r
355                 return newTR;\r
356         }\r
357 \r
358         // ---- Commands -----\r
359 \r
360         // Handle commands\r
361         switch (command) {\r
362                 case "mceTableRowProps":\r
363                         if (trElm == null)\r
364                                 return true;\r
365 \r
366                         if (user_interface) {\r
367                                 // Setup template\r
368                                 var template = new Array();\r
369 \r
370                                 template['file'] = '../../plugins/table/row.htm';\r
371                                 template['width'] = 380;\r
372                                 template['height'] = 295;\r
373 \r
374                                 // Language specific width and height addons\r
375                                 template['width'] += tinyMCE.getLang('lang_table_rowprops_delta_width', 0);\r
376                                 template['height'] += tinyMCE.getLang('lang_table_rowprops_delta_width', 0);\r
377 \r
378                                 // Open window\r
379                                 tinyMCE.openWindow(template, {editor_id : inst.editorId, inline : "yes"});\r
380                         }\r
381 \r
382                         return true;\r
383 \r
384                 case "mceTableCellProps":\r
385                         if (tdElm == null)\r
386                                 return true;\r
387 \r
388                         if (user_interface) {\r
389                                 // Setup template\r
390                                 var template = new Array();\r
391 \r
392                                 template['file'] = '../../plugins/table/cell.htm';\r
393                                 template['width'] = 380;\r
394                                 template['height'] = 295;\r
395 \r
396                                 // Language specific width and height addons\r
397                                 template['width'] += tinyMCE.getLang('lang_table_cellprops_delta_width', 0);\r
398                                 template['height'] += tinyMCE.getLang('lang_table_cellprops_delta_width', 0);\r
399 \r
400                                 // Open window\r
401                                 tinyMCE.openWindow(template, {editor_id : inst.editorId, inline : "yes"});\r
402                         }\r
403 \r
404                         return true;\r
405 \r
406                 case "mceInsertTable":\r
407                         if (user_interface) {\r
408                                 // Setup template\r
409                                 var template = new Array();\r
410 \r
411                                 template['file'] = '../../plugins/table/table.htm';\r
412                                 template['width'] = 380;\r
413                                 template['height'] = 295;\r
414 \r
415                                 // Language specific width and height addons\r
416                                 template['width'] += tinyMCE.getLang('lang_table_table_delta_width', 0);\r
417                                 template['height'] += tinyMCE.getLang('lang_table_table_delta_height', 0);\r
418 \r
419                                 // Open window\r
420                                 tinyMCE.openWindow(template, {editor_id : inst.editorId, inline : "yes", action : value});\r
421                         }\r
422 \r
423                         return true;\r
424 \r
425                 case "mceTableDelete":\r
426                         var table = tinyMCE.getParentElement(inst.getFocusElement(), "table");\r
427                         if (table) {\r
428                                 table.parentNode.removeChild(table);\r
429                                 inst.repaint();\r
430                         }\r
431                         return true;\r
432 \r
433                 case "mceTableSplitCells":\r
434                 case "mceTableMergeCells":\r
435                 case "mceTableInsertRowBefore":\r
436                 case "mceTableInsertRowAfter":\r
437                 case "mceTableDeleteRow":\r
438                 case "mceTableInsertColBefore":\r
439                 case "mceTableInsertColAfter":\r
440                 case "mceTableDeleteCol":\r
441                 case "mceTableCutRow":\r
442                 case "mceTableCopyRow":\r
443                 case "mceTablePasteRowBefore":\r
444                 case "mceTablePasteRowAfter":\r
445                         // No table just return (invalid command)\r
446                         if (!tableElm)\r
447                                 return true;\r
448 \r
449                         // Table has a tbody use that reference\r
450                         // Changed logic by ApTest 2005.07.12 (www.aptest.com)\r
451                         // Now lookk at the focused element and take its parentNode.  That will be a tbody or a table.\r
452                         if (tableElm != trElm.parentNode)\r
453                                 tableElm = trElm.parentNode;\r
454 \r
455                         if (tableElm && trElm) {\r
456                                 switch (command) {\r
457                                         case "mceTableInsertRowBefore":\r
458                                                 if (!trElm || !tdElm)\r
459                                                         return true;\r
460 \r
461                                                 var grid = getTableGrid(tableElm);\r
462                                                 var cpos = getCellPos(grid, tdElm);\r
463                                                 var newTR = doc.createElement("tr");\r
464                                                 var lastTDElm = null;\r
465 \r
466                                                 cpos.rowindex--;\r
467                                                 if (cpos.rowindex < 0)\r
468                                                         cpos.rowindex = 0;\r
469 \r
470                                                 // Create cells\r
471                                                 for (var x=0; tdElm = getCell(grid, cpos.rowindex, x); x++) {\r
472                                                         if (tdElm != lastTDElm) {\r
473                                                                 var sd = getColRowSpan(tdElm);\r
474 \r
475                                                                 if (sd['rowspan'] == 1) {\r
476                                                                         var newTD = doc.createElement("td");\r
477 \r
478                                                                         newTD.innerHTML = "&nbsp;";\r
479                                                                         newTD.colSpan = tdElm.colSpan;\r
480 \r
481                                                                         newTR.appendChild(newTD);\r
482                                                                 } else\r
483                                                                         tdElm.rowSpan = sd['rowspan'] + 1;\r
484 \r
485                                                                 lastTDElm = tdElm;\r
486                                                         }\r
487                                                 }\r
488 \r
489                                                 trElm.parentNode.insertBefore(newTR, trElm);\r
490                                         break;\r
491 \r
492                                         case "mceTableCutRow":\r
493                                                 if (!trElm || !tdElm)\r
494                                                         return true;\r
495 \r
496                                                 inst.tableRowClipboard = copyRow(doc, tableElm, trElm);\r
497                                                 inst.execCommand("mceTableDeleteRow");\r
498                                                 break;\r
499 \r
500                                         case "mceTableCopyRow":\r
501                                                 if (!trElm || !tdElm)\r
502                                                         return true;\r
503 \r
504                                                 inst.tableRowClipboard = copyRow(doc, tableElm, trElm);\r
505                                                 break;\r
506 \r
507                                         case "mceTablePasteRowBefore":\r
508                                                 if (!trElm || !tdElm)\r
509                                                         return true;\r
510 \r
511                                                 var newTR = inst.tableRowClipboard.cloneNode(true);\r
512 \r
513                                                 var prevTR = prevElm(trElm, "TR");\r
514                                                 if (prevTR != null)\r
515                                                         trimRow(tableElm, prevTR, prevTR.cells[0], newTR);\r
516 \r
517                                                 trElm.parentNode.insertBefore(newTR, trElm);\r
518                                                 break;\r
519 \r
520                                         case "mceTablePasteRowAfter":\r
521                                                 if (!trElm || !tdElm)\r
522                                                         return true;\r
523                                                 \r
524                                                 var nextTR = nextElm(trElm, "TR");\r
525                                                 var newTR = inst.tableRowClipboard.cloneNode(true);\r
526 \r
527                                                 trimRow(tableElm, trElm, tdElm, newTR);\r
528 \r
529                                                 if (nextTR == null)\r
530                                                         trElm.parentNode.appendChild(newTR);\r
531                                                 else\r
532                                                         nextTR.parentNode.insertBefore(newTR, nextTR);\r
533 \r
534                                                 break;\r
535 \r
536                                         case "mceTableInsertRowAfter":\r
537                                                 if (!trElm || !tdElm)\r
538                                                         return true;\r
539 \r
540                                                 var grid = getTableGrid(tableElm);\r
541                                                 var cpos = getCellPos(grid, tdElm);\r
542                                                 var newTR = doc.createElement("tr");\r
543                                                 var lastTDElm = null;\r
544 \r
545                                                 // Create cells\r
546                                                 for (var x=0; tdElm = getCell(grid, cpos.rowindex, x); x++) {\r
547                                                         if (tdElm != lastTDElm) {\r
548                                                                 var sd = getColRowSpan(tdElm);\r
549 \r
550                                                                 if (sd['rowspan'] == 1) {\r
551                                                                         var newTD = doc.createElement("td");\r
552 \r
553                                                                         newTD.innerHTML = "&nbsp;";\r
554                                                                         newTD.colSpan = tdElm.colSpan;\r
555 \r
556                                                                         newTR.appendChild(newTD);\r
557                                                                 } else\r
558                                                                         tdElm.rowSpan = sd['rowspan'] + 1;\r
559 \r
560                                                                 lastTDElm = tdElm;\r
561                                                         }\r
562                                                 }\r
563 \r
564                                                 if (newTR.hasChildNodes()) {\r
565                                                         var nextTR = nextElm(trElm, "TR");\r
566                                                         if (nextTR)\r
567                                                                 nextTR.parentNode.insertBefore(newTR, nextTR);\r
568                                                         else\r
569                                                                 tableElm.appendChild(newTR);\r
570                                                 }\r
571                                         break;\r
572 \r
573                                         case "mceTableDeleteRow":\r
574                                                 if (!trElm || !tdElm)\r
575                                                         return true;\r
576         \r
577                                                 var grid = getTableGrid(tableElm);\r
578                                                 var cpos = getCellPos(grid, tdElm);\r
579 \r
580                                                 // Only one row, remove whole table\r
581                                                 if (grid.length == 1) {\r
582                                                         tableElm.parentNode.removeChild(tableElm);\r
583                                                         return true;\r
584                                                 }\r
585 \r
586                                                 // Move down row spanned cells\r
587                                                 var cells = trElm.cells;\r
588                                                 var nextTR = nextElm(trElm, "TR");\r
589                                                 for (var x=0; x<cells.length; x++) {\r
590                                                         if (cells[x].rowSpan > 1) {\r
591                                                                 var newTD = cells[x].cloneNode(true);\r
592                                                                 var sd = getColRowSpan(cells[x]);\r
593 \r
594                                                                 newTD.rowSpan = sd.rowspan - 1;\r
595 \r
596                                                                 var nextTD = nextTR.cells[x];\r
597 \r
598                                                                 if (nextTD == null)\r
599                                                                         nextTR.appendChild(newTD);\r
600                                                                 else\r
601                                                                         nextTR.insertBefore(newTD, nextTD);\r
602                                                         }\r
603                                                 }\r
604 \r
605                                                 // Delete cells\r
606                                                 var lastTDElm = null;\r
607                                                 for (var x=0; tdElm = getCell(grid, cpos.rowindex, x); x++) {\r
608                                                         if (tdElm != lastTDElm) {\r
609                                                                 var sd = getColRowSpan(tdElm);\r
610 \r
611                                                                 if (sd.rowspan > 1) {\r
612                                                                         tdElm.rowSpan = sd.rowspan - 1;\r
613                                                                 } else {\r
614                                                                         trElm = tdElm.parentNode;\r
615 \r
616                                                                         if (trElm.parentNode)\r
617                                                                                 trElm._delete = true;\r
618                                                                 }\r
619 \r
620                                                                 lastTDElm = tdElm;\r
621                                                         }\r
622                                                 }\r
623 \r
624                                                 deleteMarked(tableElm);\r
625 \r
626                                                 cpos.rowindex--;\r
627                                                 if (cpos.rowindex < 0)\r
628                                                         cpos.rowindex = 0;\r
629 \r
630                                                 inst.selectNode(getCell(grid, cpos.rowindex, 0), true, true);\r
631                                         break;\r
632 \r
633                                         case "mceTableInsertColBefore":\r
634                                                 if (!trElm || !tdElm)\r
635                                                         return true;\r
636 \r
637                                                 var grid = getTableGrid(tableElm);\r
638                                                 var cpos = getCellPos(grid, tdElm);\r
639                                                 var lastTDElm = null;\r
640 \r
641                                                 for (var y=0; tdElm = getCell(grid, y, cpos.cellindex); y++) {\r
642                                                         if (tdElm != lastTDElm) {\r
643                                                                 var sd = getColRowSpan(tdElm);\r
644 \r
645                                                                 if (sd['colspan'] == 1) {\r
646                                                                         var newTD = doc.createElement("td");\r
647 \r
648                                                                         newTD.innerHTML = "&nbsp;";\r
649                                                                         newTD.rowSpan = tdElm.rowSpan;\r
650 \r
651                                                                         tdElm.parentNode.insertBefore(newTD, tdElm);\r
652                                                                 } else\r
653                                                                         tdElm.colSpan++;\r
654 \r
655                                                                 lastTDElm = tdElm;\r
656                                                         }\r
657                                                 }\r
658                                         break;\r
659 \r
660                                         case "mceTableInsertColAfter":\r
661                                                 if (!trElm || !tdElm)\r
662                                                         return true;\r
663 \r
664                                                 var grid = getTableGrid(tableElm);\r
665                                                 var cpos = getCellPos(grid, tdElm);\r
666                                                 var lastTDElm = null;\r
667 \r
668                                                 for (var y=0; tdElm = getCell(grid, y, cpos.cellindex); y++) {\r
669                                                         if (tdElm != lastTDElm) {\r
670                                                                 var sd = getColRowSpan(tdElm);\r
671 \r
672                                                                 if (sd['colspan'] == 1) {\r
673                                                                         var newTD = doc.createElement("td");\r
674 \r
675                                                                         newTD.innerHTML = "&nbsp;";\r
676                                                                         newTD.rowSpan = tdElm.rowSpan;\r
677 \r
678                                                                         var nextTD = nextElm(tdElm, "TD");\r
679                                                                         if (nextTD == null)\r
680                                                                                 tdElm.parentNode.appendChild(newTD);\r
681                                                                         else\r
682                                                                                 nextTD.parentNode.insertBefore(newTD, nextTD);\r
683                                                                 } else\r
684                                                                         tdElm.colSpan++;\r
685 \r
686                                                                 lastTDElm = tdElm;\r
687                                                         }\r
688                                                 }\r
689                                         break;\r
690 \r
691                                         case "mceTableDeleteCol":\r
692                                                 if (!trElm || !tdElm)\r
693                                                         return true;\r
694 \r
695                                                 var grid = getTableGrid(tableElm);\r
696                                                 var cpos = getCellPos(grid, tdElm);\r
697                                                 var lastTDElm = null;\r
698 \r
699                                                 // Only one col, remove whole table\r
700                                                 if (grid.length > 1 && grid[0].length <= 1) {\r
701                                                         tableElm.parentNode.removeChild(tableElm);\r
702                                                         return true;\r
703                                                 }\r
704 \r
705                                                 // Delete cells\r
706                                                 for (var y=0; tdElm = getCell(grid, y, cpos.cellindex); y++) {\r
707                                                         if (tdElm != lastTDElm) {\r
708                                                                 var sd = getColRowSpan(tdElm);\r
709 \r
710                                                                 if (sd['colspan'] > 1)\r
711                                                                         tdElm.colSpan = sd['colspan'] - 1;\r
712                                                                 else {\r
713                                                                         if (tdElm.parentNode)\r
714                                                                                 tdElm.parentNode.removeChild(tdElm);\r
715                                                                 }\r
716 \r
717                                                                 lastTDElm = tdElm;\r
718                                                         }\r
719                                                 }\r
720 \r
721                                                 cpos.cellindex--;\r
722                                                 if (cpos.cellindex < 0)\r
723                                                         cpos.cellindex = 0;\r
724 \r
725                                                 inst.selectNode(getCell(grid, 0, cpos.cellindex), true, true);\r
726                                         break;\r
727 \r
728                                 case "mceTableSplitCells":\r
729                                         if (!trElm || !tdElm)\r
730                                                 return true;\r
731 \r
732                                         var spandata = getColRowSpan(tdElm);\r
733 \r
734                                         var colspan = spandata["colspan"];\r
735                                         var rowspan = spandata["rowspan"];\r
736 \r
737                                         // Needs splitting\r
738                                         if (colspan > 1 || rowspan > 1) {\r
739                                                 // Generate cols\r
740                                                 tdElm.colSpan = 1;\r
741                                                 for (var i=1; i<colspan; i++) {\r
742                                                         var newTD = doc.createElement("td");\r
743 \r
744                                                         newTD.innerHTML = "&nbsp;";\r
745 \r
746                                                         trElm.insertBefore(newTD, nextElm(tdElm, "TD"));\r
747 \r
748                                                         if (rowspan > 1)\r
749                                                                 addRows(newTD, trElm, rowspan);\r
750                                                 }\r
751 \r
752                                                 addRows(tdElm, trElm, rowspan);\r
753                                         }\r
754 \r
755                                         // Apply visual aids\r
756                                         tableElm = tinyMCE.getParentElement(inst.getFocusElement(), "table");\r
757                                         break;\r
758 \r
759                                 case "mceTableMergeCells":\r
760                                         var rows = new Array();\r
761                                         var sel = inst.getSel();\r
762                                         var grid = getTableGrid(tableElm);\r
763 \r
764                                         if (tinyMCE.isMSIE || sel.rangeCount == 1) {\r
765                                                 if (user_interface) {\r
766                                                         // Setup template\r
767                                                         var template = new Array();\r
768                                                         var sp = getColRowSpan(tdElm);\r
769 \r
770                                                         template['file'] = '../../plugins/table/merge_cells.htm';\r
771                                                         template['width'] = 250;\r
772                                                         template['height'] = 105;\r
773 \r
774                                                         // Language specific width and height addons\r
775                                                         template['width'] += tinyMCE.getLang('lang_table_merge_cells_delta_width', 0);\r
776                                                         template['height'] += tinyMCE.getLang('lang_table_merge_cells_delta_height', 0);\r
777 \r
778                                                         // Open window\r
779                                                         tinyMCE.openWindow(template, {editor_id : inst.editorId, inline : "yes", action : "update", numcols : sp.colspan, numrows : sp.rowspan});\r
780 \r
781                                                         return true;\r
782                                                 } else {\r
783                                                         var numRows = parseInt(value['numrows']);\r
784                                                         var numCols = parseInt(value['numcols']);\r
785                                                         var cpos = getCellPos(grid, tdElm);\r
786 \r
787                                                         if (("" + numRows) == "NaN")\r
788                                                                 numRows = 1;\r
789 \r
790                                                         if (("" + numCols) == "NaN")\r
791                                                                 numCols = 1;\r
792 \r
793                                                         // Get rows and cells\r
794                                                         var tRows = tableElm.rows;\r
795                                                         for (var y=cpos.rowindex; y<grid.length; y++) {\r
796                                                                 var rowCells = new Array();\r
797 \r
798                                                                 for (var x=cpos.cellindex; x<grid[y].length; x++) {\r
799                                                                         var td = getCell(grid, y, x);\r
800 \r
801                                                                         if (td && !inArray(rows, td) && !inArray(rowCells, td)) {\r
802                                                                                 var cp = getCellPos(grid, td);\r
803 \r
804                                                                                 // Within range\r
805                                                                                 if (cp.cellindex < cpos.cellindex+numCols && cp.rowindex < cpos.rowindex+numRows)\r
806                                                                                         rowCells[rowCells.length] = td;\r
807                                                                         }\r
808                                                                 }\r
809 \r
810                                                                 if (rowCells.length > 0)\r
811                                                                         rows[rows.length] = rowCells;\r
812                                                         }\r
813 \r
814                                                         //return true;\r
815                                                 }\r
816                                         } else {\r
817                                                 var cells = new Array();\r
818                                                 var sel = inst.getSel();\r
819                                                 var lastTR = null;\r
820                                                 var curRow = null;\r
821                                                 var x1 = -1, y1 = -1, x2, y2;\r
822 \r
823                                                 // Only one cell selected, whats the point?\r
824                                                 if (sel.rangeCount < 2)\r
825                                                         return true;\r
826 \r
827                                                 // Get all selected cells\r
828                                                 for (var i=0; i<sel.rangeCount; i++) {\r
829                                                         var rng = sel.getRangeAt(i);\r
830                                                         var tdElm = rng.startContainer.childNodes[rng.startOffset];\r
831 \r
832                                                         if (!tdElm)\r
833                                                                 break;\r
834 \r
835                                                         if (tdElm.nodeName == "TD")\r
836                                                                 cells[cells.length] = tdElm;\r
837                                                 }\r
838 \r
839                                                 // Get rows and cells\r
840                                                 var tRows = tableElm.rows;\r
841                                                 for (var y=0; y<tRows.length; y++) {\r
842                                                         var rowCells = new Array();\r
843 \r
844                                                         for (var x=0; x<tRows[y].cells.length; x++) {\r
845                                                                 var td = tRows[y].cells[x];\r
846 \r
847                                                                 for (var i=0; i<cells.length; i++) {\r
848                                                                         if (td == cells[i]) {\r
849                                                                                 rowCells[rowCells.length] = td;\r
850                                                                         }\r
851                                                                 }\r
852                                                         }\r
853 \r
854                                                         if (rowCells.length > 0)\r
855                                                                 rows[rows.length] = rowCells;\r
856                                                 }\r
857 \r
858                                                 // Find selected cells in grid and box\r
859                                                 var curRow = new Array();\r
860                                                 var lastTR = null;\r
861                                                 for (var y=0; y<grid.length; y++) {\r
862                                                         for (var x=0; x<grid[y].length; x++) {\r
863                                                                 grid[y][x]._selected = false;\r
864 \r
865                                                                 for (var i=0; i<cells.length; i++) {\r
866                                                                         if (grid[y][x] == cells[i]) {\r
867                                                                                 // Get start pos\r
868                                                                                 if (x1 == -1) {\r
869                                                                                         x1 = x;\r
870                                                                                         y1 = y;\r
871                                                                                 }\r
872 \r
873                                                                                 // Get end pos\r
874                                                                                 x2 = x;\r
875                                                                                 y2 = y;\r
876 \r
877                                                                                 grid[y][x]._selected = true;\r
878                                                                         }\r
879                                                                 }\r
880                                                         }\r
881                                                 }\r
882 \r
883                                                 // Is there gaps, if so deny\r
884                                                 for (var y=y1; y<=y2; y++) {\r
885                                                         for (var x=x1; x<=x2; x++) {\r
886                                                                 if (!grid[y][x]._selected) {\r
887                                                                         alert("Invalid selection for merge.");\r
888                                                                         return true;\r
889                                                                 }\r
890                                                         }\r
891                                                 }\r
892                                         }\r
893 \r
894                                         // Validate selection and get total rowspan and colspan\r
895                                         var rowSpan = 1, colSpan = 1;\r
896 \r
897                                         // Validate horizontal and get total colspan\r
898                                         var lastRowSpan = -1;\r
899                                         for (var y=0; y<rows.length; y++) {\r
900                                                 var rowColSpan = 0;\r
901 \r
902                                                 for (var x=0; x<rows[y].length; x++) {\r
903                                                         var sd = getColRowSpan(rows[y][x]);\r
904 \r
905                                                         rowColSpan += sd['colspan'];\r
906 \r
907                                                         if (lastRowSpan != -1 && sd['rowspan'] != lastRowSpan) {\r
908                                                                 alert("Invalid selection for merge.");\r
909                                                                 return true;\r
910                                                         }\r
911 \r
912                                                         lastRowSpan = sd['rowspan'];\r
913                                                 }\r
914 \r
915                                                 if (rowColSpan > colSpan)\r
916                                                         colSpan = rowColSpan;\r
917 \r
918                                                 lastRowSpan = -1;\r
919                                         }\r
920 \r
921                                         // Validate vertical and get total rowspan\r
922                                         var lastColSpan = -1;\r
923                                         for (var x=0; x<rows[0].length; x++) {\r
924                                                 var colRowSpan = 0;\r
925 \r
926                                                 for (var y=0; y<rows.length; y++) {\r
927                                                         var sd = getColRowSpan(rows[y][x]);\r
928 \r
929                                                         colRowSpan += sd['rowspan'];\r
930 \r
931                                                         if (lastColSpan != -1 && sd['colspan'] != lastColSpan) {\r
932                                                                 alert("Invalid selection for merge.");\r
933                                                                 return true;\r
934                                                         }\r
935 \r
936                                                         lastColSpan = sd['colspan'];\r
937                                                 }\r
938 \r
939                                                 if (colRowSpan > rowSpan)\r
940                                                         rowSpan = colRowSpan;\r
941 \r
942                                                 lastColSpan = -1;\r
943                                         }\r
944 \r
945                                         // Setup td\r
946                                         tdElm = rows[0][0];\r
947                                         tdElm.rowSpan = rowSpan;\r
948                                         tdElm.colSpan = colSpan;\r
949 \r
950                                         // Merge cells\r
951                                         for (var y=0; y<rows.length; y++) {\r
952                                                 for (var x=0; x<rows[y].length; x++) {\r
953                                                         var html = rows[y][x].innerHTML;\r
954                                                         var chk = tinyMCE.regexpReplace(html, "[ \t\r\n]", "");\r
955 \r
956                                                         if (chk != "<br/>" && chk != "<br>" && chk != "&nbsp;" && (x+y > 0))\r
957                                                                 tdElm.innerHTML += html;\r
958 \r
959                                                         // Not current cell\r
960                                                         if (rows[y][x] != tdElm && !rows[y][x]._deleted) {\r
961                                                                 var cpos = getCellPos(grid, rows[y][x]);\r
962                                                                 var tr = rows[y][x].parentNode;\r
963 \r
964                                                                 tr.removeChild(rows[y][x]);\r
965                                                                 rows[y][x]._deleted = true;\r
966 \r
967                                                                 // Empty TR, remove it\r
968                                                                 if (!tr.hasChildNodes()) {\r
969                                                                         tr.parentNode.removeChild(tr);\r
970 \r
971                                                                         var lastCell = null;\r
972                                                                         for (var x=0; cellElm = getCell(grid, cpos.rowindex, x); x++) {\r
973                                                                                 if (cellElm != lastCell && cellElm.rowSpan > 1)\r
974                                                                                         cellElm.rowSpan--;\r
975 \r
976                                                                                 lastCell = cellElm;\r
977                                                                         }\r
978 \r
979                                                                         if (tdElm.rowSpan > 1)\r
980                                                                                 tdElm.rowSpan--;\r
981                                                                 }\r
982                                                         }\r
983                                                 }\r
984                                         }\r
985 \r
986                                         break;\r
987                                 }\r
988 \r
989                                 tableElm = tinyMCE.getParentElement(inst.getFocusElement(), "table");\r
990                                 tinyMCE.handleVisualAid(tableElm, true, tinyMCE.settings['visual'], tinyMCE.selectedInstance);\r
991                                 tinyMCE.triggerNodeChange();\r
992                                 inst.repaint();\r
993                         }\r
994 \r
995                 return true;\r
996         }\r
997 \r
998         // Pass to next handler in chain\r
999         return false;\r
1000 }\r
1001 \r
1002 function TinyMCE_table_handleNodeChange(editor_id, node, undo_index, undo_levels, visual_aid, any_selection) {\r
1003         var colspan = "1", rowspan = "1";\r
1004 \r
1005         var inst = tinyMCE.getInstanceById(editor_id);\r
1006 \r
1007         // Reset table controls\r
1008         tinyMCE.switchClassSticky(editor_id + '_table', 'mceButtonNormal');\r
1009         tinyMCE.switchClassSticky(editor_id + '_row_props', 'mceButtonDisabled', true);\r
1010         tinyMCE.switchClassSticky(editor_id + '_cell_props', 'mceButtonDisabled', true);\r
1011         tinyMCE.switchClassSticky(editor_id + '_row_before', 'mceButtonDisabled', true);\r
1012         tinyMCE.switchClassSticky(editor_id + '_row_after', 'mceButtonDisabled', true);\r
1013         tinyMCE.switchClassSticky(editor_id + '_delete_row', 'mceButtonDisabled', true);\r
1014         tinyMCE.switchClassSticky(editor_id + '_col_before', 'mceButtonDisabled', true);\r
1015         tinyMCE.switchClassSticky(editor_id + '_col_after', 'mceButtonDisabled', true);\r
1016         tinyMCE.switchClassSticky(editor_id + '_delete_col', 'mceButtonDisabled', true);\r
1017         tinyMCE.switchClassSticky(editor_id + '_split_cells', 'mceButtonDisabled', true);\r
1018         tinyMCE.switchClassSticky(editor_id + '_merge_cells', 'mceButtonDisabled', true);\r
1019 \r
1020         // Within a tr element\r
1021         if (tinyMCE.getParentElement(node, "tr"))\r
1022                 tinyMCE.switchClassSticky(editor_id + '_row_props', 'mceButtonSelected', false);\r
1023 \r
1024         // Within a td element\r
1025         if (tdElm = tinyMCE.getParentElement(node, "td,th")) {\r
1026                 tinyMCE.switchClassSticky(editor_id + '_cell_props', 'mceButtonSelected', false);\r
1027                 tinyMCE.switchClassSticky(editor_id + '_row_before', 'mceButtonNormal', false);\r
1028                 tinyMCE.switchClassSticky(editor_id + '_row_after', 'mceButtonNormal', false);\r
1029                 tinyMCE.switchClassSticky(editor_id + '_delete_row', 'mceButtonNormal', false);\r
1030                 tinyMCE.switchClassSticky(editor_id + '_col_before', 'mceButtonNormal', false);\r
1031                 tinyMCE.switchClassSticky(editor_id + '_col_after', 'mceButtonNormal', false);\r
1032                 tinyMCE.switchClassSticky(editor_id + '_delete_col', 'mceButtonNormal', false);\r
1033 \r
1034                 colspan = tinyMCE.getAttrib(tdElm, "colspan");\r
1035                 rowspan = tinyMCE.getAttrib(tdElm, "rowspan");\r
1036 \r
1037                 colspan = colspan == "" ? "1" : colspan;\r
1038                 rowspan = rowspan == "" ? "1" : rowspan;\r
1039 \r
1040                 if (colspan != "1" || rowspan != "1")\r
1041                         tinyMCE.switchClassSticky(editor_id + '_split_cells', 'mceButtonNormal', false);\r
1042         }\r
1043 \r
1044         // Within table\r
1045         if (tinyMCE.getParentElement(node, "table")) {\r
1046                 tinyMCE.switchClassSticky(editor_id + '_table', 'mceButtonSelected');\r
1047                 tinyMCE.switchClassSticky(editor_id + '_merge_cells', 'mceButtonNormal', false);\r
1048         }\r
1049 }\r