annotate static/js/tiny_mce/plugins/table/editor_plugin_src.js @ 339:b871892264f2

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