annotate media/js/tiny_mce/plugins/table/editor_plugin_src.js @ 133:c515b7401078

Use the new common way to apply markItUp to textareas and to get the smiley and markdown help dialogs for all the remaining apps except for forums and comments.
author Brian Neal <bgneal@gmail.com>
date Fri, 27 Nov 2009 00:21:47 +0000
parents a5b4c5ce0658
children 149c3567fec1
rev   line source
bgneal@45 1 /**
bgneal@45 2 * $Id: editor_plugin_src.js 953 2008-11-04 10:16:50Z spocke $
bgneal@45 3 *
bgneal@45 4 * @author Moxiecode
bgneal@45 5 * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
bgneal@45 6 */
bgneal@45 7
bgneal@45 8 (function() {
bgneal@45 9 var each = tinymce.each;
bgneal@45 10
bgneal@45 11 tinymce.create('tinymce.plugins.TablePlugin', {
bgneal@45 12 init : function(ed, url) {
bgneal@45 13 var t = this;
bgneal@45 14
bgneal@45 15 t.editor = ed;
bgneal@45 16 t.url = url;
bgneal@45 17
bgneal@45 18 // Register buttons
bgneal@45 19 each([
bgneal@45 20 ['table', 'table.desc', 'mceInsertTable', true],
bgneal@45 21 ['delete_table', 'table.del', 'mceTableDelete'],
bgneal@45 22 ['delete_col', 'table.delete_col_desc', 'mceTableDeleteCol'],
bgneal@45 23 ['delete_row', 'table.delete_row_desc', 'mceTableDeleteRow'],
bgneal@45 24 ['col_after', 'table.col_after_desc', 'mceTableInsertColAfter'],
bgneal@45 25 ['col_before', 'table.col_before_desc', 'mceTableInsertColBefore'],
bgneal@45 26 ['row_after', 'table.row_after_desc', 'mceTableInsertRowAfter'],
bgneal@45 27 ['row_before', 'table.row_before_desc', 'mceTableInsertRowBefore'],
bgneal@45 28 ['row_props', 'table.row_desc', 'mceTableRowProps', true],
bgneal@45 29 ['cell_props', 'table.cell_desc', 'mceTableCellProps', true],
bgneal@45 30 ['split_cells', 'table.split_cells_desc', 'mceTableSplitCells', true],
bgneal@45 31 ['merge_cells', 'table.merge_cells_desc', 'mceTableMergeCells', true]
bgneal@45 32 ], function(c) {
bgneal@45 33 ed.addButton(c[0], {title : c[1], cmd : c[2], ui : c[3]});
bgneal@45 34 });
bgneal@45 35
bgneal@45 36 if (ed.getParam('inline_styles')) {
bgneal@45 37 // Force move of attribs to styles in strict mode
bgneal@45 38 ed.onPreProcess.add(function(ed, o) {
bgneal@45 39 var dom = ed.dom;
bgneal@45 40
bgneal@45 41 each(dom.select('table', o.node), function(n) {
bgneal@45 42 var v;
bgneal@45 43
bgneal@45 44 if (v = dom.getAttrib(n, 'width')) {
bgneal@45 45 dom.setStyle(n, 'width', v);
bgneal@45 46 dom.setAttrib(n, 'width');
bgneal@45 47 }
bgneal@45 48
bgneal@45 49 if (v = dom.getAttrib(n, 'height')) {
bgneal@45 50 dom.setStyle(n, 'height', v);
bgneal@45 51 dom.setAttrib(n, 'height');
bgneal@45 52 }
bgneal@45 53 });
bgneal@45 54 });
bgneal@45 55 }
bgneal@45 56
bgneal@45 57 ed.onInit.add(function() {
bgneal@45 58 if (ed && ed.plugins.contextmenu) {
bgneal@45 59 ed.plugins.contextmenu.onContextMenu.add(function(th, m, e) {
bgneal@45 60 var sm, se = ed.selection, el = se.getNode() || ed.getBody();
bgneal@45 61
bgneal@45 62 if (ed.dom.getParent(e, 'td') || ed.dom.getParent(e, 'th')) {
bgneal@45 63 m.removeAll();
bgneal@45 64
bgneal@45 65 if (el.nodeName == 'A' && !ed.dom.getAttrib(el, 'name')) {
bgneal@45 66 m.add({title : 'advanced.link_desc', icon : 'link', cmd : ed.plugins.advlink ? 'mceAdvLink' : 'mceLink', ui : true});
bgneal@45 67 m.add({title : 'advanced.unlink_desc', icon : 'unlink', cmd : 'UnLink'});
bgneal@45 68 m.addSeparator();
bgneal@45 69 }
bgneal@45 70
bgneal@45 71 if (el.nodeName == 'IMG' && el.className.indexOf('mceItem') == -1) {
bgneal@45 72 m.add({title : 'advanced.image_desc', icon : 'image', cmd : ed.plugins.advimage ? 'mceAdvImage' : 'mceImage', ui : true});
bgneal@45 73 m.addSeparator();
bgneal@45 74 }
bgneal@45 75
bgneal@45 76 m.add({title : 'table.desc', icon : 'table', cmd : 'mceInsertTable', ui : true, value : {action : 'insert'}});
bgneal@45 77 m.add({title : 'table.props_desc', icon : 'table_props', cmd : 'mceInsertTable', ui : true});
bgneal@45 78 m.add({title : 'table.del', icon : 'delete_table', cmd : 'mceTableDelete', ui : true});
bgneal@45 79 m.addSeparator();
bgneal@45 80
bgneal@45 81 // Cell menu
bgneal@45 82 sm = m.addMenu({title : 'table.cell'});
bgneal@45 83 sm.add({title : 'table.cell_desc', icon : 'cell_props', cmd : 'mceTableCellProps', ui : true});
bgneal@45 84 sm.add({title : 'table.split_cells_desc', icon : 'split_cells', cmd : 'mceTableSplitCells', ui : true});
bgneal@45 85 sm.add({title : 'table.merge_cells_desc', icon : 'merge_cells', cmd : 'mceTableMergeCells', ui : true});
bgneal@45 86
bgneal@45 87 // Row menu
bgneal@45 88 sm = m.addMenu({title : 'table.row'});
bgneal@45 89 sm.add({title : 'table.row_desc', icon : 'row_props', cmd : 'mceTableRowProps', ui : true});
bgneal@45 90 sm.add({title : 'table.row_before_desc', icon : 'row_before', cmd : 'mceTableInsertRowBefore'});
bgneal@45 91 sm.add({title : 'table.row_after_desc', icon : 'row_after', cmd : 'mceTableInsertRowAfter'});
bgneal@45 92 sm.add({title : 'table.delete_row_desc', icon : 'delete_row', cmd : 'mceTableDeleteRow'});
bgneal@45 93 sm.addSeparator();
bgneal@45 94 sm.add({title : 'table.cut_row_desc', icon : 'cut', cmd : 'mceTableCutRow'});
bgneal@45 95 sm.add({title : 'table.copy_row_desc', icon : 'copy', cmd : 'mceTableCopyRow'});
bgneal@45 96 sm.add({title : 'table.paste_row_before_desc', icon : 'paste', cmd : 'mceTablePasteRowBefore'});
bgneal@45 97 sm.add({title : 'table.paste_row_after_desc', icon : 'paste', cmd : 'mceTablePasteRowAfter'});
bgneal@45 98
bgneal@45 99 // Column menu
bgneal@45 100 sm = m.addMenu({title : 'table.col'});
bgneal@45 101 sm.add({title : 'table.col_before_desc', icon : 'col_before', cmd : 'mceTableInsertColBefore'});
bgneal@45 102 sm.add({title : 'table.col_after_desc', icon : 'col_after', cmd : 'mceTableInsertColAfter'});
bgneal@45 103 sm.add({title : 'table.delete_col_desc', icon : 'delete_col', cmd : 'mceTableDeleteCol'});
bgneal@45 104 } else
bgneal@45 105 m.add({title : 'table.desc', icon : 'table', cmd : 'mceInsertTable', ui : true});
bgneal@45 106 });
bgneal@45 107 }
bgneal@45 108 });
bgneal@45 109
bgneal@45 110 // Add undo level when new rows are created using the tab key
bgneal@45 111 ed.onKeyDown.add(function(ed, e) {
bgneal@45 112 if (e.keyCode == 9 && ed.dom.getParent(ed.selection.getNode(), 'TABLE')) {
bgneal@45 113 if (!tinymce.isGecko && !tinymce.isOpera) {
bgneal@45 114 tinyMCE.execInstanceCommand(ed.editorId, "mceTableMoveToNextRow", true);
bgneal@45 115 return tinymce.dom.Event.cancel(e);
bgneal@45 116 }
bgneal@45 117
bgneal@45 118 ed.undoManager.add();
bgneal@45 119 }
bgneal@45 120 });
bgneal@45 121
bgneal@45 122 // Select whole table is a table border is clicked
bgneal@45 123 if (!tinymce.isIE) {
bgneal@45 124 if (ed.getParam('table_selection', true)) {
bgneal@45 125 ed.onClick.add(function(ed, e) {
bgneal@45 126 e = e.target;
bgneal@45 127
bgneal@45 128 if (e.nodeName === 'TABLE')
bgneal@45 129 ed.selection.select(e);
bgneal@45 130 });
bgneal@45 131 }
bgneal@45 132 }
bgneal@45 133
bgneal@45 134 ed.onNodeChange.add(function(ed, cm, n) {
bgneal@45 135 var p = ed.dom.getParent(n, 'td,th,caption');
bgneal@45 136
bgneal@45 137 cm.setActive('table', n.nodeName === 'TABLE' || !!p);
bgneal@45 138 if (p && p.nodeName === 'CAPTION')
bgneal@45 139 p = null;
bgneal@45 140
bgneal@45 141 cm.setDisabled('delete_table', !p);
bgneal@45 142 cm.setDisabled('delete_col', !p);
bgneal@45 143 cm.setDisabled('delete_table', !p);
bgneal@45 144 cm.setDisabled('delete_row', !p);
bgneal@45 145 cm.setDisabled('col_after', !p);
bgneal@45 146 cm.setDisabled('col_before', !p);
bgneal@45 147 cm.setDisabled('row_after', !p);
bgneal@45 148 cm.setDisabled('row_before', !p);
bgneal@45 149 cm.setDisabled('row_props', !p);
bgneal@45 150 cm.setDisabled('cell_props', !p);
bgneal@45 151 cm.setDisabled('split_cells', !p || (parseInt(ed.dom.getAttrib(p, 'colspan', '1')) < 2 && parseInt(ed.dom.getAttrib(p, 'rowspan', '1')) < 2));
bgneal@45 152 cm.setDisabled('merge_cells', !p);
bgneal@45 153 });
bgneal@45 154
bgneal@45 155 // Padd empty table cells
bgneal@45 156 if (!tinymce.isIE) {
bgneal@45 157 ed.onBeforeSetContent.add(function(ed, o) {
bgneal@45 158 if (o.initial)
bgneal@45 159 o.content = o.content.replace(/<(td|th)([^>]+|)>\s*<\/(td|th)>/g, tinymce.isOpera ? '<$1$2>&nbsp;</$1>' : '<$1$2><br mce_bogus="1" /></$1>');
bgneal@45 160 });
bgneal@45 161 }
bgneal@45 162 },
bgneal@45 163
bgneal@45 164 execCommand : function(cmd, ui, val) {
bgneal@45 165 var ed = this.editor, b;
bgneal@45 166
bgneal@45 167 // Is table command
bgneal@45 168 switch (cmd) {
bgneal@45 169 case "mceTableMoveToNextRow":
bgneal@45 170 case "mceInsertTable":
bgneal@45 171 case "mceTableRowProps":
bgneal@45 172 case "mceTableCellProps":
bgneal@45 173 case "mceTableSplitCells":
bgneal@45 174 case "mceTableMergeCells":
bgneal@45 175 case "mceTableInsertRowBefore":
bgneal@45 176 case "mceTableInsertRowAfter":
bgneal@45 177 case "mceTableDeleteRow":
bgneal@45 178 case "mceTableInsertColBefore":
bgneal@45 179 case "mceTableInsertColAfter":
bgneal@45 180 case "mceTableDeleteCol":
bgneal@45 181 case "mceTableCutRow":
bgneal@45 182 case "mceTableCopyRow":
bgneal@45 183 case "mceTablePasteRowBefore":
bgneal@45 184 case "mceTablePasteRowAfter":
bgneal@45 185 case "mceTableDelete":
bgneal@45 186 ed.execCommand('mceBeginUndoLevel');
bgneal@45 187 this._doExecCommand(cmd, ui, val);
bgneal@45 188 ed.execCommand('mceEndUndoLevel');
bgneal@45 189
bgneal@45 190 return true;
bgneal@45 191 }
bgneal@45 192
bgneal@45 193 // Pass to next handler in chain
bgneal@45 194 return false;
bgneal@45 195 },
bgneal@45 196
bgneal@45 197 getInfo : function() {
bgneal@45 198 return {
bgneal@45 199 longname : 'Tables',
bgneal@45 200 author : 'Moxiecode Systems AB',
bgneal@45 201 authorurl : 'http://tinymce.moxiecode.com',
bgneal@45 202 infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/table',
bgneal@45 203 version : tinymce.majorVersion + "." + tinymce.minorVersion
bgneal@45 204 };
bgneal@45 205 },
bgneal@45 206
bgneal@45 207 // Private plugin internal methods
bgneal@45 208
bgneal@45 209 /**
bgneal@45 210 * Executes the table commands.
bgneal@45 211 */
bgneal@45 212 _doExecCommand : function(command, user_interface, value) {
bgneal@45 213 var inst = this.editor, ed = inst, url = this.url;
bgneal@45 214 var focusElm = inst.selection.getNode();
bgneal@45 215 var trElm = inst.dom.getParent(focusElm, "tr");
bgneal@45 216 var tdElm = inst.dom.getParent(focusElm, "td,th");
bgneal@45 217 var tableElm = inst.dom.getParent(focusElm, "table");
bgneal@45 218 var doc = inst.contentWindow.document;
bgneal@45 219 var tableBorder = tableElm ? tableElm.getAttribute("border") : "";
bgneal@45 220
bgneal@45 221 // Get first TD if no TD found
bgneal@45 222 if (trElm && tdElm == null)
bgneal@45 223 tdElm = trElm.cells[0];
bgneal@45 224
bgneal@45 225 function inArray(ar, v) {
bgneal@45 226 for (var i=0; i<ar.length; i++) {
bgneal@45 227 // Is array
bgneal@45 228 if (ar[i].length > 0 && inArray(ar[i], v))
bgneal@45 229 return true;
bgneal@45 230
bgneal@45 231 // Found value
bgneal@45 232 if (ar[i] == v)
bgneal@45 233 return true;
bgneal@45 234 }
bgneal@45 235
bgneal@45 236 return false;
bgneal@45 237 }
bgneal@45 238
bgneal@45 239 function select(dx, dy) {
bgneal@45 240 var td;
bgneal@45 241
bgneal@45 242 grid = getTableGrid(tableElm);
bgneal@45 243 dx = dx || 0;
bgneal@45 244 dy = dy || 0;
bgneal@45 245 dx = Math.max(cpos.cellindex + dx, 0);
bgneal@45 246 dy = Math.max(cpos.rowindex + dy, 0);
bgneal@45 247
bgneal@45 248 // Recalculate grid and select
bgneal@45 249 inst.execCommand('mceRepaint');
bgneal@45 250 td = getCell(grid, dy, dx);
bgneal@45 251
bgneal@45 252 if (td) {
bgneal@45 253 inst.selection.select(td.firstChild || td);
bgneal@45 254 inst.selection.collapse(1);
bgneal@45 255 }
bgneal@45 256 };
bgneal@45 257
bgneal@45 258 function makeTD() {
bgneal@45 259 var newTD = doc.createElement("td");
bgneal@45 260
bgneal@45 261 if (!tinymce.isIE)
bgneal@45 262 newTD.innerHTML = '<br mce_bogus="1"/>';
bgneal@45 263 }
bgneal@45 264
bgneal@45 265 function getColRowSpan(td) {
bgneal@45 266 var colspan = inst.dom.getAttrib(td, "colspan");
bgneal@45 267 var rowspan = inst.dom.getAttrib(td, "rowspan");
bgneal@45 268
bgneal@45 269 colspan = colspan == "" ? 1 : parseInt(colspan);
bgneal@45 270 rowspan = rowspan == "" ? 1 : parseInt(rowspan);
bgneal@45 271
bgneal@45 272 return {colspan : colspan, rowspan : rowspan};
bgneal@45 273 }
bgneal@45 274
bgneal@45 275 function getCellPos(grid, td) {
bgneal@45 276 var x, y;
bgneal@45 277
bgneal@45 278 for (y=0; y<grid.length; y++) {
bgneal@45 279 for (x=0; x<grid[y].length; x++) {
bgneal@45 280 if (grid[y][x] == td)
bgneal@45 281 return {cellindex : x, rowindex : y};
bgneal@45 282 }
bgneal@45 283 }
bgneal@45 284
bgneal@45 285 return null;
bgneal@45 286 }
bgneal@45 287
bgneal@45 288 function getCell(grid, row, col) {
bgneal@45 289 if (grid[row] && grid[row][col])
bgneal@45 290 return grid[row][col];
bgneal@45 291
bgneal@45 292 return null;
bgneal@45 293 }
bgneal@45 294
bgneal@45 295 function getNextCell(table, cell) {
bgneal@45 296 var cells = [], x = 0, i, j, cell, nextCell;
bgneal@45 297
bgneal@45 298 for (i = 0; i < table.rows.length; i++)
bgneal@45 299 for (j = 0; j < table.rows[i].cells.length; j++, x++)
bgneal@45 300 cells[x] = table.rows[i].cells[j];
bgneal@45 301
bgneal@45 302 for (i = 0; i < cells.length; i++)
bgneal@45 303 if (cells[i] == cell)
bgneal@45 304 if (nextCell = cells[i+1])
bgneal@45 305 return nextCell;
bgneal@45 306 }
bgneal@45 307
bgneal@45 308 function getTableGrid(table) {
bgneal@45 309 var grid = [], rows = table.rows, x, y, td, sd, xstart, x2, y2;
bgneal@45 310
bgneal@45 311 for (y=0; y<rows.length; y++) {
bgneal@45 312 for (x=0; x<rows[y].cells.length; x++) {
bgneal@45 313 td = rows[y].cells[x];
bgneal@45 314 sd = getColRowSpan(td);
bgneal@45 315
bgneal@45 316 // All ready filled
bgneal@45 317 for (xstart = x; grid[y] && grid[y][xstart]; xstart++) ;
bgneal@45 318
bgneal@45 319 // Fill box
bgneal@45 320 for (y2=y; y2<y+sd['rowspan']; y2++) {
bgneal@45 321 if (!grid[y2])
bgneal@45 322 grid[y2] = [];
bgneal@45 323
bgneal@45 324 for (x2=xstart; x2<xstart+sd['colspan']; x2++)
bgneal@45 325 grid[y2][x2] = td;
bgneal@45 326 }
bgneal@45 327 }
bgneal@45 328 }
bgneal@45 329
bgneal@45 330 return grid;
bgneal@45 331 }
bgneal@45 332
bgneal@45 333 function trimRow(table, tr, td, new_tr) {
bgneal@45 334 var grid = getTableGrid(table), cpos = getCellPos(grid, td);
bgneal@45 335 var cells, lastElm;
bgneal@45 336
bgneal@45 337 // Time to crop away some
bgneal@45 338 if (new_tr.cells.length != tr.childNodes.length) {
bgneal@45 339 cells = tr.childNodes;
bgneal@45 340 lastElm = null;
bgneal@45 341
bgneal@45 342 for (var x=0; td = getCell(grid, cpos.rowindex, x); x++) {
bgneal@45 343 var remove = true;
bgneal@45 344 var sd = getColRowSpan(td);
bgneal@45 345
bgneal@45 346 // Remove due to rowspan
bgneal@45 347 if (inArray(cells, td)) {
bgneal@45 348 new_tr.childNodes[x]._delete = true;
bgneal@45 349 } else if ((lastElm == null || td != lastElm) && sd.colspan > 1) { // Remove due to colspan
bgneal@45 350 for (var i=x; i<x+td.colSpan; i++)
bgneal@45 351 new_tr.childNodes[i]._delete = true;
bgneal@45 352 }
bgneal@45 353
bgneal@45 354 if ((lastElm == null || td != lastElm) && sd.rowspan > 1)
bgneal@45 355 td.rowSpan = sd.rowspan + 1;
bgneal@45 356
bgneal@45 357 lastElm = td;
bgneal@45 358 }
bgneal@45 359
bgneal@45 360 deleteMarked(tableElm);
bgneal@45 361 }
bgneal@45 362 }
bgneal@45 363
bgneal@45 364 function prevElm(node, name) {
bgneal@45 365 while ((node = node.previousSibling) != null) {
bgneal@45 366 if (node.nodeName == name)
bgneal@45 367 return node;
bgneal@45 368 }
bgneal@45 369
bgneal@45 370 return null;
bgneal@45 371 }
bgneal@45 372
bgneal@45 373 function nextElm(node, names) {
bgneal@45 374 var namesAr = names.split(',');
bgneal@45 375
bgneal@45 376 while ((node = node.nextSibling) != null) {
bgneal@45 377 for (var i=0; i<namesAr.length; i++) {
bgneal@45 378 if (node.nodeName.toLowerCase() == namesAr[i].toLowerCase() )
bgneal@45 379 return node;
bgneal@45 380 }
bgneal@45 381 }
bgneal@45 382
bgneal@45 383 return null;
bgneal@45 384 }
bgneal@45 385
bgneal@45 386 function deleteMarked(tbl) {
bgneal@45 387 if (tbl.rows == 0)
bgneal@45 388 return;
bgneal@45 389
bgneal@45 390 var tr = tbl.rows[0];
bgneal@45 391 do {
bgneal@45 392 var next = nextElm(tr, "TR");
bgneal@45 393
bgneal@45 394 // Delete row
bgneal@45 395 if (tr._delete) {
bgneal@45 396 tr.parentNode.removeChild(tr);
bgneal@45 397 continue;
bgneal@45 398 }
bgneal@45 399
bgneal@45 400 // Delete cells
bgneal@45 401 var td = tr.cells[0];
bgneal@45 402 if (td.cells > 1) {
bgneal@45 403 do {
bgneal@45 404 var nexttd = nextElm(td, "TD,TH");
bgneal@45 405
bgneal@45 406 if (td._delete)
bgneal@45 407 td.parentNode.removeChild(td);
bgneal@45 408 } while ((td = nexttd) != null);
bgneal@45 409 }
bgneal@45 410 } while ((tr = next) != null);
bgneal@45 411 }
bgneal@45 412
bgneal@45 413 function addRows(td_elm, tr_elm, rowspan) {
bgneal@45 414 // Add rows
bgneal@45 415 td_elm.rowSpan = 1;
bgneal@45 416 var trNext = nextElm(tr_elm, "TR");
bgneal@45 417 for (var i=1; i<rowspan && trNext; i++) {
bgneal@45 418 var newTD = doc.createElement("td");
bgneal@45 419
bgneal@45 420 if (!tinymce.isIE)
bgneal@45 421 newTD.innerHTML = '<br mce_bogus="1"/>';
bgneal@45 422
bgneal@45 423 if (tinymce.isIE)
bgneal@45 424 trNext.insertBefore(newTD, trNext.cells(td_elm.cellIndex));
bgneal@45 425 else
bgneal@45 426 trNext.insertBefore(newTD, trNext.cells[td_elm.cellIndex]);
bgneal@45 427
bgneal@45 428 trNext = nextElm(trNext, "TR");
bgneal@45 429 }
bgneal@45 430 }
bgneal@45 431
bgneal@45 432 function copyRow(doc, table, tr) {
bgneal@45 433 var grid = getTableGrid(table);
bgneal@45 434 var newTR = tr.cloneNode(false);
bgneal@45 435 var cpos = getCellPos(grid, tr.cells[0]);
bgneal@45 436 var lastCell = null;
bgneal@45 437 var tableBorder = inst.dom.getAttrib(table, "border");
bgneal@45 438 var tdElm = null;
bgneal@45 439
bgneal@45 440 for (var x=0; tdElm = getCell(grid, cpos.rowindex, x); x++) {
bgneal@45 441 var newTD = null;
bgneal@45 442
bgneal@45 443 if (lastCell != tdElm) {
bgneal@45 444 for (var i=0; i<tr.cells.length; i++) {
bgneal@45 445 if (tdElm == tr.cells[i]) {
bgneal@45 446 newTD = tdElm.cloneNode(true);
bgneal@45 447 break;
bgneal@45 448 }
bgneal@45 449 }
bgneal@45 450 }
bgneal@45 451
bgneal@45 452 if (newTD == null) {
bgneal@45 453 newTD = doc.createElement("td");
bgneal@45 454
bgneal@45 455 if (!tinymce.isIE)
bgneal@45 456 newTD.innerHTML = '<br mce_bogus="1"/>';
bgneal@45 457 }
bgneal@45 458
bgneal@45 459 // Reset col/row span
bgneal@45 460 newTD.colSpan = 1;
bgneal@45 461 newTD.rowSpan = 1;
bgneal@45 462
bgneal@45 463 newTR.appendChild(newTD);
bgneal@45 464
bgneal@45 465 lastCell = tdElm;
bgneal@45 466 }
bgneal@45 467
bgneal@45 468 return newTR;
bgneal@45 469 }
bgneal@45 470
bgneal@45 471 // ---- Commands -----
bgneal@45 472
bgneal@45 473 // Handle commands
bgneal@45 474 switch (command) {
bgneal@45 475 case "mceTableMoveToNextRow":
bgneal@45 476 var nextCell = getNextCell(tableElm, tdElm);
bgneal@45 477
bgneal@45 478 if (!nextCell) {
bgneal@45 479 inst.execCommand("mceTableInsertRowAfter", tdElm);
bgneal@45 480 nextCell = getNextCell(tableElm, tdElm);
bgneal@45 481 }
bgneal@45 482
bgneal@45 483 inst.selection.select(nextCell);
bgneal@45 484 inst.selection.collapse(true);
bgneal@45 485
bgneal@45 486 return true;
bgneal@45 487
bgneal@45 488 case "mceTableRowProps":
bgneal@45 489 if (trElm == null)
bgneal@45 490 return true;
bgneal@45 491
bgneal@45 492 if (user_interface) {
bgneal@45 493 inst.windowManager.open({
bgneal@45 494 url : url + '/row.htm',
bgneal@45 495 width : 400 + parseInt(inst.getLang('table.rowprops_delta_width', 0)),
bgneal@45 496 height : 295 + parseInt(inst.getLang('table.rowprops_delta_height', 0)),
bgneal@45 497 inline : 1
bgneal@45 498 }, {
bgneal@45 499 plugin_url : url
bgneal@45 500 });
bgneal@45 501 }
bgneal@45 502
bgneal@45 503 return true;
bgneal@45 504
bgneal@45 505 case "mceTableCellProps":
bgneal@45 506 if (tdElm == null)
bgneal@45 507 return true;
bgneal@45 508
bgneal@45 509 if (user_interface) {
bgneal@45 510 inst.windowManager.open({
bgneal@45 511 url : url + '/cell.htm',
bgneal@45 512 width : 400 + parseInt(inst.getLang('table.cellprops_delta_width', 0)),
bgneal@45 513 height : 295 + parseInt(inst.getLang('table.cellprops_delta_height', 0)),
bgneal@45 514 inline : 1
bgneal@45 515 }, {
bgneal@45 516 plugin_url : url
bgneal@45 517 });
bgneal@45 518 }
bgneal@45 519
bgneal@45 520 return true;
bgneal@45 521
bgneal@45 522 case "mceInsertTable":
bgneal@45 523 if (user_interface) {
bgneal@45 524 inst.windowManager.open({
bgneal@45 525 url : url + '/table.htm',
bgneal@45 526 width : 400 + parseInt(inst.getLang('table.table_delta_width', 0)),
bgneal@45 527 height : 320 + parseInt(inst.getLang('table.table_delta_height', 0)),
bgneal@45 528 inline : 1
bgneal@45 529 }, {
bgneal@45 530 plugin_url : url,
bgneal@45 531 action : value ? value.action : 0
bgneal@45 532 });
bgneal@45 533 }
bgneal@45 534
bgneal@45 535 return true;
bgneal@45 536
bgneal@45 537 case "mceTableDelete":
bgneal@45 538 var table = inst.dom.getParent(inst.selection.getNode(), "table");
bgneal@45 539 if (table) {
bgneal@45 540 table.parentNode.removeChild(table);
bgneal@45 541 inst.execCommand('mceRepaint');
bgneal@45 542 }
bgneal@45 543 return true;
bgneal@45 544
bgneal@45 545 case "mceTableSplitCells":
bgneal@45 546 case "mceTableMergeCells":
bgneal@45 547 case "mceTableInsertRowBefore":
bgneal@45 548 case "mceTableInsertRowAfter":
bgneal@45 549 case "mceTableDeleteRow":
bgneal@45 550 case "mceTableInsertColBefore":
bgneal@45 551 case "mceTableInsertColAfter":
bgneal@45 552 case "mceTableDeleteCol":
bgneal@45 553 case "mceTableCutRow":
bgneal@45 554 case "mceTableCopyRow":
bgneal@45 555 case "mceTablePasteRowBefore":
bgneal@45 556 case "mceTablePasteRowAfter":
bgneal@45 557 // No table just return (invalid command)
bgneal@45 558 if (!tableElm)
bgneal@45 559 return true;
bgneal@45 560
bgneal@45 561 // Table has a tbody use that reference
bgneal@45 562 // Changed logic by ApTest 2005.07.12 (www.aptest.com)
bgneal@45 563 // Now lookk at the focused element and take its parentNode. That will be a tbody or a table.
bgneal@45 564 if (trElm && tableElm != trElm.parentNode)
bgneal@45 565 tableElm = trElm.parentNode;
bgneal@45 566
bgneal@45 567 if (tableElm && trElm) {
bgneal@45 568 switch (command) {
bgneal@45 569 case "mceTableCutRow":
bgneal@45 570 if (!trElm || !tdElm)
bgneal@45 571 return true;
bgneal@45 572
bgneal@45 573 inst.tableRowClipboard = copyRow(doc, tableElm, trElm);
bgneal@45 574 inst.execCommand("mceTableDeleteRow");
bgneal@45 575 break;
bgneal@45 576
bgneal@45 577 case "mceTableCopyRow":
bgneal@45 578 if (!trElm || !tdElm)
bgneal@45 579 return true;
bgneal@45 580
bgneal@45 581 inst.tableRowClipboard = copyRow(doc, tableElm, trElm);
bgneal@45 582 break;
bgneal@45 583
bgneal@45 584 case "mceTablePasteRowBefore":
bgneal@45 585 if (!trElm || !tdElm)
bgneal@45 586 return true;
bgneal@45 587
bgneal@45 588 var newTR = inst.tableRowClipboard.cloneNode(true);
bgneal@45 589
bgneal@45 590 var prevTR = prevElm(trElm, "TR");
bgneal@45 591 if (prevTR != null)
bgneal@45 592 trimRow(tableElm, prevTR, prevTR.cells[0], newTR);
bgneal@45 593
bgneal@45 594 trElm.parentNode.insertBefore(newTR, trElm);
bgneal@45 595 break;
bgneal@45 596
bgneal@45 597 case "mceTablePasteRowAfter":
bgneal@45 598 if (!trElm || !tdElm)
bgneal@45 599 return true;
bgneal@45 600
bgneal@45 601 var nextTR = nextElm(trElm, "TR");
bgneal@45 602 var newTR = inst.tableRowClipboard.cloneNode(true);
bgneal@45 603
bgneal@45 604 trimRow(tableElm, trElm, tdElm, newTR);
bgneal@45 605
bgneal@45 606 if (nextTR == null)
bgneal@45 607 trElm.parentNode.appendChild(newTR);
bgneal@45 608 else
bgneal@45 609 nextTR.parentNode.insertBefore(newTR, nextTR);
bgneal@45 610
bgneal@45 611 break;
bgneal@45 612
bgneal@45 613 case "mceTableInsertRowBefore":
bgneal@45 614 if (!trElm || !tdElm)
bgneal@45 615 return true;
bgneal@45 616
bgneal@45 617 var grid = getTableGrid(tableElm);
bgneal@45 618 var cpos = getCellPos(grid, tdElm);
bgneal@45 619 var newTR = doc.createElement("tr");
bgneal@45 620 var lastTDElm = null;
bgneal@45 621
bgneal@45 622 cpos.rowindex--;
bgneal@45 623 if (cpos.rowindex < 0)
bgneal@45 624 cpos.rowindex = 0;
bgneal@45 625
bgneal@45 626 // Create cells
bgneal@45 627 for (var x=0; tdElm = getCell(grid, cpos.rowindex, x); x++) {
bgneal@45 628 if (tdElm != lastTDElm) {
bgneal@45 629 var sd = getColRowSpan(tdElm);
bgneal@45 630
bgneal@45 631 if (sd['rowspan'] == 1) {
bgneal@45 632 var newTD = doc.createElement("td");
bgneal@45 633
bgneal@45 634 if (!tinymce.isIE)
bgneal@45 635 newTD.innerHTML = '<br mce_bogus="1"/>';
bgneal@45 636
bgneal@45 637 newTD.colSpan = tdElm.colSpan;
bgneal@45 638
bgneal@45 639 newTR.appendChild(newTD);
bgneal@45 640 } else
bgneal@45 641 tdElm.rowSpan = sd['rowspan'] + 1;
bgneal@45 642
bgneal@45 643 lastTDElm = tdElm;
bgneal@45 644 }
bgneal@45 645 }
bgneal@45 646
bgneal@45 647 trElm.parentNode.insertBefore(newTR, trElm);
bgneal@45 648 select(0, 1);
bgneal@45 649 break;
bgneal@45 650
bgneal@45 651 case "mceTableInsertRowAfter":
bgneal@45 652 if (!trElm || !tdElm)
bgneal@45 653 return true;
bgneal@45 654
bgneal@45 655 var grid = getTableGrid(tableElm);
bgneal@45 656 var cpos = getCellPos(grid, tdElm);
bgneal@45 657 var newTR = doc.createElement("tr");
bgneal@45 658 var lastTDElm = null;
bgneal@45 659
bgneal@45 660 // Create cells
bgneal@45 661 for (var x=0; tdElm = getCell(grid, cpos.rowindex, x); x++) {
bgneal@45 662 if (tdElm != lastTDElm) {
bgneal@45 663 var sd = getColRowSpan(tdElm);
bgneal@45 664
bgneal@45 665 if (sd['rowspan'] == 1) {
bgneal@45 666 var newTD = doc.createElement("td");
bgneal@45 667
bgneal@45 668 if (!tinymce.isIE)
bgneal@45 669 newTD.innerHTML = '<br mce_bogus="1"/>';
bgneal@45 670
bgneal@45 671 newTD.colSpan = tdElm.colSpan;
bgneal@45 672
bgneal@45 673 newTR.appendChild(newTD);
bgneal@45 674 } else
bgneal@45 675 tdElm.rowSpan = sd['rowspan'] + 1;
bgneal@45 676
bgneal@45 677 lastTDElm = tdElm;
bgneal@45 678 }
bgneal@45 679 }
bgneal@45 680
bgneal@45 681 if (newTR.hasChildNodes()) {
bgneal@45 682 var nextTR = nextElm(trElm, "TR");
bgneal@45 683 if (nextTR)
bgneal@45 684 nextTR.parentNode.insertBefore(newTR, nextTR);
bgneal@45 685 else
bgneal@45 686 tableElm.appendChild(newTR);
bgneal@45 687 }
bgneal@45 688
bgneal@45 689 select(0, 1);
bgneal@45 690 break;
bgneal@45 691
bgneal@45 692 case "mceTableDeleteRow":
bgneal@45 693 if (!trElm || !tdElm)
bgneal@45 694 return true;
bgneal@45 695
bgneal@45 696 var grid = getTableGrid(tableElm);
bgneal@45 697 var cpos = getCellPos(grid, tdElm);
bgneal@45 698
bgneal@45 699 // Only one row, remove whole table
bgneal@45 700 if (grid.length == 1 && tableElm.nodeName == 'TBODY') {
bgneal@45 701 inst.dom.remove(inst.dom.getParent(tableElm, "table"));
bgneal@45 702 return true;
bgneal@45 703 }
bgneal@45 704
bgneal@45 705 // Move down row spanned cells
bgneal@45 706 var cells = trElm.cells;
bgneal@45 707 var nextTR = nextElm(trElm, "TR");
bgneal@45 708 for (var x=0; x<cells.length; x++) {
bgneal@45 709 if (cells[x].rowSpan > 1) {
bgneal@45 710 var newTD = cells[x].cloneNode(true);
bgneal@45 711 var sd = getColRowSpan(cells[x]);
bgneal@45 712
bgneal@45 713 newTD.rowSpan = sd.rowspan - 1;
bgneal@45 714
bgneal@45 715 var nextTD = nextTR.cells[x];
bgneal@45 716
bgneal@45 717 if (nextTD == null)
bgneal@45 718 nextTR.appendChild(newTD);
bgneal@45 719 else
bgneal@45 720 nextTR.insertBefore(newTD, nextTD);
bgneal@45 721 }
bgneal@45 722 }
bgneal@45 723
bgneal@45 724 // Delete cells
bgneal@45 725 var lastTDElm = null;
bgneal@45 726 for (var x=0; tdElm = getCell(grid, cpos.rowindex, x); x++) {
bgneal@45 727 if (tdElm != lastTDElm) {
bgneal@45 728 var sd = getColRowSpan(tdElm);
bgneal@45 729
bgneal@45 730 if (sd.rowspan > 1) {
bgneal@45 731 tdElm.rowSpan = sd.rowspan - 1;
bgneal@45 732 } else {
bgneal@45 733 trElm = tdElm.parentNode;
bgneal@45 734
bgneal@45 735 if (trElm.parentNode)
bgneal@45 736 trElm._delete = true;
bgneal@45 737 }
bgneal@45 738
bgneal@45 739 lastTDElm = tdElm;
bgneal@45 740 }
bgneal@45 741 }
bgneal@45 742
bgneal@45 743 deleteMarked(tableElm);
bgneal@45 744
bgneal@45 745 select(0, -1);
bgneal@45 746 break;
bgneal@45 747
bgneal@45 748 case "mceTableInsertColBefore":
bgneal@45 749 if (!trElm || !tdElm)
bgneal@45 750 return true;
bgneal@45 751
bgneal@45 752 var grid = getTableGrid(inst.dom.getParent(tableElm, "table"));
bgneal@45 753 var cpos = getCellPos(grid, tdElm);
bgneal@45 754 var lastTDElm = null;
bgneal@45 755
bgneal@45 756 for (var y=0; tdElm = getCell(grid, y, cpos.cellindex); y++) {
bgneal@45 757 if (tdElm != lastTDElm) {
bgneal@45 758 var sd = getColRowSpan(tdElm);
bgneal@45 759
bgneal@45 760 if (sd['colspan'] == 1) {
bgneal@45 761 var newTD = doc.createElement(tdElm.nodeName);
bgneal@45 762
bgneal@45 763 if (!tinymce.isIE)
bgneal@45 764 newTD.innerHTML = '<br mce_bogus="1"/>';
bgneal@45 765
bgneal@45 766 newTD.rowSpan = tdElm.rowSpan;
bgneal@45 767
bgneal@45 768 tdElm.parentNode.insertBefore(newTD, tdElm);
bgneal@45 769 } else
bgneal@45 770 tdElm.colSpan++;
bgneal@45 771
bgneal@45 772 lastTDElm = tdElm;
bgneal@45 773 }
bgneal@45 774 }
bgneal@45 775
bgneal@45 776 select();
bgneal@45 777 break;
bgneal@45 778
bgneal@45 779 case "mceTableInsertColAfter":
bgneal@45 780 if (!trElm || !tdElm)
bgneal@45 781 return true;
bgneal@45 782
bgneal@45 783 var grid = getTableGrid(inst.dom.getParent(tableElm, "table"));
bgneal@45 784 var cpos = getCellPos(grid, tdElm);
bgneal@45 785 var lastTDElm = null;
bgneal@45 786
bgneal@45 787 for (var y=0; tdElm = getCell(grid, y, cpos.cellindex); y++) {
bgneal@45 788 if (tdElm != lastTDElm) {
bgneal@45 789 var sd = getColRowSpan(tdElm);
bgneal@45 790
bgneal@45 791 if (sd['colspan'] == 1) {
bgneal@45 792 var newTD = doc.createElement(tdElm.nodeName);
bgneal@45 793
bgneal@45 794 if (!tinymce.isIE)
bgneal@45 795 newTD.innerHTML = '<br mce_bogus="1"/>';
bgneal@45 796
bgneal@45 797 newTD.rowSpan = tdElm.rowSpan;
bgneal@45 798
bgneal@45 799 var nextTD = nextElm(tdElm, "TD,TH");
bgneal@45 800 if (nextTD == null)
bgneal@45 801 tdElm.parentNode.appendChild(newTD);
bgneal@45 802 else
bgneal@45 803 nextTD.parentNode.insertBefore(newTD, nextTD);
bgneal@45 804 } else
bgneal@45 805 tdElm.colSpan++;
bgneal@45 806
bgneal@45 807 lastTDElm = tdElm;
bgneal@45 808 }
bgneal@45 809 }
bgneal@45 810
bgneal@45 811 select(1);
bgneal@45 812 break;
bgneal@45 813
bgneal@45 814 case "mceTableDeleteCol":
bgneal@45 815 if (!trElm || !tdElm)
bgneal@45 816 return true;
bgneal@45 817
bgneal@45 818 var grid = getTableGrid(tableElm);
bgneal@45 819 var cpos = getCellPos(grid, tdElm);
bgneal@45 820 var lastTDElm = null;
bgneal@45 821
bgneal@45 822 // Only one col, remove whole table
bgneal@45 823 if ((grid.length > 1 && grid[0].length <= 1) && tableElm.nodeName == 'TBODY') {
bgneal@45 824 inst.dom.remove(inst.dom.getParent(tableElm, "table"));
bgneal@45 825 return true;
bgneal@45 826 }
bgneal@45 827
bgneal@45 828 // Delete cells
bgneal@45 829 for (var y=0; tdElm = getCell(grid, y, cpos.cellindex); y++) {
bgneal@45 830 if (tdElm != lastTDElm) {
bgneal@45 831 var sd = getColRowSpan(tdElm);
bgneal@45 832
bgneal@45 833 if (sd['colspan'] > 1)
bgneal@45 834 tdElm.colSpan = sd['colspan'] - 1;
bgneal@45 835 else {
bgneal@45 836 if (tdElm.parentNode)
bgneal@45 837 tdElm.parentNode.removeChild(tdElm);
bgneal@45 838 }
bgneal@45 839
bgneal@45 840 lastTDElm = tdElm;
bgneal@45 841 }
bgneal@45 842 }
bgneal@45 843
bgneal@45 844 select(-1);
bgneal@45 845 break;
bgneal@45 846
bgneal@45 847 case "mceTableSplitCells":
bgneal@45 848 if (!trElm || !tdElm)
bgneal@45 849 return true;
bgneal@45 850
bgneal@45 851 var spandata = getColRowSpan(tdElm);
bgneal@45 852
bgneal@45 853 var colspan = spandata["colspan"];
bgneal@45 854 var rowspan = spandata["rowspan"];
bgneal@45 855
bgneal@45 856 // Needs splitting
bgneal@45 857 if (colspan > 1 || rowspan > 1) {
bgneal@45 858 // Generate cols
bgneal@45 859 tdElm.colSpan = 1;
bgneal@45 860 for (var i=1; i<colspan; i++) {
bgneal@45 861 var newTD = doc.createElement("td");
bgneal@45 862
bgneal@45 863 if (!tinymce.isIE)
bgneal@45 864 newTD.innerHTML = '<br mce_bogus="1"/>';
bgneal@45 865
bgneal@45 866 trElm.insertBefore(newTD, nextElm(tdElm, "TD,TH"));
bgneal@45 867
bgneal@45 868 if (rowspan > 1)
bgneal@45 869 addRows(newTD, trElm, rowspan);
bgneal@45 870 }
bgneal@45 871
bgneal@45 872 addRows(tdElm, trElm, rowspan);
bgneal@45 873 }
bgneal@45 874
bgneal@45 875 // Apply visual aids
bgneal@45 876 tableElm = inst.dom.getParent(inst.selection.getNode(), "table");
bgneal@45 877 break;
bgneal@45 878
bgneal@45 879 case "mceTableMergeCells":
bgneal@45 880 var rows = [];
bgneal@45 881 var sel = inst.selection.getSel();
bgneal@45 882 var grid = getTableGrid(tableElm);
bgneal@45 883
bgneal@45 884 if (tinymce.isIE || sel.rangeCount == 1) {
bgneal@45 885 if (user_interface) {
bgneal@45 886 // Setup template
bgneal@45 887 var sp = getColRowSpan(tdElm);
bgneal@45 888
bgneal@45 889 inst.windowManager.open({
bgneal@45 890 url : url + '/merge_cells.htm',
bgneal@45 891 width : 240 + parseInt(inst.getLang('table.merge_cells_delta_width', 0)),
bgneal@45 892 height : 110 + parseInt(inst.getLang('table.merge_cells_delta_height', 0)),
bgneal@45 893 inline : 1
bgneal@45 894 }, {
bgneal@45 895 action : "update",
bgneal@45 896 numcols : sp.colspan,
bgneal@45 897 numrows : sp.rowspan,
bgneal@45 898 plugin_url : url
bgneal@45 899 });
bgneal@45 900
bgneal@45 901 return true;
bgneal@45 902 } else {
bgneal@45 903 var numRows = parseInt(value['numrows']);
bgneal@45 904 var numCols = parseInt(value['numcols']);
bgneal@45 905 var cpos = getCellPos(grid, tdElm);
bgneal@45 906
bgneal@45 907 if (("" + numRows) == "NaN")
bgneal@45 908 numRows = 1;
bgneal@45 909
bgneal@45 910 if (("" + numCols) == "NaN")
bgneal@45 911 numCols = 1;
bgneal@45 912
bgneal@45 913 // Get rows and cells
bgneal@45 914 var tRows = tableElm.rows;
bgneal@45 915 for (var y=cpos.rowindex; y<grid.length; y++) {
bgneal@45 916 var rowCells = [];
bgneal@45 917
bgneal@45 918 for (var x=cpos.cellindex; x<grid[y].length; x++) {
bgneal@45 919 var td = getCell(grid, y, x);
bgneal@45 920
bgneal@45 921 if (td && !inArray(rows, td) && !inArray(rowCells, td)) {
bgneal@45 922 var cp = getCellPos(grid, td);
bgneal@45 923
bgneal@45 924 // Within range
bgneal@45 925 if (cp.cellindex < cpos.cellindex+numCols && cp.rowindex < cpos.rowindex+numRows)
bgneal@45 926 rowCells[rowCells.length] = td;
bgneal@45 927 }
bgneal@45 928 }
bgneal@45 929
bgneal@45 930 if (rowCells.length > 0)
bgneal@45 931 rows[rows.length] = rowCells;
bgneal@45 932
bgneal@45 933 var td = getCell(grid, cpos.rowindex, cpos.cellindex);
bgneal@45 934 each(ed.dom.select('br', td), function(e, i) {
bgneal@45 935 if (i > 0 && ed.dom.getAttrib('mce_bogus'))
bgneal@45 936 ed.dom.remove(e);
bgneal@45 937 });
bgneal@45 938 }
bgneal@45 939
bgneal@45 940 //return true;
bgneal@45 941 }
bgneal@45 942 } else {
bgneal@45 943 var cells = [];
bgneal@45 944 var sel = inst.selection.getSel();
bgneal@45 945 var lastTR = null;
bgneal@45 946 var curRow = null;
bgneal@45 947 var x1 = -1, y1 = -1, x2, y2;
bgneal@45 948
bgneal@45 949 // Only one cell selected, whats the point?
bgneal@45 950 if (sel.rangeCount < 2)
bgneal@45 951 return true;
bgneal@45 952
bgneal@45 953 // Get all selected cells
bgneal@45 954 for (var i=0; i<sel.rangeCount; i++) {
bgneal@45 955 var rng = sel.getRangeAt(i);
bgneal@45 956 var tdElm = rng.startContainer.childNodes[rng.startOffset];
bgneal@45 957
bgneal@45 958 if (!tdElm)
bgneal@45 959 break;
bgneal@45 960
bgneal@45 961 if (tdElm.nodeName == "TD" || tdElm.nodeName == "TH")
bgneal@45 962 cells[cells.length] = tdElm;
bgneal@45 963 }
bgneal@45 964
bgneal@45 965 // Get rows and cells
bgneal@45 966 var tRows = tableElm.rows;
bgneal@45 967 for (var y=0; y<tRows.length; y++) {
bgneal@45 968 var rowCells = [];
bgneal@45 969
bgneal@45 970 for (var x=0; x<tRows[y].cells.length; x++) {
bgneal@45 971 var td = tRows[y].cells[x];
bgneal@45 972
bgneal@45 973 for (var i=0; i<cells.length; i++) {
bgneal@45 974 if (td == cells[i]) {
bgneal@45 975 rowCells[rowCells.length] = td;
bgneal@45 976 }
bgneal@45 977 }
bgneal@45 978 }
bgneal@45 979
bgneal@45 980 if (rowCells.length > 0)
bgneal@45 981 rows[rows.length] = rowCells;
bgneal@45 982 }
bgneal@45 983
bgneal@45 984 // Find selected cells in grid and box
bgneal@45 985 var curRow = [];
bgneal@45 986 var lastTR = null;
bgneal@45 987 for (var y=0; y<grid.length; y++) {
bgneal@45 988 for (var x=0; x<grid[y].length; x++) {
bgneal@45 989 grid[y][x]._selected = false;
bgneal@45 990
bgneal@45 991 for (var i=0; i<cells.length; i++) {
bgneal@45 992 if (grid[y][x] == cells[i]) {
bgneal@45 993 // Get start pos
bgneal@45 994 if (x1 == -1) {
bgneal@45 995 x1 = x;
bgneal@45 996 y1 = y;
bgneal@45 997 }
bgneal@45 998
bgneal@45 999 // Get end pos
bgneal@45 1000 x2 = x;
bgneal@45 1001 y2 = y;
bgneal@45 1002
bgneal@45 1003 grid[y][x]._selected = true;
bgneal@45 1004 }
bgneal@45 1005 }
bgneal@45 1006 }
bgneal@45 1007 }
bgneal@45 1008
bgneal@45 1009 // Is there gaps, if so deny
bgneal@45 1010 for (var y=y1; y<=y2; y++) {
bgneal@45 1011 for (var x=x1; x<=x2; x++) {
bgneal@45 1012 if (!grid[y][x]._selected) {
bgneal@45 1013 alert("Invalid selection for merge.");
bgneal@45 1014 return true;
bgneal@45 1015 }
bgneal@45 1016 }
bgneal@45 1017 }
bgneal@45 1018 }
bgneal@45 1019
bgneal@45 1020 // Validate selection and get total rowspan and colspan
bgneal@45 1021 var rowSpan = 1, colSpan = 1;
bgneal@45 1022
bgneal@45 1023 // Validate horizontal and get total colspan
bgneal@45 1024 var lastRowSpan = -1;
bgneal@45 1025 for (var y=0; y<rows.length; y++) {
bgneal@45 1026 var rowColSpan = 0;
bgneal@45 1027
bgneal@45 1028 for (var x=0; x<rows[y].length; x++) {
bgneal@45 1029 var sd = getColRowSpan(rows[y][x]);
bgneal@45 1030
bgneal@45 1031 rowColSpan += sd['colspan'];
bgneal@45 1032
bgneal@45 1033 if (lastRowSpan != -1 && sd['rowspan'] != lastRowSpan) {
bgneal@45 1034 alert("Invalid selection for merge.");
bgneal@45 1035 return true;
bgneal@45 1036 }
bgneal@45 1037
bgneal@45 1038 lastRowSpan = sd['rowspan'];
bgneal@45 1039 }
bgneal@45 1040
bgneal@45 1041 if (rowColSpan > colSpan)
bgneal@45 1042 colSpan = rowColSpan;
bgneal@45 1043
bgneal@45 1044 lastRowSpan = -1;
bgneal@45 1045 }
bgneal@45 1046
bgneal@45 1047 // Validate vertical and get total rowspan
bgneal@45 1048 var lastColSpan = -1;
bgneal@45 1049 for (var x=0; x<rows[0].length; x++) {
bgneal@45 1050 var colRowSpan = 0;
bgneal@45 1051
bgneal@45 1052 for (var y=0; y<rows.length; y++) {
bgneal@45 1053 var sd = getColRowSpan(rows[y][x]);
bgneal@45 1054
bgneal@45 1055 colRowSpan += sd['rowspan'];
bgneal@45 1056
bgneal@45 1057 if (lastColSpan != -1 && sd['colspan'] != lastColSpan) {
bgneal@45 1058 alert("Invalid selection for merge.");
bgneal@45 1059 return true;
bgneal@45 1060 }
bgneal@45 1061
bgneal@45 1062 lastColSpan = sd['colspan'];
bgneal@45 1063 }
bgneal@45 1064
bgneal@45 1065 if (colRowSpan > rowSpan)
bgneal@45 1066 rowSpan = colRowSpan;
bgneal@45 1067
bgneal@45 1068 lastColSpan = -1;
bgneal@45 1069 }
bgneal@45 1070
bgneal@45 1071 // Setup td
bgneal@45 1072 tdElm = rows[0][0];
bgneal@45 1073 tdElm.rowSpan = rowSpan;
bgneal@45 1074 tdElm.colSpan = colSpan;
bgneal@45 1075
bgneal@45 1076 // Merge cells
bgneal@45 1077 for (var y=0; y<rows.length; y++) {
bgneal@45 1078 for (var x=0; x<rows[y].length; x++) {
bgneal@45 1079 var html = rows[y][x].innerHTML;
bgneal@45 1080 var chk = html.replace(/[ \t\r\n]/g, "");
bgneal@45 1081
bgneal@45 1082 if (chk != "<br/>" && chk != "<br>" && chk != '<br mce_bogus="1"/>' && (x+y > 0))
bgneal@45 1083 tdElm.innerHTML += html;
bgneal@45 1084
bgneal@45 1085 // Not current cell
bgneal@45 1086 if (rows[y][x] != tdElm && !rows[y][x]._deleted) {
bgneal@45 1087 var cpos = getCellPos(grid, rows[y][x]);
bgneal@45 1088 var tr = rows[y][x].parentNode;
bgneal@45 1089
bgneal@45 1090 tr.removeChild(rows[y][x]);
bgneal@45 1091 rows[y][x]._deleted = true;
bgneal@45 1092
bgneal@45 1093 // Empty TR, remove it
bgneal@45 1094 if (!tr.hasChildNodes()) {
bgneal@45 1095 tr.parentNode.removeChild(tr);
bgneal@45 1096
bgneal@45 1097 var lastCell = null;
bgneal@45 1098 for (var x=0; cellElm = getCell(grid, cpos.rowindex, x); x++) {
bgneal@45 1099 if (cellElm != lastCell && cellElm.rowSpan > 1)
bgneal@45 1100 cellElm.rowSpan--;
bgneal@45 1101
bgneal@45 1102 lastCell = cellElm;
bgneal@45 1103 }
bgneal@45 1104
bgneal@45 1105 if (tdElm.rowSpan > 1)
bgneal@45 1106 tdElm.rowSpan--;
bgneal@45 1107 }
bgneal@45 1108 }
bgneal@45 1109 }
bgneal@45 1110 }
bgneal@45 1111
bgneal@45 1112 // Remove all but one bogus br
bgneal@45 1113 each(ed.dom.select('br', tdElm), function(e, i) {
bgneal@45 1114 if (i > 0 && ed.dom.getAttrib(e, 'mce_bogus'))
bgneal@45 1115 ed.dom.remove(e);
bgneal@45 1116 });
bgneal@45 1117
bgneal@45 1118 break;
bgneal@45 1119 }
bgneal@45 1120
bgneal@45 1121 tableElm = inst.dom.getParent(inst.selection.getNode(), "table");
bgneal@45 1122 inst.addVisual(tableElm);
bgneal@45 1123 inst.nodeChanged();
bgneal@45 1124 }
bgneal@45 1125
bgneal@45 1126 return true;
bgneal@45 1127 }
bgneal@45 1128
bgneal@45 1129 // Pass to next handler in chain
bgneal@45 1130 return false;
bgneal@45 1131 }
bgneal@45 1132 });
bgneal@45 1133
bgneal@45 1134 // Register plugin
bgneal@45 1135 tinymce.PluginManager.add('table', tinymce.plugins.TablePlugin);
bgneal@45 1136 })();