annotate media/js/tiny_mce/plugins/table/editor_plugin_src.js @ 265:1ba2c6bf6eb7

Closing #98. Animated GIFs were losing their transparency and animated properties when saved as avatars. Reworked the avatar save process to only run the avatar through PIL if it is too big. This preserves the original uploaded file if it is within the desired size settings. This may still mangle big animated gifs. If this becomes a problem, then maybe look into calling the PIL Image.resize() method directly. Moved the PIL image specific functions from bio.forms to a new module: core.image for better reusability in the future.
author Brian Neal <bgneal@gmail.com>
date Fri, 24 Sep 2010 02:12:09 +0000
parents 6ed2932901fa
children
rev   line source
bgneal@45 1 /**
bgneal@183 2 * editor_plugin_src.js
bgneal@45 3 *
bgneal@183 4 * Copyright 2009, Moxiecode Systems AB
bgneal@183 5 * Released under LGPL License.
bgneal@183 6 *
bgneal@183 7 * License: http://tinymce.moxiecode.com/license
bgneal@183 8 * Contributing: http://tinymce.moxiecode.com/contributing
bgneal@45 9 */
bgneal@45 10
bgneal@183 11 (function(tinymce) {
bgneal@45 12 var each = tinymce.each;
bgneal@45 13
bgneal@247 14 // Checks if the selection/caret is at the start of the specified block element
bgneal@247 15 function isAtStart(rng, par) {
bgneal@247 16 var doc = par.ownerDocument, rng2 = doc.createRange(), elm;
bgneal@247 17
bgneal@247 18 rng2.setStartBefore(par);
bgneal@247 19 rng2.setEnd(rng.endContainer, rng.endOffset);
bgneal@247 20
bgneal@247 21 elm = doc.createElement('body');
bgneal@247 22 elm.appendChild(rng2.cloneContents());
bgneal@247 23
bgneal@247 24 // Check for text characters of other elements that should be treated as content
bgneal@247 25 return elm.innerHTML.replace(/<(br|img|object|embed|input|textarea)[^>]*>/gi, '-').replace(/<[^>]+>/g, '').length == 0;
bgneal@247 26 };
bgneal@247 27
bgneal@183 28 /**
bgneal@183 29 * Table Grid class.
bgneal@183 30 */
bgneal@183 31 function TableGrid(table, dom, selection) {
bgneal@183 32 var grid, startPos, endPos, selectedCell;
bgneal@183 33
bgneal@183 34 buildGrid();
bgneal@183 35 selectedCell = dom.getParent(selection.getStart(), 'th,td');
bgneal@183 36 if (selectedCell) {
bgneal@183 37 startPos = getPos(selectedCell);
bgneal@183 38 endPos = findEndPos();
bgneal@183 39 selectedCell = getCell(startPos.x, startPos.y);
bgneal@183 40 }
bgneal@183 41
bgneal@217 42 function cloneNode(node, children) {
bgneal@217 43 node = node.cloneNode(children);
bgneal@217 44 node.removeAttribute('id');
bgneal@217 45
bgneal@217 46 return node;
bgneal@217 47 }
bgneal@217 48
bgneal@183 49 function buildGrid() {
bgneal@183 50 var startY = 0;
bgneal@183 51
bgneal@183 52 grid = [];
bgneal@183 53
bgneal@183 54 each(['thead', 'tbody', 'tfoot'], function(part) {
bgneal@247 55 var rows = dom.select('> ' + part + ' tr', table);
bgneal@183 56
bgneal@183 57 each(rows, function(tr, y) {
bgneal@183 58 y += startY;
bgneal@183 59
bgneal@247 60 each(dom.select('> td, > th', tr), function(td, x) {
bgneal@183 61 var x2, y2, rowspan, colspan;
bgneal@183 62
bgneal@183 63 // Skip over existing cells produced by rowspan
bgneal@183 64 if (grid[y]) {
bgneal@183 65 while (grid[y][x])
bgneal@183 66 x++;
bgneal@183 67 }
bgneal@183 68
bgneal@183 69 // Get col/rowspan from cell
bgneal@183 70 rowspan = getSpanVal(td, 'rowspan');
bgneal@183 71 colspan = getSpanVal(td, 'colspan');
bgneal@183 72
bgneal@183 73 // Fill out rowspan/colspan right and down
bgneal@183 74 for (y2 = y; y2 < y + rowspan; y2++) {
bgneal@183 75 if (!grid[y2])
bgneal@183 76 grid[y2] = [];
bgneal@183 77
bgneal@183 78 for (x2 = x; x2 < x + colspan; x2++) {
bgneal@183 79 grid[y2][x2] = {
bgneal@183 80 part : part,
bgneal@183 81 real : y2 == y && x2 == x,
bgneal@183 82 elm : td,
bgneal@183 83 rowspan : rowspan,
bgneal@183 84 colspan : colspan
bgneal@183 85 };
bgneal@183 86 }
bgneal@183 87 }
bgneal@183 88 });
bgneal@183 89 });
bgneal@183 90
bgneal@183 91 startY += rows.length;
bgneal@183 92 });
bgneal@183 93 };
bgneal@183 94
bgneal@183 95 function getCell(x, y) {
bgneal@183 96 var row;
bgneal@183 97
bgneal@183 98 row = grid[y];
bgneal@183 99 if (row)
bgneal@183 100 return row[x];
bgneal@183 101 };
bgneal@183 102
bgneal@183 103 function getSpanVal(td, name) {
bgneal@183 104 return parseInt(td.getAttribute(name) || 1);
bgneal@183 105 };
bgneal@183 106
bgneal@183 107 function isCellSelected(cell) {
bgneal@183 108 return dom.hasClass(cell.elm, 'mceSelected') || cell == selectedCell;
bgneal@183 109 };
bgneal@183 110
bgneal@183 111 function getSelectedRows() {
bgneal@183 112 var rows = [];
bgneal@183 113
bgneal@183 114 each(table.rows, function(row) {
bgneal@183 115 each(row.cells, function(cell) {
bgneal@183 116 if (dom.hasClass(cell, 'mceSelected') || cell == selectedCell.elm) {
bgneal@183 117 rows.push(row);
bgneal@183 118 return false;
bgneal@183 119 }
bgneal@183 120 });
bgneal@183 121 });
bgneal@183 122
bgneal@183 123 return rows;
bgneal@183 124 };
bgneal@183 125
bgneal@183 126 function deleteTable() {
bgneal@183 127 var rng = dom.createRng();
bgneal@183 128
bgneal@183 129 rng.setStartAfter(table);
bgneal@183 130 rng.setEndAfter(table);
bgneal@183 131
bgneal@183 132 selection.setRng(rng);
bgneal@183 133
bgneal@183 134 dom.remove(table);
bgneal@183 135 };
bgneal@183 136
bgneal@183 137 function cloneCell(cell) {
bgneal@183 138 var formatNode;
bgneal@183 139
bgneal@183 140 // Clone formats
bgneal@183 141 tinymce.walk(cell, function(node) {
bgneal@183 142 var curNode;
bgneal@183 143
bgneal@183 144 if (node.nodeType == 3) {
bgneal@183 145 each(dom.getParents(node.parentNode, null, cell).reverse(), function(node) {
bgneal@217 146 node = cloneNode(node, false);
bgneal@183 147
bgneal@183 148 if (!formatNode)
bgneal@183 149 formatNode = curNode = node;
bgneal@183 150 else if (curNode)
bgneal@183 151 curNode.appendChild(node);
bgneal@183 152
bgneal@183 153 curNode = node;
bgneal@183 154 });
bgneal@183 155
bgneal@183 156 // Add something to the inner node
bgneal@183 157 if (curNode)
bgneal@183 158 curNode.innerHTML = tinymce.isIE ? '&nbsp;' : '<br _mce_bogus="1" />';
bgneal@183 159
bgneal@183 160 return false;
bgneal@183 161 }
bgneal@183 162 }, 'childNodes');
bgneal@183 163
bgneal@217 164 cell = cloneNode(cell, false);
bgneal@183 165 cell.rowSpan = cell.colSpan = 1;
bgneal@183 166
bgneal@183 167 if (formatNode) {
bgneal@183 168 cell.appendChild(formatNode);
bgneal@183 169 } else {
bgneal@183 170 if (!tinymce.isIE)
bgneal@183 171 cell.innerHTML = '<br _mce_bogus="1" />';
bgneal@183 172 }
bgneal@183 173
bgneal@183 174 return cell;
bgneal@183 175 };
bgneal@183 176
bgneal@183 177 function cleanup() {
bgneal@183 178 var rng = dom.createRng();
bgneal@183 179
bgneal@183 180 // Empty rows
bgneal@183 181 each(dom.select('tr', table), function(tr) {
bgneal@183 182 if (tr.cells.length == 0)
bgneal@183 183 dom.remove(tr);
bgneal@183 184 });
bgneal@183 185
bgneal@183 186 // Empty table
bgneal@183 187 if (dom.select('tr', table).length == 0) {
bgneal@183 188 rng.setStartAfter(table);
bgneal@183 189 rng.setEndAfter(table);
bgneal@183 190 selection.setRng(rng);
bgneal@183 191 dom.remove(table);
bgneal@183 192 return;
bgneal@183 193 }
bgneal@183 194
bgneal@183 195 // Empty header/body/footer
bgneal@183 196 each(dom.select('thead,tbody,tfoot', table), function(part) {
bgneal@183 197 if (part.rows.length == 0)
bgneal@183 198 dom.remove(part);
bgneal@183 199 });
bgneal@183 200
bgneal@183 201 // Restore selection to start position if it still exists
bgneal@183 202 buildGrid();
bgneal@183 203
bgneal@183 204 // Restore the selection to the closest table position
bgneal@183 205 row = grid[Math.min(grid.length - 1, startPos.y)];
bgneal@183 206 if (row) {
bgneal@183 207 selection.select(row[Math.min(row.length - 1, startPos.x)].elm, true);
bgneal@183 208 selection.collapse(true);
bgneal@183 209 }
bgneal@183 210 };
bgneal@183 211
bgneal@183 212 function fillLeftDown(x, y, rows, cols) {
bgneal@183 213 var tr, x2, r, c, cell;
bgneal@183 214
bgneal@183 215 tr = grid[y][x].elm.parentNode;
bgneal@183 216 for (r = 1; r <= rows; r++) {
bgneal@183 217 tr = dom.getNext(tr, 'tr');
bgneal@183 218
bgneal@183 219 if (tr) {
bgneal@183 220 // Loop left to find real cell
bgneal@183 221 for (x2 = x; x2 >= 0; x2--) {
bgneal@183 222 cell = grid[y + r][x2].elm;
bgneal@183 223
bgneal@183 224 if (cell.parentNode == tr) {
bgneal@183 225 // Append clones after
bgneal@183 226 for (c = 1; c <= cols; c++)
bgneal@183 227 dom.insertAfter(cloneCell(cell), cell);
bgneal@183 228
bgneal@183 229 break;
bgneal@183 230 }
bgneal@183 231 }
bgneal@183 232
bgneal@183 233 if (x2 == -1) {
bgneal@183 234 // Insert nodes before first cell
bgneal@183 235 for (c = 1; c <= cols; c++)
bgneal@183 236 tr.insertBefore(cloneCell(tr.cells[0]), tr.cells[0]);
bgneal@183 237 }
bgneal@183 238 }
bgneal@183 239 }
bgneal@183 240 };
bgneal@183 241
bgneal@183 242 function split() {
bgneal@183 243 each(grid, function(row, y) {
bgneal@183 244 each(row, function(cell, x) {
bgneal@183 245 var colSpan, rowSpan, newCell, i;
bgneal@183 246
bgneal@183 247 if (isCellSelected(cell)) {
bgneal@183 248 cell = cell.elm;
bgneal@183 249 colSpan = getSpanVal(cell, 'colspan');
bgneal@183 250 rowSpan = getSpanVal(cell, 'rowspan');
bgneal@183 251
bgneal@183 252 if (colSpan > 1 || rowSpan > 1) {
bgneal@183 253 cell.colSpan = cell.rowSpan = 1;
bgneal@183 254
bgneal@183 255 // Insert cells right
bgneal@183 256 for (i = 0; i < colSpan - 1; i++)
bgneal@183 257 dom.insertAfter(cloneCell(cell), cell);
bgneal@183 258
bgneal@183 259 fillLeftDown(x, y, rowSpan - 1, colSpan);
bgneal@183 260 }
bgneal@183 261 }
bgneal@183 262 });
bgneal@183 263 });
bgneal@183 264 };
bgneal@183 265
bgneal@183 266 function merge(cell, cols, rows) {
bgneal@183 267 var startX, startY, endX, endY, x, y, startCell, endCell, cell, children;
bgneal@183 268
bgneal@183 269 // Use specified cell and cols/rows
bgneal@183 270 if (cell) {
bgneal@183 271 pos = getPos(cell);
bgneal@183 272 startX = pos.x;
bgneal@183 273 startY = pos.y;
bgneal@183 274 endX = startX + (cols - 1);
bgneal@183 275 endY = startY + (rows - 1);
bgneal@183 276 } else {
bgneal@183 277 // Use selection
bgneal@183 278 startX = startPos.x;
bgneal@183 279 startY = startPos.y;
bgneal@183 280 endX = endPos.x;
bgneal@183 281 endY = endPos.y;
bgneal@183 282 }
bgneal@183 283
bgneal@183 284 // Find start/end cells
bgneal@183 285 startCell = getCell(startX, startY);
bgneal@183 286 endCell = getCell(endX, endY);
bgneal@183 287
bgneal@183 288 // Check if the cells exists and if they are of the same part for example tbody = tbody
bgneal@183 289 if (startCell && endCell && startCell.part == endCell.part) {
bgneal@183 290 // Split and rebuild grid
bgneal@183 291 split();
bgneal@183 292 buildGrid();
bgneal@183 293
bgneal@183 294 // Set row/col span to start cell
bgneal@183 295 startCell = getCell(startX, startY).elm;
bgneal@183 296 startCell.colSpan = (endX - startX) + 1;
bgneal@183 297 startCell.rowSpan = (endY - startY) + 1;
bgneal@183 298
bgneal@183 299 // Remove other cells and add it's contents to the start cell
bgneal@183 300 for (y = startY; y <= endY; y++) {
bgneal@183 301 for (x = startX; x <= endX; x++) {
bgneal@183 302 cell = grid[y][x].elm;
bgneal@183 303
bgneal@183 304 if (cell != startCell) {
bgneal@183 305 // Move children to startCell
bgneal@183 306 children = tinymce.grep(cell.childNodes);
bgneal@183 307 each(children, function(node, i) {
bgneal@183 308 // Jump over last BR element
bgneal@183 309 if (node.nodeName != 'BR' || i != children.length - 1)
bgneal@183 310 startCell.appendChild(node);
bgneal@183 311 });
bgneal@183 312
bgneal@183 313 // Remove cell
bgneal@183 314 dom.remove(cell);
bgneal@183 315 }
bgneal@183 316 }
bgneal@183 317 }
bgneal@183 318
bgneal@183 319 // Remove empty rows etc and restore caret location
bgneal@183 320 cleanup();
bgneal@183 321 }
bgneal@183 322 };
bgneal@183 323
bgneal@183 324 function insertRow(before) {
bgneal@183 325 var posY, cell, lastCell, x, rowElm, newRow, newCell, otherCell;
bgneal@183 326
bgneal@183 327 // Find first/last row
bgneal@183 328 each(grid, function(row, y) {
bgneal@183 329 each(row, function(cell, x) {
bgneal@183 330 if (isCellSelected(cell)) {
bgneal@183 331 cell = cell.elm;
bgneal@183 332 rowElm = cell.parentNode;
bgneal@217 333 newRow = cloneNode(rowElm, false);
bgneal@183 334 posY = y;
bgneal@183 335
bgneal@183 336 if (before)
bgneal@183 337 return false;
bgneal@183 338 }
bgneal@183 339 });
bgneal@183 340
bgneal@183 341 if (before)
bgneal@183 342 return !posY;
bgneal@183 343 });
bgneal@183 344
bgneal@183 345 for (x = 0; x < grid[0].length; x++) {
bgneal@183 346 cell = grid[posY][x].elm;
bgneal@183 347
bgneal@183 348 if (cell != lastCell) {
bgneal@183 349 if (!before) {
bgneal@183 350 rowSpan = getSpanVal(cell, 'rowspan');
bgneal@183 351 if (rowSpan > 1) {
bgneal@183 352 cell.rowSpan = rowSpan + 1;
bgneal@183 353 continue;
bgneal@183 354 }
bgneal@183 355 } else {
bgneal@183 356 // Check if cell above can be expanded
bgneal@183 357 if (posY > 0 && grid[posY - 1][x]) {
bgneal@183 358 otherCell = grid[posY - 1][x].elm;
bgneal@183 359 rowSpan = getSpanVal(otherCell, 'rowspan');
bgneal@183 360 if (rowSpan > 1) {
bgneal@183 361 otherCell.rowSpan = rowSpan + 1;
bgneal@183 362 continue;
bgneal@183 363 }
bgneal@183 364 }
bgneal@183 365 }
bgneal@183 366
bgneal@183 367 // Insert new cell into new row
bgneal@183 368 newCell = cloneCell(cell)
bgneal@183 369 newCell.colSpan = cell.colSpan;
bgneal@183 370 newRow.appendChild(newCell);
bgneal@183 371
bgneal@183 372 lastCell = cell;
bgneal@183 373 }
bgneal@183 374 }
bgneal@183 375
bgneal@183 376 if (newRow.hasChildNodes()) {
bgneal@183 377 if (!before)
bgneal@183 378 dom.insertAfter(newRow, rowElm);
bgneal@183 379 else
bgneal@183 380 rowElm.parentNode.insertBefore(newRow, rowElm);
bgneal@183 381 }
bgneal@183 382 };
bgneal@183 383
bgneal@183 384 function insertCol(before) {
bgneal@183 385 var posX, lastCell;
bgneal@183 386
bgneal@183 387 // Find first/last column
bgneal@183 388 each(grid, function(row, y) {
bgneal@183 389 each(row, function(cell, x) {
bgneal@183 390 if (isCellSelected(cell)) {
bgneal@183 391 posX = x;
bgneal@183 392
bgneal@183 393 if (before)
bgneal@183 394 return false;
bgneal@183 395 }
bgneal@183 396 });
bgneal@183 397
bgneal@183 398 if (before)
bgneal@183 399 return !posX;
bgneal@183 400 });
bgneal@183 401
bgneal@183 402 each(grid, function(row, y) {
bgneal@183 403 var cell = row[posX].elm, rowSpan, colSpan;
bgneal@183 404
bgneal@183 405 if (cell != lastCell) {
bgneal@183 406 colSpan = getSpanVal(cell, 'colspan');
bgneal@183 407 rowSpan = getSpanVal(cell, 'rowspan');
bgneal@183 408
bgneal@183 409 if (colSpan == 1) {
bgneal@183 410 if (!before) {
bgneal@183 411 dom.insertAfter(cloneCell(cell), cell);
bgneal@183 412 fillLeftDown(posX, y, rowSpan - 1, colSpan);
bgneal@183 413 } else {
bgneal@183 414 cell.parentNode.insertBefore(cloneCell(cell), cell);
bgneal@183 415 fillLeftDown(posX, y, rowSpan - 1, colSpan);
bgneal@183 416 }
bgneal@183 417 } else
bgneal@183 418 cell.colSpan++;
bgneal@183 419
bgneal@183 420 lastCell = cell;
bgneal@183 421 }
bgneal@183 422 });
bgneal@183 423 };
bgneal@183 424
bgneal@183 425 function deleteCols() {
bgneal@183 426 var cols = [];
bgneal@183 427
bgneal@183 428 // Get selected column indexes
bgneal@183 429 each(grid, function(row, y) {
bgneal@183 430 each(row, function(cell, x) {
bgneal@183 431 if (isCellSelected(cell) && tinymce.inArray(cols, x) === -1) {
bgneal@183 432 each(grid, function(row) {
bgneal@183 433 var cell = row[x].elm, colSpan;
bgneal@183 434
bgneal@183 435 colSpan = getSpanVal(cell, 'colspan');
bgneal@183 436
bgneal@183 437 if (colSpan > 1)
bgneal@183 438 cell.colSpan = colSpan - 1;
bgneal@183 439 else
bgneal@183 440 dom.remove(cell);
bgneal@183 441 });
bgneal@183 442
bgneal@183 443 cols.push(x);
bgneal@183 444 }
bgneal@183 445 });
bgneal@183 446 });
bgneal@183 447
bgneal@183 448 cleanup();
bgneal@183 449 };
bgneal@183 450
bgneal@183 451 function deleteRows() {
bgneal@183 452 var rows;
bgneal@183 453
bgneal@183 454 function deleteRow(tr) {
bgneal@183 455 var nextTr, pos, lastCell;
bgneal@183 456
bgneal@183 457 nextTr = dom.getNext(tr, 'tr');
bgneal@183 458
bgneal@183 459 // Move down row spanned cells
bgneal@183 460 each(tr.cells, function(cell) {
bgneal@183 461 var rowSpan = getSpanVal(cell, 'rowspan');
bgneal@183 462
bgneal@183 463 if (rowSpan > 1) {
bgneal@183 464 cell.rowSpan = rowSpan - 1;
bgneal@183 465 pos = getPos(cell);
bgneal@183 466 fillLeftDown(pos.x, pos.y, 1, 1);
bgneal@183 467 }
bgneal@183 468 });
bgneal@183 469
bgneal@183 470 // Delete cells
bgneal@183 471 pos = getPos(tr.cells[0]);
bgneal@183 472 each(grid[pos.y], function(cell) {
bgneal@183 473 var rowSpan;
bgneal@183 474
bgneal@183 475 cell = cell.elm;
bgneal@183 476
bgneal@183 477 if (cell != lastCell) {
bgneal@183 478 rowSpan = getSpanVal(cell, 'rowspan');
bgneal@183 479
bgneal@183 480 if (rowSpan <= 1)
bgneal@183 481 dom.remove(cell);
bgneal@183 482 else
bgneal@183 483 cell.rowSpan = rowSpan - 1;
bgneal@183 484
bgneal@183 485 lastCell = cell;
bgneal@183 486 }
bgneal@183 487 });
bgneal@183 488 };
bgneal@183 489
bgneal@183 490 // Get selected rows and move selection out of scope
bgneal@183 491 rows = getSelectedRows();
bgneal@183 492
bgneal@183 493 // Delete all selected rows
bgneal@183 494 each(rows.reverse(), function(tr) {
bgneal@183 495 deleteRow(tr);
bgneal@183 496 });
bgneal@183 497
bgneal@183 498 cleanup();
bgneal@183 499 };
bgneal@183 500
bgneal@183 501 function cutRows() {
bgneal@183 502 var rows = getSelectedRows();
bgneal@183 503
bgneal@183 504 dom.remove(rows);
bgneal@183 505 cleanup();
bgneal@183 506
bgneal@183 507 return rows;
bgneal@183 508 };
bgneal@183 509
bgneal@183 510 function copyRows() {
bgneal@183 511 var rows = getSelectedRows();
bgneal@183 512
bgneal@183 513 each(rows, function(row, i) {
bgneal@217 514 rows[i] = cloneNode(row, true);
bgneal@183 515 });
bgneal@183 516
bgneal@183 517 return rows;
bgneal@183 518 };
bgneal@183 519
bgneal@183 520 function pasteRows(rows, before) {
bgneal@183 521 var selectedRows = getSelectedRows(),
bgneal@183 522 targetRow = selectedRows[before ? 0 : selectedRows.length - 1],
bgneal@183 523 targetCellCount = targetRow.cells.length;
bgneal@183 524
bgneal@183 525 // Calc target cell count
bgneal@183 526 each(grid, function(row) {
bgneal@183 527 var match;
bgneal@183 528
bgneal@183 529 targetCellCount = 0;
bgneal@183 530 each(row, function(cell, x) {
bgneal@183 531 if (cell.real)
bgneal@183 532 targetCellCount += cell.colspan;
bgneal@183 533
bgneal@183 534 if (cell.elm.parentNode == targetRow)
bgneal@183 535 match = 1;
bgneal@183 536 });
bgneal@183 537
bgneal@183 538 if (match)
bgneal@183 539 return false;
bgneal@183 540 });
bgneal@183 541
bgneal@183 542 if (!before)
bgneal@183 543 rows.reverse();
bgneal@183 544
bgneal@183 545 each(rows, function(row) {
bgneal@183 546 var cellCount = row.cells.length, cell;
bgneal@183 547
bgneal@183 548 // Remove col/rowspans
bgneal@183 549 for (i = 0; i < cellCount; i++) {
bgneal@183 550 cell = row.cells[i];
bgneal@183 551 cell.colSpan = cell.rowSpan = 1;
bgneal@183 552 }
bgneal@183 553
bgneal@183 554 // Needs more cells
bgneal@183 555 for (i = cellCount; i < targetCellCount; i++)
bgneal@183 556 row.appendChild(cloneCell(row.cells[cellCount - 1]));
bgneal@183 557
bgneal@183 558 // Needs less cells
bgneal@183 559 for (i = targetCellCount; i < cellCount; i++)
bgneal@183 560 dom.remove(row.cells[i]);
bgneal@183 561
bgneal@183 562 // Add before/after
bgneal@183 563 if (before)
bgneal@183 564 targetRow.parentNode.insertBefore(row, targetRow);
bgneal@183 565 else
bgneal@183 566 dom.insertAfter(row, targetRow);
bgneal@183 567 });
bgneal@183 568 };
bgneal@183 569
bgneal@183 570 function getPos(target) {
bgneal@183 571 var pos;
bgneal@183 572
bgneal@183 573 each(grid, function(row, y) {
bgneal@183 574 each(row, function(cell, x) {
bgneal@183 575 if (cell.elm == target) {
bgneal@183 576 pos = {x : x, y : y};
bgneal@183 577 return false;
bgneal@183 578 }
bgneal@183 579 });
bgneal@183 580
bgneal@183 581 return !pos;
bgneal@183 582 });
bgneal@183 583
bgneal@183 584 return pos;
bgneal@183 585 };
bgneal@183 586
bgneal@183 587 function setStartCell(cell) {
bgneal@183 588 startPos = getPos(cell);
bgneal@183 589 };
bgneal@183 590
bgneal@183 591 function findEndPos() {
bgneal@183 592 var pos, maxX, maxY;
bgneal@183 593
bgneal@183 594 maxX = maxY = 0;
bgneal@183 595
bgneal@183 596 each(grid, function(row, y) {
bgneal@183 597 each(row, function(cell, x) {
bgneal@183 598 var colSpan, rowSpan;
bgneal@183 599
bgneal@183 600 if (isCellSelected(cell)) {
bgneal@183 601 cell = grid[y][x];
bgneal@183 602
bgneal@183 603 if (x > maxX)
bgneal@183 604 maxX = x;
bgneal@183 605
bgneal@183 606 if (y > maxY)
bgneal@183 607 maxY = y;
bgneal@183 608
bgneal@183 609 if (cell.real) {
bgneal@183 610 colSpan = cell.colspan - 1;
bgneal@183 611 rowSpan = cell.rowspan - 1;
bgneal@183 612
bgneal@183 613 if (colSpan) {
bgneal@183 614 if (x + colSpan > maxX)
bgneal@183 615 maxX = x + colSpan;
bgneal@183 616 }
bgneal@183 617
bgneal@183 618 if (rowSpan) {
bgneal@183 619 if (y + rowSpan > maxY)
bgneal@183 620 maxY = y + rowSpan;
bgneal@183 621 }
bgneal@183 622 }
bgneal@183 623 }
bgneal@183 624 });
bgneal@183 625 });
bgneal@183 626
bgneal@183 627 return {x : maxX, y : maxY};
bgneal@183 628 };
bgneal@183 629
bgneal@183 630 function setEndCell(cell) {
bgneal@183 631 var startX, startY, endX, endY, maxX, maxY, colSpan, rowSpan;
bgneal@183 632
bgneal@183 633 endPos = getPos(cell);
bgneal@183 634
bgneal@183 635 if (startPos && endPos) {
bgneal@183 636 // Get start/end positions
bgneal@183 637 startX = Math.min(startPos.x, endPos.x);
bgneal@183 638 startY = Math.min(startPos.y, endPos.y);
bgneal@183 639 endX = Math.max(startPos.x, endPos.x);
bgneal@183 640 endY = Math.max(startPos.y, endPos.y);
bgneal@183 641
bgneal@183 642 // Expand end positon to include spans
bgneal@183 643 maxX = endX;
bgneal@183 644 maxY = endY;
bgneal@183 645
bgneal@183 646 // Expand startX
bgneal@183 647 for (y = startY; y <= maxY; y++) {
bgneal@183 648 cell = grid[y][startX];
bgneal@183 649
bgneal@183 650 if (!cell.real) {
bgneal@183 651 if (startX - (cell.colspan - 1) < startX)
bgneal@183 652 startX -= cell.colspan - 1;
bgneal@183 653 }
bgneal@183 654 }
bgneal@183 655
bgneal@183 656 // Expand startY
bgneal@183 657 for (x = startX; x <= maxX; x++) {
bgneal@183 658 cell = grid[startY][x];
bgneal@183 659
bgneal@183 660 if (!cell.real) {
bgneal@183 661 if (startY - (cell.rowspan - 1) < startY)
bgneal@183 662 startY -= cell.rowspan - 1;
bgneal@183 663 }
bgneal@183 664 }
bgneal@183 665
bgneal@183 666 // Find max X, Y
bgneal@183 667 for (y = startY; y <= endY; y++) {
bgneal@183 668 for (x = startX; x <= endX; x++) {
bgneal@183 669 cell = grid[y][x];
bgneal@183 670
bgneal@183 671 if (cell.real) {
bgneal@183 672 colSpan = cell.colspan - 1;
bgneal@183 673 rowSpan = cell.rowspan - 1;
bgneal@183 674
bgneal@183 675 if (colSpan) {
bgneal@183 676 if (x + colSpan > maxX)
bgneal@183 677 maxX = x + colSpan;
bgneal@183 678 }
bgneal@183 679
bgneal@183 680 if (rowSpan) {
bgneal@183 681 if (y + rowSpan > maxY)
bgneal@183 682 maxY = y + rowSpan;
bgneal@183 683 }
bgneal@183 684 }
bgneal@183 685 }
bgneal@183 686 }
bgneal@183 687
bgneal@183 688 // Remove current selection
bgneal@183 689 dom.removeClass(dom.select('td.mceSelected,th.mceSelected'), 'mceSelected');
bgneal@183 690
bgneal@183 691 // Add new selection
bgneal@183 692 for (y = startY; y <= maxY; y++) {
bgneal@183 693 for (x = startX; x <= maxX; x++)
bgneal@183 694 dom.addClass(grid[y][x].elm, 'mceSelected');
bgneal@183 695 }
bgneal@183 696 }
bgneal@183 697 };
bgneal@183 698
bgneal@183 699 // Expose to public
bgneal@183 700 tinymce.extend(this, {
bgneal@183 701 deleteTable : deleteTable,
bgneal@183 702 split : split,
bgneal@183 703 merge : merge,
bgneal@183 704 insertRow : insertRow,
bgneal@183 705 insertCol : insertCol,
bgneal@183 706 deleteCols : deleteCols,
bgneal@183 707 deleteRows : deleteRows,
bgneal@183 708 cutRows : cutRows,
bgneal@183 709 copyRows : copyRows,
bgneal@183 710 pasteRows : pasteRows,
bgneal@183 711 getPos : getPos,
bgneal@183 712 setStartCell : setStartCell,
bgneal@183 713 setEndCell : setEndCell
bgneal@183 714 });
bgneal@183 715 };
bgneal@183 716
bgneal@45 717 tinymce.create('tinymce.plugins.TablePlugin', {
bgneal@45 718 init : function(ed, url) {
bgneal@183 719 var winMan, clipboardRows;
bgneal@45 720
bgneal@183 721 function createTableGrid(node) {
bgneal@183 722 var selection = ed.selection, tblElm = ed.dom.getParent(node || selection.getNode(), 'table');
bgneal@183 723
bgneal@183 724 if (tblElm)
bgneal@183 725 return new TableGrid(tblElm, ed.dom, selection);
bgneal@183 726 };
bgneal@183 727
bgneal@183 728 function cleanup() {
bgneal@183 729 // Restore selection possibilities
bgneal@183 730 ed.getBody().style.webkitUserSelect = '';
bgneal@183 731 ed.dom.removeClass(ed.dom.select('td.mceSelected,th.mceSelected'), 'mceSelected');
bgneal@183 732 };
bgneal@45 733
bgneal@45 734 // Register buttons
bgneal@45 735 each([
bgneal@45 736 ['table', 'table.desc', 'mceInsertTable', true],
bgneal@45 737 ['delete_table', 'table.del', 'mceTableDelete'],
bgneal@45 738 ['delete_col', 'table.delete_col_desc', 'mceTableDeleteCol'],
bgneal@45 739 ['delete_row', 'table.delete_row_desc', 'mceTableDeleteRow'],
bgneal@45 740 ['col_after', 'table.col_after_desc', 'mceTableInsertColAfter'],
bgneal@45 741 ['col_before', 'table.col_before_desc', 'mceTableInsertColBefore'],
bgneal@45 742 ['row_after', 'table.row_after_desc', 'mceTableInsertRowAfter'],
bgneal@45 743 ['row_before', 'table.row_before_desc', 'mceTableInsertRowBefore'],
bgneal@45 744 ['row_props', 'table.row_desc', 'mceTableRowProps', true],
bgneal@45 745 ['cell_props', 'table.cell_desc', 'mceTableCellProps', true],
bgneal@45 746 ['split_cells', 'table.split_cells_desc', 'mceTableSplitCells', true],
bgneal@45 747 ['merge_cells', 'table.merge_cells_desc', 'mceTableMergeCells', true]
bgneal@45 748 ], function(c) {
bgneal@45 749 ed.addButton(c[0], {title : c[1], cmd : c[2], ui : c[3]});
bgneal@45 750 });
bgneal@45 751
bgneal@183 752 // Select whole table is a table border is clicked
bgneal@183 753 if (!tinymce.isIE) {
bgneal@183 754 ed.onClick.add(function(ed, e) {
bgneal@183 755 e = e.target;
bgneal@45 756
bgneal@183 757 if (e.nodeName === 'TABLE')
bgneal@183 758 ed.selection.select(e);
bgneal@45 759 });
bgneal@45 760 }
bgneal@45 761
bgneal@183 762 // Handle node change updates
bgneal@183 763 ed.onNodeChange.add(function(ed, cm, n) {
bgneal@183 764 var p;
bgneal@183 765
bgneal@183 766 n = ed.selection.getStart();
bgneal@183 767 p = ed.dom.getParent(n, 'td,th,caption');
bgneal@183 768 cm.setActive('table', n.nodeName === 'TABLE' || !!p);
bgneal@183 769
bgneal@183 770 // Disable table tools if we are in caption
bgneal@183 771 if (p && p.nodeName === 'CAPTION')
bgneal@183 772 p = 0;
bgneal@183 773
bgneal@183 774 cm.setDisabled('delete_table', !p);
bgneal@183 775 cm.setDisabled('delete_col', !p);
bgneal@183 776 cm.setDisabled('delete_table', !p);
bgneal@183 777 cm.setDisabled('delete_row', !p);
bgneal@183 778 cm.setDisabled('col_after', !p);
bgneal@183 779 cm.setDisabled('col_before', !p);
bgneal@183 780 cm.setDisabled('row_after', !p);
bgneal@183 781 cm.setDisabled('row_before', !p);
bgneal@183 782 cm.setDisabled('row_props', !p);
bgneal@183 783 cm.setDisabled('cell_props', !p);
bgneal@183 784 cm.setDisabled('split_cells', !p);
bgneal@183 785 cm.setDisabled('merge_cells', !p);
bgneal@183 786 });
bgneal@183 787
bgneal@183 788 ed.onInit.add(function(ed) {
bgneal@183 789 var startTable, startCell, dom = ed.dom, tableGrid;
bgneal@183 790
bgneal@183 791 winMan = ed.windowManager;
bgneal@183 792
bgneal@183 793 // Add cell selection logic
bgneal@183 794 ed.onMouseDown.add(function(ed, e) {
bgneal@183 795 if (e.button != 2) {
bgneal@183 796 cleanup();
bgneal@183 797
bgneal@183 798 startCell = dom.getParent(e.target, 'td,th');
bgneal@183 799 startTable = dom.getParent(startCell, 'table');
bgneal@183 800 }
bgneal@183 801 });
bgneal@183 802
bgneal@183 803 dom.bind(ed.getDoc(), 'mouseover', function(e) {
bgneal@183 804 var sel, table, target = e.target;
bgneal@183 805
bgneal@183 806 if (startCell && (tableGrid || target != startCell) && (target.nodeName == 'TD' || target.nodeName == 'TH')) {
bgneal@183 807 table = dom.getParent(target, 'table');
bgneal@183 808 if (table == startTable) {
bgneal@183 809 if (!tableGrid) {
bgneal@183 810 tableGrid = createTableGrid(table);
bgneal@183 811 tableGrid.setStartCell(startCell);
bgneal@183 812
bgneal@183 813 ed.getBody().style.webkitUserSelect = 'none';
bgneal@183 814 }
bgneal@183 815
bgneal@183 816 tableGrid.setEndCell(target);
bgneal@183 817 }
bgneal@183 818
bgneal@183 819 // Remove current selection
bgneal@183 820 sel = ed.selection.getSel();
bgneal@183 821
bgneal@183 822 if (sel.removeAllRanges)
bgneal@183 823 sel.removeAllRanges();
bgneal@183 824 else
bgneal@183 825 sel.empty();
bgneal@183 826
bgneal@183 827 e.preventDefault();
bgneal@183 828 }
bgneal@183 829 });
bgneal@183 830
bgneal@183 831 ed.onMouseUp.add(function(ed, e) {
bgneal@183 832 var rng, sel = ed.selection, selectedCells, nativeSel = sel.getSel(), walker, node, lastNode, endNode;
bgneal@183 833
bgneal@183 834 // Move selection to startCell
bgneal@183 835 if (startCell) {
bgneal@183 836 if (tableGrid)
bgneal@183 837 ed.getBody().style.webkitUserSelect = '';
bgneal@183 838
bgneal@183 839 function setPoint(node, start) {
bgneal@183 840 var walker = new tinymce.dom.TreeWalker(node, node);
bgneal@183 841
bgneal@183 842 do {
bgneal@183 843 // Text node
bgneal@183 844 if (node.nodeType == 3 && tinymce.trim(node.nodeValue).length != 0) {
bgneal@183 845 if (start)
bgneal@183 846 rng.setStart(node, 0);
bgneal@183 847 else
bgneal@183 848 rng.setEnd(node, node.nodeValue.length);
bgneal@183 849
bgneal@183 850 return;
bgneal@183 851 }
bgneal@183 852
bgneal@183 853 // BR element
bgneal@183 854 if (node.nodeName == 'BR') {
bgneal@183 855 if (start)
bgneal@183 856 rng.setStartBefore(node);
bgneal@183 857 else
bgneal@183 858 rng.setEndBefore(node);
bgneal@183 859
bgneal@183 860 return;
bgneal@183 861 }
bgneal@183 862 } while (node = (start ? walker.next() : walker.prev()));
bgneal@183 863 };
bgneal@183 864
bgneal@183 865 // Try to expand text selection as much as we can only Gecko supports cell selection
bgneal@183 866 selectedCells = dom.select('td.mceSelected,th.mceSelected');
bgneal@183 867 if (selectedCells.length > 0) {
bgneal@183 868 rng = dom.createRng();
bgneal@183 869 node = selectedCells[0];
bgneal@183 870 endNode = selectedCells[selectedCells.length - 1];
bgneal@183 871
bgneal@183 872 setPoint(node, 1);
bgneal@183 873 walker = new tinymce.dom.TreeWalker(node, dom.getParent(selectedCells[0], 'table'));
bgneal@183 874
bgneal@183 875 do {
bgneal@183 876 if (node.nodeName == 'TD' || node.nodeName == 'TH') {
bgneal@183 877 if (!dom.hasClass(node, 'mceSelected'))
bgneal@183 878 break;
bgneal@183 879
bgneal@183 880 lastNode = node;
bgneal@183 881 }
bgneal@183 882 } while (node = walker.next());
bgneal@183 883
bgneal@183 884 setPoint(lastNode);
bgneal@183 885
bgneal@183 886 sel.setRng(rng);
bgneal@183 887 }
bgneal@183 888
bgneal@183 889 ed.nodeChanged();
bgneal@183 890 startCell = tableGrid = startTable = null;
bgneal@183 891 }
bgneal@183 892 });
bgneal@183 893
bgneal@183 894 ed.onKeyUp.add(function(ed, e) {
bgneal@183 895 cleanup();
bgneal@183 896 });
bgneal@183 897
bgneal@183 898 // Add context menu
bgneal@45 899 if (ed && ed.plugins.contextmenu) {
bgneal@45 900 ed.plugins.contextmenu.onContextMenu.add(function(th, m, e) {
bgneal@45 901 var sm, se = ed.selection, el = se.getNode() || ed.getBody();
bgneal@45 902
bgneal@217 903 if (ed.dom.getParent(e, 'td') || ed.dom.getParent(e, 'th') || ed.dom.select('td.mceSelected,th.mceSelected').length) {
bgneal@45 904 m.removeAll();
bgneal@45 905
bgneal@45 906 if (el.nodeName == 'A' && !ed.dom.getAttrib(el, 'name')) {
bgneal@45 907 m.add({title : 'advanced.link_desc', icon : 'link', cmd : ed.plugins.advlink ? 'mceAdvLink' : 'mceLink', ui : true});
bgneal@45 908 m.add({title : 'advanced.unlink_desc', icon : 'unlink', cmd : 'UnLink'});
bgneal@45 909 m.addSeparator();
bgneal@45 910 }
bgneal@45 911
bgneal@45 912 if (el.nodeName == 'IMG' && el.className.indexOf('mceItem') == -1) {
bgneal@45 913 m.add({title : 'advanced.image_desc', icon : 'image', cmd : ed.plugins.advimage ? 'mceAdvImage' : 'mceImage', ui : true});
bgneal@45 914 m.addSeparator();
bgneal@45 915 }
bgneal@45 916
bgneal@183 917 m.add({title : 'table.desc', icon : 'table', cmd : 'mceInsertTable', value : {action : 'insert'}});
bgneal@183 918 m.add({title : 'table.props_desc', icon : 'table_props', cmd : 'mceInsertTable'});
bgneal@183 919 m.add({title : 'table.del', icon : 'delete_table', cmd : 'mceTableDelete'});
bgneal@45 920 m.addSeparator();
bgneal@45 921
bgneal@45 922 // Cell menu
bgneal@45 923 sm = m.addMenu({title : 'table.cell'});
bgneal@183 924 sm.add({title : 'table.cell_desc', icon : 'cell_props', cmd : 'mceTableCellProps'});
bgneal@183 925 sm.add({title : 'table.split_cells_desc', icon : 'split_cells', cmd : 'mceTableSplitCells'});
bgneal@183 926 sm.add({title : 'table.merge_cells_desc', icon : 'merge_cells', cmd : 'mceTableMergeCells'});
bgneal@45 927
bgneal@45 928 // Row menu
bgneal@45 929 sm = m.addMenu({title : 'table.row'});
bgneal@183 930 sm.add({title : 'table.row_desc', icon : 'row_props', cmd : 'mceTableRowProps'});
bgneal@45 931 sm.add({title : 'table.row_before_desc', icon : 'row_before', cmd : 'mceTableInsertRowBefore'});
bgneal@45 932 sm.add({title : 'table.row_after_desc', icon : 'row_after', cmd : 'mceTableInsertRowAfter'});
bgneal@45 933 sm.add({title : 'table.delete_row_desc', icon : 'delete_row', cmd : 'mceTableDeleteRow'});
bgneal@45 934 sm.addSeparator();
bgneal@45 935 sm.add({title : 'table.cut_row_desc', icon : 'cut', cmd : 'mceTableCutRow'});
bgneal@45 936 sm.add({title : 'table.copy_row_desc', icon : 'copy', cmd : 'mceTableCopyRow'});
bgneal@183 937 sm.add({title : 'table.paste_row_before_desc', icon : 'paste', cmd : 'mceTablePasteRowBefore'}).setDisabled(!clipboardRows);
bgneal@183 938 sm.add({title : 'table.paste_row_after_desc', icon : 'paste', cmd : 'mceTablePasteRowAfter'}).setDisabled(!clipboardRows);
bgneal@45 939
bgneal@45 940 // Column menu
bgneal@45 941 sm = m.addMenu({title : 'table.col'});
bgneal@45 942 sm.add({title : 'table.col_before_desc', icon : 'col_before', cmd : 'mceTableInsertColBefore'});
bgneal@45 943 sm.add({title : 'table.col_after_desc', icon : 'col_after', cmd : 'mceTableInsertColAfter'});
bgneal@45 944 sm.add({title : 'table.delete_col_desc', icon : 'delete_col', cmd : 'mceTableDeleteCol'});
bgneal@45 945 } else
bgneal@183 946 m.add({title : 'table.desc', icon : 'table', cmd : 'mceInsertTable'});
bgneal@45 947 });
bgneal@45 948 }
bgneal@183 949
bgneal@183 950 // Fixes an issue on Gecko where it's impossible to place the caret behind a table
bgneal@183 951 // This fix will force a paragraph element after the table but only when the forced_root_block setting is enabled
bgneal@183 952 if (!tinymce.isIE) {
bgneal@183 953 function fixTableCaretPos() {
bgneal@183 954 var last;
bgneal@183 955
bgneal@183 956 // Skip empty text nodes form the end
bgneal@183 957 for (last = ed.getBody().lastChild; last && last.nodeType == 3 && !last.nodeValue.length; last = last.previousSibling) ;
bgneal@183 958
bgneal@183 959 if (last && last.nodeName == 'TABLE')
bgneal@183 960 ed.dom.add(ed.getBody(), 'p', null, '<br mce_bogus="1" />');
bgneal@183 961 };
bgneal@183 962
bgneal@183 963 // Fixes an bug where it's impossible to place the caret before a table in Gecko
bgneal@183 964 // this fix solves it by detecting when the caret is at the beginning of such a table
bgneal@183 965 // and then manually moves the caret infront of the table
bgneal@183 966 if (tinymce.isGecko) {
bgneal@183 967 ed.onKeyDown.add(function(ed, e) {
bgneal@183 968 var rng, table, dom = ed.dom;
bgneal@183 969
bgneal@183 970 // On gecko it's not possible to place the caret before a table
bgneal@183 971 if (e.keyCode == 37 || e.keyCode == 38) {
bgneal@183 972 rng = ed.selection.getRng();
bgneal@183 973 table = dom.getParent(rng.startContainer, 'table');
bgneal@183 974
bgneal@183 975 if (table && ed.getBody().firstChild == table) {
bgneal@183 976 if (isAtStart(rng, table)) {
bgneal@183 977 rng = dom.createRng();
bgneal@183 978
bgneal@183 979 rng.setStartBefore(table);
bgneal@183 980 rng.setEndBefore(table);
bgneal@183 981
bgneal@183 982 ed.selection.setRng(rng);
bgneal@183 983
bgneal@183 984 e.preventDefault();
bgneal@183 985 }
bgneal@183 986 }
bgneal@183 987 }
bgneal@183 988 });
bgneal@183 989 }
bgneal@183 990
bgneal@183 991 ed.onKeyUp.add(fixTableCaretPos);
bgneal@183 992 ed.onSetContent.add(fixTableCaretPos);
bgneal@183 993 ed.onVisualAid.add(fixTableCaretPos);
bgneal@183 994
bgneal@183 995 ed.onPreProcess.add(function(ed, o) {
bgneal@183 996 var last = o.node.lastChild;
bgneal@183 997
bgneal@183 998 if (last && last.childNodes.length == 1 && last.firstChild.nodeName == 'BR')
bgneal@183 999 ed.dom.remove(last);
bgneal@183 1000 });
bgneal@183 1001
bgneal@183 1002 fixTableCaretPos();
bgneal@183 1003 }
bgneal@45 1004 });
bgneal@45 1005
bgneal@183 1006 // Register action commands
bgneal@183 1007 each({
bgneal@183 1008 mceTableSplitCells : function(grid) {
bgneal@183 1009 grid.split();
bgneal@183 1010 },
bgneal@183 1011
bgneal@183 1012 mceTableMergeCells : function(grid) {
bgneal@183 1013 var rowSpan, colSpan, cell;
bgneal@183 1014
bgneal@183 1015 cell = ed.dom.getParent(ed.selection.getNode(), 'th,td');
bgneal@183 1016 if (cell) {
bgneal@183 1017 rowSpan = cell.rowSpan;
bgneal@183 1018 colSpan = cell.colSpan;
bgneal@45 1019 }
bgneal@45 1020
bgneal@183 1021 if (!ed.dom.select('td.mceSelected,th.mceSelected').length) {
bgneal@183 1022 winMan.open({
bgneal@183 1023 url : url + '/merge_cells.htm',
bgneal@183 1024 width : 240 + parseInt(ed.getLang('table.merge_cells_delta_width', 0)),
bgneal@183 1025 height : 110 + parseInt(ed.getLang('table.merge_cells_delta_height', 0)),
bgneal@183 1026 inline : 1
bgneal@183 1027 }, {
bgneal@183 1028 rows : rowSpan,
bgneal@183 1029 cols : colSpan,
bgneal@183 1030 onaction : function(data) {
bgneal@183 1031 grid.merge(cell, data.cols, data.rows);
bgneal@183 1032 },
bgneal@183 1033 plugin_url : url
bgneal@183 1034 });
bgneal@183 1035 } else
bgneal@183 1036 grid.merge();
bgneal@183 1037 },
bgneal@183 1038
bgneal@183 1039 mceTableInsertRowBefore : function(grid) {
bgneal@183 1040 grid.insertRow(true);
bgneal@183 1041 },
bgneal@183 1042
bgneal@183 1043 mceTableInsertRowAfter : function(grid) {
bgneal@183 1044 grid.insertRow();
bgneal@183 1045 },
bgneal@183 1046
bgneal@183 1047 mceTableInsertColBefore : function(grid) {
bgneal@183 1048 grid.insertCol(true);
bgneal@183 1049 },
bgneal@183 1050
bgneal@183 1051 mceTableInsertColAfter : function(grid) {
bgneal@183 1052 grid.insertCol();
bgneal@183 1053 },
bgneal@183 1054
bgneal@183 1055 mceTableDeleteCol : function(grid) {
bgneal@183 1056 grid.deleteCols();
bgneal@183 1057 },
bgneal@183 1058
bgneal@183 1059 mceTableDeleteRow : function(grid) {
bgneal@183 1060 grid.deleteRows();
bgneal@183 1061 },
bgneal@183 1062
bgneal@183 1063 mceTableCutRow : function(grid) {
bgneal@183 1064 clipboardRows = grid.cutRows();
bgneal@183 1065 },
bgneal@183 1066
bgneal@183 1067 mceTableCopyRow : function(grid) {
bgneal@183 1068 clipboardRows = grid.copyRows();
bgneal@183 1069 },
bgneal@183 1070
bgneal@183 1071 mceTablePasteRowBefore : function(grid) {
bgneal@183 1072 grid.pasteRows(clipboardRows, true);
bgneal@183 1073 },
bgneal@183 1074
bgneal@183 1075 mceTablePasteRowAfter : function(grid) {
bgneal@183 1076 grid.pasteRows(clipboardRows);
bgneal@183 1077 },
bgneal@183 1078
bgneal@183 1079 mceTableDelete : function(grid) {
bgneal@183 1080 grid.deleteTable();
bgneal@45 1081 }
bgneal@183 1082 }, function(func, name) {
bgneal@183 1083 ed.addCommand(name, function() {
bgneal@183 1084 var grid = createTableGrid();
bgneal@183 1085
bgneal@183 1086 if (grid) {
bgneal@183 1087 func(grid);
bgneal@183 1088 ed.execCommand('mceRepaint');
bgneal@183 1089 cleanup();
bgneal@183 1090 }
bgneal@183 1091 });
bgneal@45 1092 });
bgneal@45 1093
bgneal@183 1094 // Register dialog commands
bgneal@183 1095 each({
bgneal@183 1096 mceInsertTable : function(val) {
bgneal@183 1097 winMan.open({
bgneal@183 1098 url : url + '/table.htm',
bgneal@183 1099 width : 400 + parseInt(ed.getLang('table.table_delta_width', 0)),
bgneal@183 1100 height : 320 + parseInt(ed.getLang('table.table_delta_height', 0)),
bgneal@183 1101 inline : 1
bgneal@183 1102 }, {
bgneal@183 1103 plugin_url : url,
bgneal@183 1104 action : val ? val.action : 0
bgneal@183 1105 });
bgneal@183 1106 },
bgneal@45 1107
bgneal@183 1108 mceTableRowProps : function() {
bgneal@183 1109 winMan.open({
bgneal@183 1110 url : url + '/row.htm',
bgneal@183 1111 width : 400 + parseInt(ed.getLang('table.rowprops_delta_width', 0)),
bgneal@183 1112 height : 295 + parseInt(ed.getLang('table.rowprops_delta_height', 0)),
bgneal@183 1113 inline : 1
bgneal@183 1114 }, {
bgneal@183 1115 plugin_url : url
bgneal@183 1116 });
bgneal@183 1117 },
bgneal@183 1118
bgneal@183 1119 mceTableCellProps : function() {
bgneal@183 1120 winMan.open({
bgneal@183 1121 url : url + '/cell.htm',
bgneal@183 1122 width : 400 + parseInt(ed.getLang('table.cellprops_delta_width', 0)),
bgneal@183 1123 height : 295 + parseInt(ed.getLang('table.cellprops_delta_height', 0)),
bgneal@183 1124 inline : 1
bgneal@183 1125 }, {
bgneal@183 1126 plugin_url : url
bgneal@45 1127 });
bgneal@45 1128 }
bgneal@183 1129 }, function(func, name) {
bgneal@183 1130 ed.addCommand(name, function(ui, val) {
bgneal@183 1131 func(val);
bgneal@183 1132 });
bgneal@45 1133 });
bgneal@45 1134 }
bgneal@45 1135 });
bgneal@45 1136
bgneal@45 1137 // Register plugin
bgneal@45 1138 tinymce.PluginManager.add('table', tinymce.plugins.TablePlugin);
bgneal@183 1139 })(tinymce);