From 8a4cc52bd62bdf7b06bf8919f208cdfb035a5816 Mon Sep 17 00:00:00 2001
From: Aleksander Machniak <alec@alec.pl>
Date: Tue, 08 May 2012 06:17:09 -0400
Subject: [PATCH] TinyMCE 3.5

---
 program/js/tiny_mce/plugins/table/editor_plugin_src.js |  168 ++++++++++++++++++++++++++++++++++++++-----------------
 1 files changed, 116 insertions(+), 52 deletions(-)

diff --git a/program/js/tiny_mce/plugins/table/editor_plugin_src.js b/program/js/tiny_mce/plugins/table/editor_plugin_src.js
index ccfe808..832b5e9 100644
--- a/program/js/tiny_mce/plugins/table/editor_plugin_src.js
+++ b/program/js/tiny_mce/plugins/table/editor_plugin_src.js
@@ -988,7 +988,7 @@
 						rng.endOffset == 0 && 
 						currentCell && 
 						(n.nodeName=="TR" || n==tableParent);
-					tableCellSelection = (n.nodeName=="TD"||n.nodeName=="TH")&& !currentCell;       
+					tableCellSelection = (n.nodeName=="TD"||n.nodeName=="TH")&& !currentCell;	   
 					return  allOfCellSelected || tableCellSelection;
 					// return false;
 				}
@@ -1000,7 +1000,7 @@
 
 					var rng = ed.selection.getRng();
 					var n = ed.selection.getNode();
-					var currentCell = ed.dom.getParent(rng.startContainer, 'TD');
+					var currentCell = ed.dom.getParent(rng.startContainer, 'TD,TH');
 				
 					if (!tableCellSelected(ed, rng, n, currentCell))
 						return;
@@ -1012,7 +1012,7 @@
 					var end = currentCell.lastChild;
 					while (end.lastChild)
 						end = end.lastChild;
-                    
+					
 					// Select the entire table cell. Nothing outside of the table cell should be selected.
 					rng.setEnd(end, end.nodeValue.length);
 					ed.selection.setRng(rng);
