includes/clientside/tinymce/plugins/table/editor_plugin_src.js
changeset 543 dffcbfbc4e59
parent 476 f26a69c40431
child 588 20484deb89cd
equal deleted inserted replaced
542:5841df0ab575 543:dffcbfbc4e59
     1 /**
     1 /**
     2  * $Id: editor_plugin_src.js 651 2008-02-29 10:00:25Z spocke $
     2  * $Id: editor_plugin_src.js 824 2008-04-28 15:12:06Z spocke $
     3  *
     3  *
     4  * @author Moxiecode
     4  * @author Moxiecode
     5  * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
     5  * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
     6  */
     6  */
     7 
     7 
    34 			});
    34 			});
    35 
    35 
    36 			ed.onInit.add(function() {
    36 			ed.onInit.add(function() {
    37 				if (ed && ed.plugins.contextmenu) {
    37 				if (ed && ed.plugins.contextmenu) {
    38 					ed.plugins.contextmenu.onContextMenu.add(function(th, m, e) {
    38 					ed.plugins.contextmenu.onContextMenu.add(function(th, m, e) {
    39 						var sm;
    39 						var sm, se = ed.selection, el = se.getNode() || ed.getBody();
    40 
    40 
    41 						if (ed.dom.getParent(e, 'td') || ed.dom.getParent(e, 'th')) {
    41 						if (ed.dom.getParent(e, 'td') || ed.dom.getParent(e, 'th')) {
    42 							m.removeAll();
    42 							m.removeAll();
       
    43 
       
    44 							if (el.nodeName == 'A' && !ed.dom.getAttrib(el, 'name')) {
       
    45 								m.add({title : 'advanced.link_desc', icon : 'link', cmd : ed.plugins.advlink ? 'mceAdvLink' : 'mceLink', ui : true});
       
    46 								m.add({title : 'advanced.unlink_desc', icon : 'unlink', cmd : 'UnLink'});
       
    47 								m.addSeparator();
       
    48 							}
       
    49 
       
    50 							if (el.nodeName == 'IMG' && el.className.indexOf('mceItem') == -1) {
       
    51 								m.add({title : 'advanced.image_desc', icon : 'image', cmd : ed.plugins.advimage ? 'mceAdvImage' : 'mceImage', ui : true});
       
    52 								m.addSeparator();
       
    53 							}
       
    54 
    43 							m.add({title : 'table.desc', icon : 'table', cmd : 'mceInsertTable', ui : true, value : {action : 'insert'}});
    55 							m.add({title : 'table.desc', icon : 'table', cmd : 'mceInsertTable', ui : true, value : {action : 'insert'}});
    44 							m.add({title : 'table.props_desc', icon : 'table_props', cmd : 'mceInsertTable', ui : true});
    56 							m.add({title : 'table.props_desc', icon : 'table_props', cmd : 'mceInsertTable', ui : true});
    45 							m.add({title : 'table.del', icon : 'delete_table', cmd : 'mceTableDelete', ui : true});
    57 							m.add({title : 'table.del', icon : 'delete_table', cmd : 'mceTableDelete', ui : true});
    46 							m.addSeparator();
    58 							m.addSeparator();
    47 
    59 
    72 							m.add({title : 'table.desc', icon : 'table', cmd : 'mceInsertTable', ui : true});
    84 							m.add({title : 'table.desc', icon : 'table', cmd : 'mceInsertTable', ui : true});
    73 					});
    85 					});
    74 				}
    86 				}
    75 			});
    87 			});
    76 
    88 
    77 			// Block delete on gecko inside TD:s. Gecko is removing table elements and then produces incorrect tables
       
    78 			// The backspace key also removed TD:s but this one can not be blocked
       
    79 			if (tinymce.isGecko) {
       
    80 				ed.onKeyPress.add(function(ed, e) {
       
    81 					var n;
       
    82 
       
    83 					if (e.keyCode == 46) {
       
    84 						n = ed.dom.getParent(ed.selection.getNode(), 'TD,TH');
       
    85 						if (n && (!n.hasChildNodes() || (n.childNodes.length == 1 && n.firstChild.nodeName == 'BR')))
       
    86 							tinymce.dom.Event.cancel(e);
       
    87 					}
       
    88 				});
       
    89 			}
       
    90 
       
    91 			// Add undo level when new rows are created using the tab key
    89 			// Add undo level when new rows are created using the tab key
    92 			ed.onKeyDown.add(function(ed, e) {
    90 			ed.onKeyDown.add(function(ed, e) {
    93 				if (e.keyCode == 9 && ed.dom.getParent(ed.selection.getNode(), 'TABLE'))
    91 				if (e.keyCode == 9 && ed.dom.getParent(ed.selection.getNode(), 'TABLE')) {
       
    92 					if (!tinymce.isGecko && !tinymce.isOpera) {
       
    93 						tinyMCE.execInstanceCommand(ed.editorId, "mceTableMoveToNextRow", true);
       
    94 						return tinymce.dom.Event.cancel(e);
       
    95 					}
       
    96 
    94 					ed.undoManager.add();
    97 					ed.undoManager.add();
       
    98 				}
    95 			});
    99 			});
       
   100 
       
   101 			// Select whole table is a table border is clicked
       
   102 			if (!tinymce.isIE) {
       
   103 				if (ed.getParam('table_selection', true)) {
       
   104 					ed.onClick.add(function(ed, e) {
       
   105 						e = e.target;
       
   106 
       
   107 						if (e.nodeName === 'TABLE')
       
   108 							ed.selection.select(e);
       
   109 					});
       
   110 				}
       
   111 			}
    96 
   112 
    97 			ed.onNodeChange.add(function(ed, cm, n) {
   113 			ed.onNodeChange.add(function(ed, cm, n) {
    98 				var p = ed.dom.getParent(n, 'td,th,caption');
   114 				var p = ed.dom.getParent(n, 'td,th,caption');
    99 
   115 
   100 				cm.setActive('table', !!p);
   116 				cm.setActive('table', n.nodeName === 'TABLE' || !!p);
   101 				if (p && p.nodeName === 'CAPTION')
   117 				if (p && p.nodeName === 'CAPTION')
   102 					p = null;
   118 					p = null;
   103 
   119 
   104 				cm.setDisabled('delete_table', !p);
   120 				cm.setDisabled('delete_table', !p);
   105 				cm.setDisabled('delete_col', !p);
   121 				cm.setDisabled('delete_col', !p);
   112 				cm.setDisabled('row_props', !p);
   128 				cm.setDisabled('row_props', !p);
   113 				cm.setDisabled('cell_props', !p);
   129 				cm.setDisabled('cell_props', !p);
   114 				cm.setDisabled('split_cells', !p || (parseInt(ed.dom.getAttrib(p, 'colspan', '1')) < 2 && parseInt(ed.dom.getAttrib(p, 'rowspan', '1')) < 2));
   130 				cm.setDisabled('split_cells', !p || (parseInt(ed.dom.getAttrib(p, 'colspan', '1')) < 2 && parseInt(ed.dom.getAttrib(p, 'rowspan', '1')) < 2));
   115 				cm.setDisabled('merge_cells', !p);
   131 				cm.setDisabled('merge_cells', !p);
   116 			});
   132 			});
       
   133 
       
   134 			// Padd empty table cells
       
   135 			if (!tinymce.isIE) {
       
   136 				ed.onBeforeSetContent.add(function(ed, o) {
       
   137 					if (o.initial)
       
   138 						o.content = o.content.replace(/<(td|th)([^>]+|)>\s*<\/(td|th)>/g, tinymce.isOpera ? '<$1$2>&nbsp;</$1>' : '<$1$2><br mce_bogus="1" /></$1>');
       
   139 				});
       
   140 			}
   117 		},
   141 		},
   118 
   142 
   119 		execCommand : function(cmd, ui, val) {
   143 		execCommand : function(cmd, ui, val) {
   120 			var ed = this.editor, b;
   144 			var ed = this.editor, b;
   121 
   145 
   122 			// Is table command
   146 			// Is table command
   123 			switch (cmd) {
   147 			switch (cmd) {
       
   148 				case "mceTableMoveToNextRow":
   124 				case "mceInsertTable":
   149 				case "mceInsertTable":
   125 				case "mceTableRowProps":
   150 				case "mceTableRowProps":
   126 				case "mceTableCellProps":
   151 				case "mceTableCellProps":
   127 				case "mceTableSplitCells":
   152 				case "mceTableSplitCells":
   128 				case "mceTableMergeCells":
   153 				case "mceTableMergeCells":
   244 					return grid[row][col];
   269 					return grid[row][col];
   245 
   270 
   246 				return null;
   271 				return null;
   247 			}
   272 			}
   248 
   273 
       
   274 			function getNextCell(table, cell) {
       
   275 				var cells = [], x = 0, i, j, cell, nextCell;
       
   276 
       
   277 				for (i = 0; i < table.rows.length; i++)
       
   278 					for (j = 0; j < table.rows[i].cells.length; j++, x++)
       
   279 						cells[x] = table.rows[i].cells[j];
       
   280 
       
   281 				for (i = 0; i < cells.length; i++)
       
   282 					if (cells[i] == cell)
       
   283 						if (nextCell = cells[i+1])
       
   284 							return nextCell;
       
   285 			}
       
   286 
   249 			function getTableGrid(table) {
   287 			function getTableGrid(table) {
   250 				var grid = new Array(), rows = table.rows, x, y, td, sd, xstart, x2, y2;
   288 				var grid = [], rows = table.rows, x, y, td, sd, xstart, x2, y2;
   251 
   289 
   252 				for (y=0; y<rows.length; y++) {
   290 				for (y=0; y<rows.length; y++) {
   253 					for (x=0; x<rows[y].cells.length; x++) {
   291 					for (x=0; x<rows[y].cells.length; x++) {
   254 						td = rows[y].cells[x];
   292 						td = rows[y].cells[x];
   255 						sd = getColRowSpan(td);
   293 						sd = getColRowSpan(td);
   258 						for (xstart = x; grid[y] && grid[y][xstart]; xstart++) ;
   296 						for (xstart = x; grid[y] && grid[y][xstart]; xstart++) ;
   259 
   297 
   260 						// Fill box
   298 						// Fill box
   261 						for (y2=y; y2<y+sd['rowspan']; y2++) {
   299 						for (y2=y; y2<y+sd['rowspan']; y2++) {
   262 							if (!grid[y2])
   300 							if (!grid[y2])
   263 								grid[y2] = new Array();
   301 								grid[y2] = [];
   264 
   302 
   265 							for (x2=xstart; x2<xstart+sd['colspan']; x2++)
   303 							for (x2=xstart; x2<xstart+sd['colspan']; x2++)
   266 								grid[y2][x2] = td;
   304 								grid[y2][x2] = td;
   267 						}
   305 						}
   268 					}
   306 					}
   411 
   449 
   412 			// ---- Commands -----
   450 			// ---- Commands -----
   413 
   451 
   414 			// Handle commands
   452 			// Handle commands
   415 			switch (command) {
   453 			switch (command) {
       
   454 				case "mceTableMoveToNextRow":
       
   455 					var nextCell = getNextCell(tableElm, tdElm);
       
   456 
       
   457 					if (!nextCell) {
       
   458 						inst.execCommand("mceTableInsertRowAfter", tdElm);
       
   459 						nextCell = getNextCell(tableElm, tdElm);
       
   460 					}
       
   461 
       
   462 					inst.selection.select(nextCell);
       
   463 					inst.selection.collapse(true);
       
   464 
       
   465 					return true;
       
   466 
   416 				case "mceTableRowProps":
   467 				case "mceTableRowProps":
   417 					if (trElm == null)
   468 					if (trElm == null)
   418 						return true;
   469 						return true;
   419 
   470 
   420 					if (user_interface) {
   471 					if (user_interface) {
   839 										numCols = 1;
   890 										numCols = 1;
   840 
   891 
   841 									// Get rows and cells
   892 									// Get rows and cells
   842 									var tRows = tableElm.rows;
   893 									var tRows = tableElm.rows;
   843 									for (var y=cpos.rowindex; y<grid.length; y++) {
   894 									for (var y=cpos.rowindex; y<grid.length; y++) {
   844 										var rowCells = new Array();
   895 										var rowCells = [];
   845 
   896 
   846 										for (var x=cpos.cellindex; x<grid[y].length; x++) {
   897 										for (var x=cpos.cellindex; x<grid[y].length; x++) {
   847 											var td = getCell(grid, y, x);
   898 											var td = getCell(grid, y, x);
   848 
   899 
   849 											if (td && !inArray(rows, td) && !inArray(rowCells, td)) {
   900 											if (td && !inArray(rows, td) && !inArray(rowCells, td)) {
   855 											}
   906 											}
   856 										}
   907 										}
   857 
   908 
   858 										if (rowCells.length > 0)
   909 										if (rowCells.length > 0)
   859 											rows[rows.length] = rowCells;
   910 											rows[rows.length] = rowCells;
       
   911 
       
   912 										var td = getCell(grid, cpos.rowindex, cpos.cellindex);
       
   913 										each(ed.dom.select('br', td), function(e, i) {
       
   914 											if (i > 0 && ed.dom.getAttrib('mce_bogus'))
       
   915 												ed.dom.remove(e);
       
   916 										});
   860 									}
   917 									}
   861 
   918 
   862 									//return true;
   919 									//return true;
   863 								}
   920 								}
   864 							} else {
   921 							} else {
   878 									var tdElm = rng.startContainer.childNodes[rng.startOffset];
   935 									var tdElm = rng.startContainer.childNodes[rng.startOffset];
   879 
   936 
   880 									if (!tdElm)
   937 									if (!tdElm)
   881 										break;
   938 										break;
   882 
   939 
   883 									if (tdElm.nodeName == "TD")
   940 									if (tdElm.nodeName == "TD" || tdElm.nodeName == "TH")
   884 										cells[cells.length] = tdElm;
   941 										cells[cells.length] = tdElm;
   885 								}
   942 								}
   886 
   943 
   887 								// Get rows and cells
   944 								// Get rows and cells
   888 								var tRows = tableElm.rows;
   945 								var tRows = tableElm.rows;
   889 								for (var y=0; y<tRows.length; y++) {
   946 								for (var y=0; y<tRows.length; y++) {
   890 									var rowCells = new Array();
   947 									var rowCells = [];
   891 
   948 
   892 									for (var x=0; x<tRows[y].cells.length; x++) {
   949 									for (var x=0; x<tRows[y].cells.length; x++) {
   893 										var td = tRows[y].cells[x];
   950 										var td = tRows[y].cells[x];
   894 
   951 
   895 										for (var i=0; i<cells.length; i++) {
   952 										for (var i=0; i<cells.length; i++) {
   902 									if (rowCells.length > 0)
   959 									if (rowCells.length > 0)
   903 										rows[rows.length] = rowCells;
   960 										rows[rows.length] = rowCells;
   904 								}
   961 								}
   905 
   962 
   906 								// Find selected cells in grid and box
   963 								// Find selected cells in grid and box
   907 								var curRow = new Array();
   964 								var curRow = [];
   908 								var lastTR = null;
   965 								var lastTR = null;
   909 								for (var y=0; y<grid.length; y++) {
   966 								for (var y=0; y<grid.length; y++) {
   910 									for (var x=0; x<grid[y].length; x++) {
   967 									for (var x=0; x<grid[y].length; x++) {
   911 										grid[y][x]._selected = false;
   968 										grid[y][x]._selected = false;
   912 
   969 
  1029 										}
  1086 										}
  1030 									}
  1087 									}
  1031 								}
  1088 								}
  1032 							}
  1089 							}
  1033 
  1090 
       
  1091 							// Remove all but one bogus br
       
  1092 							each(ed.dom.select('br', tdElm), function(e, i) {
       
  1093 								if (i > 0 && ed.dom.getAttrib(e, 'mce_bogus'))
       
  1094 									ed.dom.remove(e);
       
  1095 							});
       
  1096 
  1034 							break;
  1097 							break;
  1035 						}
  1098 						}
  1036 
  1099 
  1037 						tableElm = inst.dom.getParent(inst.selection.getNode(), "table");
  1100 						tableElm = inst.dom.getParent(inst.selection.getNode(), "table");
  1038 						inst.addVisual(tableElm);
  1101 						inst.addVisual(tableElm);