@@ -1074,31 +1074,87 @@
 				// Fix to allow navigating up and down in a table in WebKit browsers.
 				if (tinymce.isWebKit) {
 					function moveSelection(ed, e) {
+						var VK = tinymce.VK;
+						var key = e.keyCode;
+
+						function handle(upBool, sourceNode, event) {
+							var siblingDirection = upBool ? 'previousSibling' : 'nextSibling';
+							var currentRow = ed.dom.getParent(sourceNode, 'tr');
+							var siblingRow = currentRow[siblingDirection];
+
+							if (siblingRow) {
+								moveCursorToRow(ed, sourceNode, siblingRow, upBool);
+								tinymce.dom.Event.cancel(event);
+								return true;
+							} else {
+								var tableNode = ed.dom.getParent(currentRow, 'table');
+								var middleNode = currentRow.parentNode;
+								var parentNodeName = middleNode.nodeName.toLowerCase();
+								if (parentNodeName === 'tbody' || parentNodeName === (upBool ? 'tfoot' : 'thead')) {
+									var targetParent = getTargetParent(upBool, tableNode, middleNode, 'tbody');
+									if (targetParent !== null) {
+										return moveToRowInTarget(upBool, targetParent, sourceNode, event);
+									}
+								}
+								return escapeTable(upBool, currentRow, siblingDirection, tableNode, event);
+							}
+						}
+
+						function getTargetParent(upBool, topNode, secondNode, nodeName) {
+							var tbodies = ed.dom.select('>' + nodeName, topNode);
+							var position = tbodies.indexOf(secondNode);
+							if (upBool && position === 0 || !upBool && position === tbodies.length - 1) {
+								return getFirstHeadOrFoot(upBool, topNode);
+							} else if (position === -1) {
+								var topOrBottom = secondNode.tagName.toLowerCase() === 'thead' ? 0 : tbodies.length - 1;
+								return tbodies[topOrBottom];
+							} else {
+								return tbodies[position + (upBool ? -1 : 1)];
+							}
+						}
+
+						function getFirstHeadOrFoot(upBool, parent) {
+							var tagName = upBool ? 'thead' : 'tfoot';
+							var headOrFoot = ed.dom.select('>' + tagName, parent);
+							return headOrFoot.length !== 0 ? headOrFoot[0] : null;
+						}
+
+						function moveToRowInTarget(upBool, targetParent, sourceNode, event) {
+							var targetRow = getChildForDirection(targetParent, upBool);
+							targetRow && moveCursorToRow(ed, sourceNode, targetRow, upBool);
+							tinymce.dom.Event.cancel(event);
+							return true;
+						}
+
+						function escapeTable(upBool, currentRow, siblingDirection, table, event) {
+							var tableSibling = table[siblingDirection];
+							if (tableSibling) {
+								moveCursorToStartOfElement(tableSibling);
+								return true;
+							} else {
+								var parentCell = ed.dom.getParent(table, 'td,th');
+								if (parentCell) {
+									return handle(upBool, parentCell, event);
+								} else {
+									var backUpSibling = getChildForDirection(currentRow, !upBool);
+									moveCursorToStartOfElement(backUpSibling);
+									return tinymce.dom.Event.cancel(event);
+								}
+							}
+						}
+
+						function getChildForDirection(parent, up) {
+							var child =  parent && parent[up ? 'lastChild' : 'firstChild'];
+							// BR is not a valid table child to return in this case we return the table cell
+							return child && child.nodeName === 'BR' ? ed.dom.getParent(child, 'td,th') : child;
+						}
 
 						function moveCursorToStartOfElement(n) {
 							ed.selection.setCursorLocation(n, 0);
 						}
 
-						function getSibling(event, element) {
-							return event.keyCode == UP_ARROW ? element.previousSibling : element.nextSibling;
-						}
-
-						function getNextRow(e, row) {
-							var sibling = getSibling(e, row);
-							return sibling !== null && sibling.tagName === 'TR' ? sibling : null;
-						}
-
-						function getTable(ed, currentRow) {
-							return ed.dom.getParent(currentRow, 'table');
-						}
-
-						function getTableSibling(currentRow) {
-							var table = getTable(ed, currentRow);
-							return getSibling(e, table);
-						}
-
-						function isVerticalMovement(event) {
-							return event.keyCode == UP_ARROW || event.keyCode == DOWN_ARROW;
+						function isVerticalMovement() {
+							return key == VK.UP || key == VK.DOWN;
 						}
 
 						function isInTable(ed) {
@@ -1129,42 +1185,32 @@
 							return r;
 						}
 
-						function moveCursorToRow(ed, node, row) {
+						function moveCursorToRow(ed, node, row, upBool) {
 							var srcColumnIndex = columnIndex(ed.dom.getParent(node, 'td,th'));
-							var tgtColumnIndex = findColumn(row, srcColumnIndex)
+							var tgtColumnIndex = findColumn(row, srcColumnIndex);
 							var tgtNode = row.childNodes[tgtColumnIndex];
-							moveCursorToStartOfElement(tgtNode);
+							var rowCellTarget = getChildForDirection(tgtNode, upBool);
+							moveCursorToStartOfElement(rowCellTarget || tgtNode);
 						}
 
-						function escapeTable(currentRow, e) {
-							var tableSiblingElement = getTableSibling(currentRow);
-							if (tableSiblingElement !== null) {
-								moveCursorToStartOfElement(tableSiblingElement);
-								return tinymce.dom.Event.cancel(e);
-							} else {
-								var element = e.keyCode == UP_ARROW ? currentRow.firstChild : currentRow.lastChild;
-								// rely on default behaviour to escape table after we are in the last cell of the last row
-								moveCursorToStartOfElement(element);
-								return true;
-							}
+						function shouldFixCaret(preBrowserNode) {
+							var newNode = ed.selection.getNode();
+							var newParent = ed.dom.getParent(newNode, 'td,th');
+							var oldParent = ed.dom.getParent(preBrowserNode, 'td,th');
+							return newParent && newParent !== oldParent && checkSameParentTable(newParent, oldParent)
 						}
 
-						var UP_ARROW = 38;
-						var DOWN_ARROW = 40;
+						function checkSameParentTable(nodeOne, NodeTwo) {
+							return ed.dom.getParent(nodeOne, 'TABLE') === ed.dom.getParent(NodeTwo, 'TABLE');
+						}
 
-						if (isVerticalMovement(e) && isInTable(ed)) {
-							var node = ed.selection.getNode();
-							var currentRow = ed.dom.getParent(node, 'tr');
-							var nextRow = getNextRow(e, currentRow);
-
-							// If we're at the first or last row in the table, we should move the caret outside of the table
-							if (nextRow == null) {
-								return escapeTable(currentRow, e);
-							} else {
-								moveCursorToRow(ed, node, nextRow);
-								tinymce.dom.Event.cancel(e);
-								return true;
-							}
+						if (isVerticalMovement() && isInTable(ed)) {
+							var preBrowserNode = ed.selection.getNode();
+							setTimeout(function() {
+								if (shouldFixCaret(preBrowserNode)) {
+									handle(!e.shiftKey && key === VK.UP, preBrowserNode, e);
+								}
+							}, 0);
 						}
 					}
 
@@ -1223,6 +1269,24 @@
 							ed.dom.remove(last);
 					});
 
+
+					/**
+					 * Fixes bug in Gecko where shift-enter in table cell does not place caret on new line
+					 */
+					if (tinymce.isGecko) {
+						ed.onKeyDown.add(function(ed, e) {
+							if (e.keyCode === tinymce.VK.ENTER && e.shiftKey) {
+								var node = ed.selection.getRng().startContainer;
+								var tableCell = dom.getParent(node, 'td,th');
+								if (tableCell) {
+									var zeroSizedNbsp = ed.getDoc().createTextNode("\uFEFF");
+									dom.insertAfter(zeroSizedNbsp, node);
+								}
+							}
+						});
+					}
+
+
 					fixTableCaretPos();
 					ed.startContent = ed.getContent({format : 'raw'});
 				}

--
Gitblit v1.9.1