tinymce-rails 3.5b3 → 3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/tinymce/rails/helper.rb +6 -4
- data/lib/tinymce/rails/version.rb +2 -2
- data/vendor/assets/javascripts/tinymce/plugins/autolink/editor_plugin.js +1 -1
- data/vendor/assets/javascripts/tinymce/plugins/autolink/editor_plugin_src.js +6 -6
- data/vendor/assets/javascripts/tinymce/plugins/fullscreen/editor_plugin.js +1 -1
- data/vendor/assets/javascripts/tinymce/plugins/fullscreen/editor_plugin_src.js +1 -1
- data/vendor/assets/javascripts/tinymce/plugins/noneditable/editor_plugin.js +1 -1
- data/vendor/assets/javascripts/tinymce/plugins/noneditable/editor_plugin_src.js +86 -0
- data/vendor/assets/javascripts/tinymce/themes/advanced/editor_template.js +1 -1
- data/vendor/assets/javascripts/tinymce/themes/advanced/editor_template_src.js +16 -2
- data/vendor/assets/javascripts/tinymce/themes/advanced/js/image.js +4 -2
- data/vendor/assets/javascripts/tinymce/themes/advanced/skins/default/ui.css +5 -1
- data/vendor/assets/javascripts/tinymce/themes/advanced/skins/highcontrast/ui.css +5 -1
- data/vendor/assets/javascripts/tinymce/themes/advanced/skins/o2k7/ui.css +5 -1
- data/vendor/assets/javascripts/tinymce/tiny_mce.js +1 -1
- data/vendor/assets/javascripts/tinymce/tiny_mce_jquery.js +1 -1
- data/vendor/assets/javascripts/tinymce/tiny_mce_jquery_src.js +283 -137
- data/vendor/assets/javascripts/tinymce/tiny_mce_src.js +283 -118
- metadata +8 -12
| @@ -6,9 +6,9 @@ | |
| 6 6 | 
             
            	var tinymce = {
         | 
| 7 7 | 
             
            		majorVersion : '3',
         | 
| 8 8 |  | 
| 9 | 
            -
            		minorVersion : ' | 
| 9 | 
            +
            		minorVersion : '5',
         | 
| 10 10 |  | 
| 11 | 
            -
            		releaseDate : '2012-03 | 
| 11 | 
            +
            		releaseDate : '2012-05-03',
         | 
| 12 12 |  | 
| 13 13 | 
             
            		_init : function() {
         | 
| 14 14 | 
             
            			var t = this, d = document, na = navigator, ua = na.userAgent, i, nl, n, base, p, v;
         | 
| @@ -506,52 +506,64 @@ | |
| 506 506 | 
             
            tinymce.create('tinymce.util.Dispatcher', {
         | 
| 507 507 | 
             
            	scope : null,
         | 
| 508 508 | 
             
            	listeners : null,
         | 
| 509 | 
            +
            	inDispatch: false,
         | 
| 509 510 |  | 
| 510 | 
            -
            	Dispatcher : function( | 
| 511 | 
            -
            		this.scope =  | 
| 511 | 
            +
            	Dispatcher : function(scope) {
         | 
| 512 | 
            +
            		this.scope = scope || this;
         | 
| 512 513 | 
             
            		this.listeners = [];
         | 
| 513 514 | 
             
            	},
         | 
| 514 515 |  | 
| 515 | 
            -
            	add : function( | 
| 516 | 
            -
            		this.listeners.push({cb :  | 
| 516 | 
            +
            	add : function(callback, scope) {
         | 
| 517 | 
            +
            		this.listeners.push({cb : callback, scope : scope || this.scope});
         | 
| 517 518 |  | 
| 518 | 
            -
            		return  | 
| 519 | 
            +
            		return callback;
         | 
| 519 520 | 
             
            	},
         | 
| 520 521 |  | 
| 521 | 
            -
            	addToTop : function( | 
| 522 | 
            -
            		this | 
| 522 | 
            +
            	addToTop : function(callback, scope) {
         | 
| 523 | 
            +
            		var self = this, listener = {cb : callback, scope : scope || self.scope};
         | 
| 523 524 |  | 
| 524 | 
            -
            		 | 
| 525 | 
            +
            		// Create new listeners if addToTop is executed in a dispatch loop
         | 
| 526 | 
            +
            		if (self.inDispatch) {
         | 
| 527 | 
            +
            			self.listeners = [listener].concat(self.listeners);
         | 
| 528 | 
            +
            		} else {
         | 
| 529 | 
            +
            			self.listeners.unshift(listener);
         | 
| 530 | 
            +
            		}
         | 
| 531 | 
            +
             | 
| 532 | 
            +
            		return callback;
         | 
| 525 533 | 
             
            	},
         | 
| 526 534 |  | 
| 527 | 
            -
            	remove : function( | 
| 528 | 
            -
            		var  | 
| 535 | 
            +
            	remove : function(callback) {
         | 
| 536 | 
            +
            		var listeners = this.listeners, output = null;
         | 
| 529 537 |  | 
| 530 | 
            -
            		tinymce.each( | 
| 531 | 
            -
            			if ( | 
| 532 | 
            -
            				 | 
| 533 | 
            -
            				 | 
| 538 | 
            +
            		tinymce.each(listeners, function(listener, i) {
         | 
| 539 | 
            +
            			if (callback == listener.cb) {
         | 
| 540 | 
            +
            				output = listener;
         | 
| 541 | 
            +
            				listeners.splice(i, 1);
         | 
| 534 542 | 
             
            				return false;
         | 
| 535 543 | 
             
            			}
         | 
| 536 544 | 
             
            		});
         | 
| 537 545 |  | 
| 538 | 
            -
            		return  | 
| 546 | 
            +
            		return output;
         | 
| 539 547 | 
             
            	},
         | 
| 540 548 |  | 
| 541 549 | 
             
            	dispatch : function() {
         | 
| 542 | 
            -
            		var  | 
| 550 | 
            +
            		var self = this, returnValue, args = arguments, i, listeners = self.listeners, listener;
         | 
| 543 551 |  | 
| 552 | 
            +
            		self.inDispatch = true;
         | 
| 553 | 
            +
            		
         | 
| 544 554 | 
             
            		// Needs to be a real loop since the listener count might change while looping
         | 
| 545 555 | 
             
            		// And this is also more efficient
         | 
| 546 | 
            -
            		for (i = 0; i< | 
| 547 | 
            -
            			 | 
| 548 | 
            -
            			 | 
| 556 | 
            +
            		for (i = 0; i < listeners.length; i++) {
         | 
| 557 | 
            +
            			listener = listeners[i];
         | 
| 558 | 
            +
            			returnValue = listener.cb.apply(listener.scope, args.length > 0 ? args : [listener.scope]);
         | 
| 549 559 |  | 
| 550 | 
            -
            			if ( | 
| 560 | 
            +
            			if (returnValue === false)
         | 
| 551 561 | 
             
            				break;
         | 
| 552 562 | 
             
            		}
         | 
| 553 563 |  | 
| 554 | 
            -
            		 | 
| 564 | 
            +
            		self.inDispatch = false;
         | 
| 565 | 
            +
             | 
| 566 | 
            +
            		return returnValue;
         | 
| 555 567 | 
             
            	}
         | 
| 556 568 |  | 
| 557 569 | 
             
            	});
         | 
| @@ -1134,12 +1146,8 @@ tinymce.util.Quirks = function(editor) { | |
| 1134 1146 | 
             
            		editor.onKeyDown.add(function(editor, e) {
         | 
| 1135 1147 | 
             
            			var isDelete;
         | 
| 1136 1148 |  | 
| 1137 | 
            -
            			if (e.isDefaultPrevented()) {
         | 
| 1138 | 
            -
            				return;
         | 
| 1139 | 
            -
            			}
         | 
| 1140 | 
            -
             | 
| 1141 1149 | 
             
            			isDelete = e.keyCode == DELETE;
         | 
| 1142 | 
            -
            			if ((isDelete || e.keyCode == BACKSPACE) && !VK.modifierPressed(e)) {
         | 
| 1150 | 
            +
            			if (!e.isDefaultPrevented() && (isDelete || e.keyCode == BACKSPACE) && !VK.modifierPressed(e)) {
         | 
| 1143 1151 | 
             
            				e.preventDefault();
         | 
| 1144 1152 | 
             
            				removeMergedFormatSpans(isDelete);
         | 
| 1145 1153 | 
             
            			}
         | 
| @@ -1147,33 +1155,73 @@ tinymce.util.Quirks = function(editor) { | |
| 1147 1155 |  | 
| 1148 1156 | 
             
            		editor.addCommand('Delete', function() {removeMergedFormatSpans();});
         | 
| 1149 1157 | 
             
            	};
         | 
| 1150 | 
            -
             | 
| 1158 | 
            +
            	
         | 
| 1151 1159 | 
             
            	function emptyEditorWhenDeleting() {
         | 
| 1152 | 
            -
            		function  | 
| 1153 | 
            -
            			var  | 
| 1154 | 
            -
            			var contents = rng.cloneContents();
         | 
| 1155 | 
            -
            			body.appendChild(contents);
         | 
| 1156 | 
            -
            			return selection.serializer.serialize(body, {format: 'html'});
         | 
| 1157 | 
            -
            		}
         | 
| 1160 | 
            +
            		function getEndPointNode(rng, start) {
         | 
| 1161 | 
            +
            			var container, offset, prefix = start ? 'start' : 'end';
         | 
| 1158 1162 |  | 
| 1159 | 
            -
             | 
| 1160 | 
            -
            			 | 
| 1163 | 
            +
            			container = rng[prefix + 'Container'];
         | 
| 1164 | 
            +
            			offset = rng[prefix + 'Offset'];
         | 
| 1161 1165 |  | 
| 1162 | 
            -
            			 | 
| 1163 | 
            -
            			 | 
| 1166 | 
            +
            			// Resolve indexed container
         | 
| 1167 | 
            +
            			if (container.nodeType == 1 && container.hasChildNodes()) {
         | 
| 1168 | 
            +
            				container = container.childNodes[Math.min(start ? offset : (offset > 0 ? offset - 1 : 0), container.childNodes.length - 1)]
         | 
| 1169 | 
            +
            			}
         | 
| 1164 1170 |  | 
| 1165 | 
            -
            			 | 
| 1166 | 
            -
             | 
| 1167 | 
            -
             | 
| 1171 | 
            +
            			return container;
         | 
| 1172 | 
            +
            		};
         | 
| 1173 | 
            +
             | 
| 1174 | 
            +
            		function isAtStartEndOfBody(rng, start) {
         | 
| 1175 | 
            +
            			var container, offset, root, childNode, prefix = start ? 'start' : 'end', isAfter;
         | 
| 1176 | 
            +
             | 
| 1177 | 
            +
            			container = rng[prefix + 'Container'];
         | 
| 1178 | 
            +
            			offset = rng[prefix + 'Offset'];
         | 
| 1179 | 
            +
            			root = dom.getRoot();
         | 
| 1180 | 
            +
             | 
| 1181 | 
            +
            			// Resolve indexed container
         | 
| 1182 | 
            +
            			if (container.nodeType == 1) {
         | 
| 1183 | 
            +
            				isAfter = offset >= container.childNodes.length;
         | 
| 1184 | 
            +
            				container = getEndPointNode(rng, start);
         | 
| 1185 | 
            +
             | 
| 1186 | 
            +
            				if (container.nodeType == 3) {
         | 
| 1187 | 
            +
            					offset = start && !isAfter ? 0 : container.nodeValue.length;
         | 
| 1188 | 
            +
            				}
         | 
| 1189 | 
            +
            			}
         | 
| 1190 | 
            +
             | 
| 1191 | 
            +
            			// Check if start/end is in the middle of text
         | 
| 1192 | 
            +
            			if (container.nodeType == 3 && ((start && offset > 0) || (!start && offset < container.nodeValue.length))) {
         | 
| 1193 | 
            +
            				return false;
         | 
| 1194 | 
            +
            			}
         | 
| 1195 | 
            +
             | 
| 1196 | 
            +
            			// Walk up the DOM tree to see if the endpoint is at the beginning/end of body
         | 
| 1197 | 
            +
            			while (container !== root) {
         | 
| 1198 | 
            +
            				childNode = container.parentNode[start ? 'firstChild' : 'lastChild'];
         | 
| 1199 | 
            +
             | 
| 1200 | 
            +
            				// If first/last element is a BR then jump to it's sibling in case: <p>x<br></p>
         | 
| 1201 | 
            +
            				if (childNode.nodeName == "BR") {
         | 
| 1202 | 
            +
            					childNode = childNode[start ? 'nextSibling' : 'previousSibling'] || childNode;
         | 
| 1203 | 
            +
            				}
         | 
| 1204 | 
            +
             | 
| 1205 | 
            +
            				// If the childNode isn't the container node then break in case <p><span>A</span>[X]</p>
         | 
| 1206 | 
            +
            				if (childNode !== container) {
         | 
| 1207 | 
            +
            					return false;
         | 
| 1208 | 
            +
            				}
         | 
| 1209 | 
            +
             | 
| 1210 | 
            +
            				container = container.parentNode;
         | 
| 1211 | 
            +
            			}
         | 
| 1212 | 
            +
             | 
| 1213 | 
            +
            			return true;
         | 
| 1214 | 
            +
            		};
         | 
| 1168 1215 |  | 
| 1169 1216 | 
             
            		editor.onKeyDown.addToTop(function(editor, e) {
         | 
| 1170 | 
            -
            			var keyCode = e.keyCode;
         | 
| 1217 | 
            +
            			var rng, keyCode = e.keyCode;
         | 
| 1171 1218 |  | 
| 1172 | 
            -
            			if (keyCode == DELETE || keyCode == BACKSPACE) {
         | 
| 1173 | 
            -
            				 | 
| 1219 | 
            +
            			if (!e.isDefaultPrevented() && (keyCode == DELETE || keyCode == BACKSPACE)) {
         | 
| 1220 | 
            +
            				rng = selection.getRng(true);
         | 
| 1174 1221 |  | 
| 1175 | 
            -
            				if ( | 
| 1176 | 
            -
            					 | 
| 1222 | 
            +
            				if (isAtStartEndOfBody(rng, true) && isAtStartEndOfBody(rng, false) &&
         | 
| 1223 | 
            +
            					(rng.collapsed || dom.findCommonAncestor(getEndPointNode(rng, true), getEndPointNode(rng)) === dom.getRoot())) {
         | 
| 1224 | 
            +
            					editor.setContent('');
         | 
| 1177 1225 | 
             
            					editor.nodeChanged();
         | 
| 1178 1226 | 
             
            					e.preventDefault();
         | 
| 1179 1227 | 
             
            				}
         | 
| @@ -1182,14 +1230,25 @@ tinymce.util.Quirks = function(editor) { | |
| 1182 1230 | 
             
            	};
         | 
| 1183 1231 |  | 
| 1184 1232 | 
             
            	function inputMethodFocus() {
         | 
| 1185 | 
            -
            		 | 
| 1186 | 
            -
            			 | 
| 1187 | 
            -
             | 
| 1233 | 
            +
            		if (!editor.settings.content_editable) {
         | 
| 1234 | 
            +
            			// Case 1 IME doesn't initialize if you focus the document
         | 
| 1235 | 
            +
            			dom.bind(editor.getDoc(), 'focusin', function(e) {
         | 
| 1236 | 
            +
            				selection.setRng(selection.getRng());
         | 
| 1237 | 
            +
            			});
         | 
| 1238 | 
            +
             | 
| 1239 | 
            +
            			// Case 2 IME doesn't initialize if you click the documentElement it also doesn't properly fire the focusin event
         | 
| 1240 | 
            +
            			dom.bind(editor.getDoc(), 'mousedown', function(e) {
         | 
| 1241 | 
            +
            				if (e.target == editor.getDoc().documentElement) {
         | 
| 1242 | 
            +
            					editor.getWin().focus();
         | 
| 1243 | 
            +
            					selection.setRng(selection.getRng());
         | 
| 1244 | 
            +
            				}
         | 
| 1245 | 
            +
            			});
         | 
| 1246 | 
            +
            		}
         | 
| 1188 1247 | 
             
            	};
         | 
| 1189 1248 |  | 
| 1190 1249 | 
             
            	function removeHrOnBackspace() {
         | 
| 1191 1250 | 
             
            		editor.onKeyDown.add(function(editor, e) {
         | 
| 1192 | 
            -
            			if (e.keyCode === BACKSPACE) {
         | 
| 1251 | 
            +
            			if (!e.isDefaultPrevented() && e.keyCode === BACKSPACE) {
         | 
| 1193 1252 | 
             
            				if (selection.isCollapsed() && selection.getRng(true).startOffset === 0) {
         | 
| 1194 1253 | 
             
            					var node = selection.getNode();
         | 
| 1195 1254 | 
             
            					var previousSibling = node.previousSibling;
         | 
| @@ -1322,7 +1381,7 @@ tinymce.util.Quirks = function(editor) { | |
| 1322 1381 |  | 
| 1323 1382 | 
             
            	function disableBackspaceIntoATable() {
         | 
| 1324 1383 | 
             
            		editor.onKeyDown.add(function(editor, e) {
         | 
| 1325 | 
            -
            			if (e.keyCode === BACKSPACE) {
         | 
| 1384 | 
            +
            			if (!e.isDefaultPrevented() && e.keyCode === BACKSPACE) {
         | 
| 1326 1385 | 
             
            				if (selection.isCollapsed() && selection.getRng(true).startOffset === 0) {
         | 
| 1327 1386 | 
             
            					var previousSibling = selection.getNode().previousSibling;
         | 
| 1328 1387 | 
             
            					if (previousSibling && previousSibling.nodeName && previousSibling.nodeName.toLowerCase() === "table") {
         | 
| @@ -1410,12 +1469,8 @@ tinymce.util.Quirks = function(editor) { | |
| 1410 1469 | 
             
            		editor.onKeyDown.add(function(editor, e) {
         | 
| 1411 1470 | 
             
            			var isDelete, rng, container, offset, brElm, sibling, collapsed;
         | 
| 1412 1471 |  | 
| 1413 | 
            -
            			if (e.isDefaultPrevented()) {
         | 
| 1414 | 
            -
            				return;
         | 
| 1415 | 
            -
            			}
         | 
| 1416 | 
            -
             | 
| 1417 1472 | 
             
            			isDelete = e.keyCode == DELETE;
         | 
| 1418 | 
            -
            			if ((isDelete || e.keyCode == BACKSPACE) && !VK.modifierPressed(e)) {
         | 
| 1473 | 
            +
            			if (!e.isDefaultPrevented() && (isDelete || e.keyCode == BACKSPACE) && !VK.modifierPressed(e)) {
         | 
| 1419 1474 | 
             
            				rng = selection.getRng();
         | 
| 1420 1475 | 
             
            				container = rng.startContainer;
         | 
| 1421 1476 | 
             
            				offset = rng.startOffset;
         | 
| @@ -1455,7 +1510,7 @@ tinymce.util.Quirks = function(editor) { | |
| 1455 1510 | 
             
            		editor.onKeyDown.add(function(editor, e) {
         | 
| 1456 1511 | 
             
            			var rng, container, offset, root, parent;
         | 
| 1457 1512 |  | 
| 1458 | 
            -
            			if (e.keyCode != VK.BACKSPACE) {
         | 
| 1513 | 
            +
            			if (e.isDefaultPrevented() || e.keyCode != VK.BACKSPACE) {
         | 
| 1459 1514 | 
             
            				return;
         | 
| 1460 1515 | 
             
            			}
         | 
| 1461 1516 |  | 
| @@ -1469,7 +1524,7 @@ tinymce.util.Quirks = function(editor) { | |
| 1469 1524 | 
             
            				return;
         | 
| 1470 1525 | 
             
            			}
         | 
| 1471 1526 |  | 
| 1472 | 
            -
            			while (parent && parent.parentNode.firstChild == parent && parent.parentNode != root) {
         | 
| 1527 | 
            +
            			while (parent && parent.parentNode && parent.parentNode.firstChild == parent && parent.parentNode != root) {
         | 
| 1473 1528 | 
             
            				parent = parent.parentNode;
         | 
| 1474 1529 | 
             
            			}
         | 
| 1475 1530 |  | 
| @@ -1547,7 +1602,7 @@ tinymce.util.Quirks = function(editor) { | |
| 1547 1602 |  | 
| 1548 1603 | 
             
            	function deleteImageOnBackSpace() {
         | 
| 1549 1604 | 
             
            		editor.onKeyDown.add(function(editor, e) {
         | 
| 1550 | 
            -
            			if (e.keyCode == 8 && selection.getNode().nodeName == 'IMG') {
         | 
| 1605 | 
            +
            			if (!e.isDefaultPrevented() && e.keyCode == 8 && selection.getNode().nodeName == 'IMG') {
         | 
| 1551 1606 | 
             
            				e.preventDefault();
         | 
| 1552 1607 | 
             
            				editor.undoManager.beforeChange();
         | 
| 1553 1608 | 
             
            				dom.remove(selection.getNode());
         | 
| @@ -1559,12 +1614,12 @@ tinymce.util.Quirks = function(editor) { | |
| 1559 1614 | 
             
            	// All browsers
         | 
| 1560 1615 | 
             
            	disableBackspaceIntoATable();
         | 
| 1561 1616 | 
             
            	removeBlockQuoteOnBackSpace();
         | 
| 1617 | 
            +
            	emptyEditorWhenDeleting();
         | 
| 1562 1618 |  | 
| 1563 1619 | 
             
            	// WebKit
         | 
| 1564 1620 | 
             
            	if (tinymce.isWebKit) {
         | 
| 1565 1621 | 
             
            		keepInlineElementOnDeleteBackspace();
         | 
| 1566 1622 | 
             
            		cleanupStylesWhenDeleting();
         | 
| 1567 | 
            -
            		emptyEditorWhenDeleting();
         | 
| 1568 1623 | 
             
            		inputMethodFocus();
         | 
| 1569 1624 | 
             
            		selectControlElements();
         | 
| 1570 1625 |  | 
| @@ -1577,7 +1632,6 @@ tinymce.util.Quirks = function(editor) { | |
| 1577 1632 | 
             
            	// IE
         | 
| 1578 1633 | 
             
            	if (tinymce.isIE) {
         | 
| 1579 1634 | 
             
            		removeHrOnBackspace();
         | 
| 1580 | 
            -
            		emptyEditorWhenDeleting();
         | 
| 1581 1635 | 
             
            		ensureBodyHasRoleApplication();
         | 
| 1582 1636 | 
             
            		addNewLinesBeforeBrInPre();
         | 
| 1583 1637 | 
             
            		removePreSerializedStylesWhenSelectingControls();
         | 
| @@ -3459,7 +3513,7 @@ tinymce.html.Styles = function(settings, schema) { | |
| 3459 3513 | 
             
            		self.parse = function(html, args) {
         | 
| 3460 3514 | 
             
            			var parser, rootNode, node, nodes, i, l, fi, fl, list, name, validate,
         | 
| 3461 3515 | 
             
            				blockElements, startWhiteSpaceRegExp, invalidChildren = [], isInWhiteSpacePreservedElement,
         | 
| 3462 | 
            -
            				endWhiteSpaceRegExp, allWhiteSpaceRegExp, whiteSpaceElements, children, nonEmptyElements, rootBlockName;
         | 
| 3516 | 
            +
            				endWhiteSpaceRegExp, allWhiteSpaceRegExp, isAllWhiteSpaceRegExp, whiteSpaceElements, children, nonEmptyElements, rootBlockName;
         | 
| 3463 3517 |  | 
| 3464 3518 | 
             
            			args = args || {};
         | 
| 3465 3519 | 
             
            			matchedNodes = {};
         | 
| @@ -3474,6 +3528,7 @@ tinymce.html.Styles = function(settings, schema) { | |
| 3474 3528 | 
             
            			startWhiteSpaceRegExp = /^[ \t\r\n]+/;
         | 
| 3475 3529 | 
             
            			endWhiteSpaceRegExp = /[ \t\r\n]+$/;
         | 
| 3476 3530 | 
             
            			allWhiteSpaceRegExp = /[ \t\r\n]+/g;
         | 
| 3531 | 
            +
            			isAllWhiteSpaceRegExp = /^[ \t\r\n]+$/;
         | 
| 3477 3532 |  | 
| 3478 3533 | 
             
            			function addRootBlocks() {
         | 
| 3479 3534 | 
             
            				var node = rootNode.firstChild, next, rootBlockNode;
         | 
| @@ -3626,10 +3681,12 @@ tinymce.html.Styles = function(settings, schema) { | |
| 3626 3681 | 
             
            					if (elementRule) {
         | 
| 3627 3682 | 
             
            						if (blockElements[name]) {
         | 
| 3628 3683 | 
             
            							if (!isInWhiteSpacePreservedElement) {
         | 
| 3629 | 
            -
            								// Trim whitespace  | 
| 3630 | 
            -
            								 | 
| 3684 | 
            +
            								// Trim whitespace of the first node in a block
         | 
| 3685 | 
            +
            								textNode = node.firstChild;
         | 
| 3686 | 
            +
            								if (textNode && textNode.type === 3) {
         | 
| 3631 3687 | 
             
            									text = textNode.value.replace(startWhiteSpaceRegExp, '');
         | 
| 3632 3688 |  | 
| 3689 | 
            +
            									// Any characters left after trim or should we remove it
         | 
| 3633 3690 | 
             
            									if (text.length > 0) {
         | 
| 3634 3691 | 
             
            										textNode.value = text;
         | 
| 3635 3692 | 
             
            										textNode = textNode.next;
         | 
| @@ -3638,12 +3695,27 @@ tinymce.html.Styles = function(settings, schema) { | |
| 3638 3695 | 
             
            										textNode.remove();
         | 
| 3639 3696 | 
             
            										textNode = sibling;
         | 
| 3640 3697 | 
             
            									}
         | 
| 3698 | 
            +
             | 
| 3699 | 
            +
            									// Remove any pure whitespace siblings
         | 
| 3700 | 
            +
            									while (textNode && textNode.type === 3) {
         | 
| 3701 | 
            +
            										text = textNode.value;
         | 
| 3702 | 
            +
            										sibling = textNode.next;
         | 
| 3703 | 
            +
             | 
| 3704 | 
            +
            										if (text.length === 0 || isAllWhiteSpaceRegExp.test(text)) {
         | 
| 3705 | 
            +
            											textNode.remove();
         | 
| 3706 | 
            +
            											textNode = sibling;
         | 
| 3707 | 
            +
            										}
         | 
| 3708 | 
            +
             | 
| 3709 | 
            +
            										textNode = sibling;
         | 
| 3710 | 
            +
            									}
         | 
| 3641 3711 | 
             
            								}
         | 
| 3642 3712 |  | 
| 3643 | 
            -
            								// Trim whitespace  | 
| 3644 | 
            -
            								 | 
| 3713 | 
            +
            								// Trim whitespace of the last node in a block
         | 
| 3714 | 
            +
            								textNode = node.lastChild;
         | 
| 3715 | 
            +
            								if (textNode && textNode.type === 3) {
         | 
| 3645 3716 | 
             
            									text = textNode.value.replace(endWhiteSpaceRegExp, '');
         | 
| 3646 3717 |  | 
| 3718 | 
            +
            									// Any characters left after trim or should we remove it
         | 
| 3647 3719 | 
             
            									if (text.length > 0) {
         | 
| 3648 3720 | 
             
            										textNode.value = text;
         | 
| 3649 3721 | 
             
            										textNode = textNode.prev;
         | 
| @@ -3652,6 +3724,19 @@ tinymce.html.Styles = function(settings, schema) { | |
| 3652 3724 | 
             
            										textNode.remove();
         | 
| 3653 3725 | 
             
            										textNode = sibling;
         | 
| 3654 3726 | 
             
            									}
         | 
| 3727 | 
            +
             | 
| 3728 | 
            +
            									// Remove any pure whitespace siblings
         | 
| 3729 | 
            +
            									while (textNode && textNode.type === 3) {
         | 
| 3730 | 
            +
            										text = textNode.value;
         | 
| 3731 | 
            +
            										sibling = textNode.prev;
         | 
| 3732 | 
            +
             | 
| 3733 | 
            +
            										if (text.length === 0 || isAllWhiteSpaceRegExp.test(text)) {
         | 
| 3734 | 
            +
            											textNode.remove();
         | 
| 3735 | 
            +
            											textNode = sibling;
         | 
| 3736 | 
            +
            										}
         | 
| 3737 | 
            +
             | 
| 3738 | 
            +
            										textNode = sibling;
         | 
| 3739 | 
            +
            									}
         | 
| 3655 3740 | 
             
            								}
         | 
| 3656 3741 | 
             
            							}
         | 
| 3657 3742 |  | 
| @@ -4532,7 +4617,11 @@ tinymce.dom = {}; | |
| 4532 4617 | 
             
            			return self.bind(target, events instanceof Array ? events.join(' ') : events, func, scope);
         | 
| 4533 4618 | 
             
            		};
         | 
| 4534 4619 |  | 
| 4535 | 
            -
            		self.remove = function(target, events, func) {
         | 
| 4620 | 
            +
            		self.remove = function(target, events, func, scope) {
         | 
| 4621 | 
            +
            			if (!target) {
         | 
| 4622 | 
            +
            				return self;
         | 
| 4623 | 
            +
            			}
         | 
| 4624 | 
            +
             | 
| 4536 4625 | 
             
            			// Old API supported direct ID assignment
         | 
| 4537 4626 | 
             
            			if (typeof(target) === "string") {
         | 
| 4538 4627 | 
             
            				target = document.getElementById(target);
         | 
| @@ -4540,7 +4629,7 @@ tinymce.dom = {}; | |
| 4540 4629 |  | 
| 4541 4630 | 
             
            			// Old API supported multiple targets
         | 
| 4542 4631 | 
             
            			if (target instanceof Array) {
         | 
| 4543 | 
            -
            				var i = target;
         | 
| 4632 | 
            +
            				var i = target.length;
         | 
| 4544 4633 |  | 
| 4545 4634 | 
             
            				while (i--) {
         | 
| 4546 4635 | 
             
            					self.remove(target[i], events, func, scope);
         | 
| @@ -8967,6 +9056,29 @@ window.tinymce.dom.Sizzle = Sizzle; | |
| 8967 9056 | 
             
            				return index;
         | 
| 8968 9057 | 
             
            			};
         | 
| 8969 9058 |  | 
| 9059 | 
            +
            			function normalizeTableCellSelection(rng) {
         | 
| 9060 | 
            +
            				function moveEndPoint(start) {
         | 
| 9061 | 
            +
            					var container, offset, childNodes, prefix = start ? 'start' : 'end';
         | 
| 9062 | 
            +
             | 
| 9063 | 
            +
            					container = rng[prefix + 'Container'];
         | 
| 9064 | 
            +
            					offset = rng[prefix + 'Offset'];
         | 
| 9065 | 
            +
             | 
| 9066 | 
            +
            					if (container.nodeType == 1 && container.nodeName == "TR") {
         | 
| 9067 | 
            +
            						childNodes = container.childNodes;
         | 
| 9068 | 
            +
            						container = childNodes[Math.min(start ? offset : offset - 1, childNodes.length - 1)];
         | 
| 9069 | 
            +
            						if (container) {
         | 
| 9070 | 
            +
            							offset = start ? 0 : container.childNodes.length;
         | 
| 9071 | 
            +
            							rng['set' + (start ? 'Start' : 'End')](container, offset);
         | 
| 9072 | 
            +
            						}
         | 
| 9073 | 
            +
            					}
         | 
| 9074 | 
            +
            				};
         | 
| 9075 | 
            +
             | 
| 9076 | 
            +
            				moveEndPoint(true);
         | 
| 9077 | 
            +
            				moveEndPoint();
         | 
| 9078 | 
            +
             | 
| 9079 | 
            +
            				return rng;
         | 
| 9080 | 
            +
            			};
         | 
| 9081 | 
            +
             | 
| 8970 9082 | 
             
            			function getLocation() {
         | 
| 8971 9083 | 
             
            				var rng = t.getRng(true), root = dom.getRoot(), bookmark = {};
         | 
| 8972 9084 |  | 
| @@ -9061,13 +9173,8 @@ window.tinymce.dom.Sizzle = Sizzle; | |
| 9061 9173 | 
             
            				if (name == 'IMG')
         | 
| 9062 9174 | 
             
            					return {name : name, index : findIndex(name, element)};
         | 
| 9063 9175 |  | 
| 9064 | 
            -
            				// Can't insert a node into the root of document WebKit defaults to document
         | 
| 9065 | 
            -
            				if (rng.startContainer.nodeType == 9) {
         | 
| 9066 | 
            -
            					return;
         | 
| 9067 | 
            -
            				}
         | 
| 9068 | 
            -
             | 
| 9069 9176 | 
             
            				// W3C method
         | 
| 9070 | 
            -
            				rng2 = rng.cloneRange();
         | 
| 9177 | 
            +
            				rng2 = normalizeTableCellSelection(rng.cloneRange());
         | 
| 9071 9178 |  | 
| 9072 9179 | 
             
            				// Insert end marker
         | 
| 9073 9180 | 
             
            				if (!collapsed) {
         | 
| @@ -9075,6 +9182,7 @@ window.tinymce.dom.Sizzle = Sizzle; | |
| 9075 9182 | 
             
            					rng2.insertNode(dom.create('span', {'data-mce-type' : "bookmark", id : id + '_end', style : styles}, chr));
         | 
| 9076 9183 | 
             
            				}
         | 
| 9077 9184 |  | 
| 9185 | 
            +
            				rng = normalizeTableCellSelection(rng);
         | 
| 9078 9186 | 
             
            				rng.collapse(true);
         | 
| 9079 9187 | 
             
            				rng.insertNode(dom.create('span', {'data-mce-type' : "bookmark", id : id + '_start', style : styles}, chr));
         | 
| 9080 9188 | 
             
            			}
         | 
| @@ -9299,48 +9407,58 @@ window.tinymce.dom.Sizzle = Sizzle; | |
| 9299 9407 | 
             
            		},
         | 
| 9300 9408 |  | 
| 9301 9409 | 
             
            		getRng : function(w3c) {
         | 
| 9302 | 
            -
            			var  | 
| 9410 | 
            +
            			var self = this, selection, rng, elm, doc = self.win.document;
         | 
| 9303 9411 |  | 
| 9304 9412 | 
             
            			// Found tridentSel object then we need to use that one
         | 
| 9305 | 
            -
            			if (w3c &&  | 
| 9306 | 
            -
            				return  | 
| 9413 | 
            +
            			if (w3c && self.tridentSel) {
         | 
| 9414 | 
            +
            				return self.tridentSel.getRangeAt(0);
         | 
| 9415 | 
            +
            			}
         | 
| 9307 9416 |  | 
| 9308 9417 | 
             
            			try {
         | 
| 9309 | 
            -
            				if ( | 
| 9310 | 
            -
            					 | 
| 9418 | 
            +
            				if (selection = self.getSel()) {
         | 
| 9419 | 
            +
            					rng = selection.rangeCount > 0 ? selection.getRangeAt(0) : (selection.createRange ? selection.createRange() : doc.createRange());
         | 
| 9420 | 
            +
            				}
         | 
| 9311 9421 | 
             
            			} catch (ex) {
         | 
| 9312 9422 | 
             
            				// IE throws unspecified error here if TinyMCE is placed in a frame/iframe
         | 
| 9313 9423 | 
             
            			}
         | 
| 9314 9424 |  | 
| 9315 9425 | 
             
            			// We have W3C ranges and it's IE then fake control selection since IE9 doesn't handle that correctly yet
         | 
| 9316 | 
            -
            			if (tinymce.isIE &&  | 
| 9426 | 
            +
            			if (tinymce.isIE && rng && rng.setStart && doc.selection.createRange().item) {
         | 
| 9317 9427 | 
             
            				elm = doc.selection.createRange().item(0);
         | 
| 9318 | 
            -
            				 | 
| 9319 | 
            -
            				 | 
| 9320 | 
            -
            				 | 
| 9428 | 
            +
            				rng = doc.createRange();
         | 
| 9429 | 
            +
            				rng.setStartBefore(elm);
         | 
| 9430 | 
            +
            				rng.setEndAfter(elm);
         | 
| 9321 9431 | 
             
            			}
         | 
| 9322 9432 |  | 
| 9323 9433 | 
             
            			// No range found then create an empty one
         | 
| 9324 9434 | 
             
            			// This can occur when the editor is placed in a hidden container element on Gecko
         | 
| 9325 9435 | 
             
            			// Or on IE when there was an exception
         | 
| 9326 | 
            -
            			if (! | 
| 9327 | 
            -
            				 | 
| 9436 | 
            +
            			if (!rng) {
         | 
| 9437 | 
            +
            				rng = doc.createRange ? doc.createRange() : doc.body.createTextRange();
         | 
| 9438 | 
            +
            			}
         | 
| 9328 9439 |  | 
| 9329 | 
            -
            			 | 
| 9330 | 
            -
             | 
| 9440 | 
            +
            			// If range is at start of document then move it to start of body
         | 
| 9441 | 
            +
            			if (rng.setStart && rng.startContainer.nodeType === 9 && rng.collapsed) {
         | 
| 9442 | 
            +
            				elm = self.dom.getRoot();
         | 
| 9443 | 
            +
            				rng.setStart(elm, 0);
         | 
| 9444 | 
            +
            				rng.setEnd(elm, 0);
         | 
| 9445 | 
            +
            			}
         | 
| 9446 | 
            +
             | 
| 9447 | 
            +
            			if (self.selectedRange && self.explicitRange) {
         | 
| 9448 | 
            +
            				if (rng.compareBoundaryPoints(rng.START_TO_START, self.selectedRange) === 0 && rng.compareBoundaryPoints(rng.END_TO_END, self.selectedRange) === 0) {
         | 
| 9331 9449 | 
             
            					// Safari, Opera and Chrome only ever select text which causes the range to change.
         | 
| 9332 9450 | 
             
            					// This lets us use the originally set range if the selection hasn't been changed by the user.
         | 
| 9333 | 
            -
            					 | 
| 9451 | 
            +
            					rng = self.explicitRange;
         | 
| 9334 9452 | 
             
            				} else {
         | 
| 9335 | 
            -
            					 | 
| 9336 | 
            -
            					 | 
| 9453 | 
            +
            					self.selectedRange = null;
         | 
| 9454 | 
            +
            					self.explicitRange = null;
         | 
| 9337 9455 | 
             
            				}
         | 
| 9338 9456 | 
             
            			}
         | 
| 9339 9457 |  | 
| 9340 | 
            -
            			return  | 
| 9458 | 
            +
            			return rng;
         | 
| 9341 9459 | 
             
            		},
         | 
| 9342 9460 |  | 
| 9343 | 
            -
            		setRng : function(r) {
         | 
| 9461 | 
            +
            		setRng : function(r, forward) {
         | 
| 9344 9462 | 
             
            			var s, t = this;
         | 
| 9345 9463 |  | 
| 9346 9464 | 
             
            			if (!t.tridentSel) {
         | 
| @@ -9356,6 +9474,13 @@ window.tinymce.dom.Sizzle = Sizzle; | |
| 9356 9474 | 
             
            					}
         | 
| 9357 9475 |  | 
| 9358 9476 | 
             
            					s.addRange(r);
         | 
| 9477 | 
            +
             | 
| 9478 | 
            +
            					// Forward is set to false and we have an extend function
         | 
| 9479 | 
            +
            					if (forward === false && s.extend) {
         | 
| 9480 | 
            +
            						s.collapse(r.endContainer, r.endOffset);
         | 
| 9481 | 
            +
            						s.extend(r.startContainer, r.startOffset);
         | 
| 9482 | 
            +
            					}
         | 
| 9483 | 
            +
             | 
| 9359 9484 | 
             
            					// adding range isn't always successful so we need to check range count otherwise an exception can occur
         | 
| 9360 9485 | 
             
            					t.selectedRange = s.rangeCount > 0 ? s.getRangeAt(0) : null;
         | 
| 9361 9486 | 
             
            				}
         | 
| @@ -9471,12 +9596,41 @@ window.tinymce.dom.Sizzle = Sizzle; | |
| 9471 9596 | 
             
            			return bl;
         | 
| 9472 9597 | 
             
            		},
         | 
| 9473 9598 |  | 
| 9599 | 
            +
            		isForward: function(){
         | 
| 9600 | 
            +
            			var dom = this.dom, sel = this.getSel(), anchorRange, focusRange;
         | 
| 9601 | 
            +
             | 
| 9602 | 
            +
            			// No support for selection direction then always return true
         | 
| 9603 | 
            +
            			if (!sel || sel.anchorNode == null || sel.focusNode == null) {
         | 
| 9604 | 
            +
            				return true;
         | 
| 9605 | 
            +
            			}
         | 
| 9606 | 
            +
             | 
| 9607 | 
            +
            			anchorRange = dom.createRng();
         | 
| 9608 | 
            +
            			anchorRange.setStart(sel.anchorNode, sel.anchorOffset);
         | 
| 9609 | 
            +
            			anchorRange.collapse(true);
         | 
| 9610 | 
            +
             | 
| 9611 | 
            +
            			focusRange = dom.createRng();
         | 
| 9612 | 
            +
            			focusRange.setStart(sel.focusNode, sel.focusOffset);
         | 
| 9613 | 
            +
            			focusRange.collapse(true);
         | 
| 9614 | 
            +
             | 
| 9615 | 
            +
            			return anchorRange.compareBoundaryPoints(anchorRange.START_TO_START, focusRange) <= 0;
         | 
| 9616 | 
            +
            		},
         | 
| 9617 | 
            +
             | 
| 9474 9618 | 
             
            		normalize : function() {
         | 
| 9475 | 
            -
            			var self = this, rng, normalized, collapsed;
         | 
| 9619 | 
            +
            			var self = this, rng, normalized, collapsed, node, sibling;
         | 
| 9476 9620 |  | 
| 9477 9621 | 
             
            			function normalizeEndPoint(start) {
         | 
| 9478 9622 | 
             
            				var container, offset, walker, dom = self.dom, body = dom.getRoot(), node, nonEmptyElementsMap, nodeName;
         | 
| 9479 9623 |  | 
| 9624 | 
            +
            				function hasBrBeforeAfter(node, left) {
         | 
| 9625 | 
            +
            					var walker = new TreeWalker(node, dom.getParent(node.parentNode, dom.isBlock) || body);
         | 
| 9626 | 
            +
             | 
| 9627 | 
            +
            					while (node = walker[left ? 'prev' : 'next']()) {
         | 
| 9628 | 
            +
            						if (node.nodeName === "BR") {
         | 
| 9629 | 
            +
            							return true;
         | 
| 9630 | 
            +
            						}
         | 
| 9631 | 
            +
            					}
         | 
| 9632 | 
            +
            				};
         | 
| 9633 | 
            +
             | 
| 9480 9634 | 
             
            				// Walks the dom left/right to find a suitable text node to move the endpoint into
         | 
| 9481 9635 | 
             
            				// It will only walk within the current parent block or body and will stop if it hits a block or a BR/IMG
         | 
| 9482 9636 | 
             
            				function findTextNodeRelative(left, startNode) {
         | 
| @@ -9517,7 +9671,7 @@ window.tinymce.dom.Sizzle = Sizzle; | |
| 9517 9671 |  | 
| 9518 9672 | 
             
            				// If the container is a document move it to the body element
         | 
| 9519 9673 | 
             
            				if (container.nodeType === 9) {
         | 
| 9520 | 
            -
            					container =  | 
| 9674 | 
            +
            					container = dom.getRoot();
         | 
| 9521 9675 | 
             
            					offset = 0;
         | 
| 9522 9676 | 
             
            				}
         | 
| 9523 9677 |  | 
| @@ -9540,7 +9694,7 @@ window.tinymce.dom.Sizzle = Sizzle; | |
| 9540 9694 | 
             
            						offset = 0;
         | 
| 9541 9695 |  | 
| 9542 9696 | 
             
            						// Don't walk into elements that doesn't have any child nodes like a IMG
         | 
| 9543 | 
            -
            						if (container.hasChildNodes()) {
         | 
| 9697 | 
            +
            						if (container.hasChildNodes() && !/TABLE/.test(container.nodeName)) {
         | 
| 9544 9698 | 
             
            							// Walk the DOM to find a text node to place the caret at or a BR
         | 
| 9545 9699 | 
             
            							node = container;
         | 
| 9546 9700 | 
             
            							walker = new TreeWalker(container, body);
         | 
| @@ -9572,7 +9726,6 @@ window.tinymce.dom.Sizzle = Sizzle; | |
| 9572 9726 | 
             
            					}
         | 
| 9573 9727 | 
             
            				}
         | 
| 9574 9728 |  | 
| 9575 | 
            -
             | 
| 9576 9729 | 
             
            				// Lean the caret to the left if possible
         | 
| 9577 9730 | 
             
            				if (collapsed) {
         | 
| 9578 9731 | 
             
            					// So this: <b>x</b><i>|x</i>
         | 
| @@ -9586,8 +9739,11 @@ window.tinymce.dom.Sizzle = Sizzle; | |
| 9586 9739 | 
             
            					// So this: <i><b></b><i>|<br></i>
         | 
| 9587 9740 | 
             
            					// Becomes: <i><b>|</b><i><br></i>
         | 
| 9588 9741 | 
             
            					// Seems that only gecko has issues with this
         | 
| 9589 | 
            -
            					if (container.nodeType === 1 | 
| 9590 | 
            -
            						 | 
| 9742 | 
            +
            					if (container.nodeType === 1) {
         | 
| 9743 | 
            +
            						node = container.childNodes[offset];
         | 
| 9744 | 
            +
            						if(node && node.nodeName === 'BR' && !hasBrBeforeAfter(node) && !hasBrBeforeAfter(node, true)) {
         | 
| 9745 | 
            +
            							findTextNodeRelative(true, container.childNodes[offset]);
         | 
| 9746 | 
            +
            						}
         | 
| 9591 9747 | 
             
            					}
         | 
| 9592 9748 | 
             
            				}
         | 
| 9593 9749 |  | 
| @@ -9603,9 +9759,6 @@ window.tinymce.dom.Sizzle = Sizzle; | |
| 9603 9759 | 
             
            					rng['set' + (start ? 'Start' : 'End')](container, offset);
         | 
| 9604 9760 | 
             
            			};
         | 
| 9605 9761 |  | 
| 9606 | 
            -
            			// TODO:
         | 
| 9607 | 
            -
            			// Retain selection direction.
         | 
| 9608 | 
            -
             | 
| 9609 9762 | 
             
            			// Normalize only on non IE browsers for now
         | 
| 9610 9763 | 
             
            			if (tinymce.isIE)
         | 
| 9611 9764 | 
             
            				return;
         | 
| @@ -9627,7 +9780,7 @@ window.tinymce.dom.Sizzle = Sizzle; | |
| 9627 9780 | 
             
            				}
         | 
| 9628 9781 |  | 
| 9629 9782 | 
             
            				//console.log(self.dom.dumpRng(rng));
         | 
| 9630 | 
            -
            				self.setRng(rng);
         | 
| 9783 | 
            +
            				self.setRng(rng, self.isForward());
         | 
| 9631 9784 | 
             
            			}
         | 
| 9632 9785 | 
             
            		},
         | 
| 9633 9786 |  | 
| @@ -9771,13 +9924,13 @@ window.tinymce.dom.Sizzle = Sizzle; | |
| 9771 9924 | 
             
            			}
         | 
| 9772 9925 | 
             
            		});
         | 
| 9773 9926 |  | 
| 9774 | 
            -
            		// Remove internal classes mceItem<..>
         | 
| 9927 | 
            +
            		// Remove internal classes mceItem<..> or mceSelected
         | 
| 9775 9928 | 
             
            		htmlParser.addAttributeFilter('class', function(nodes, name) {
         | 
| 9776 9929 | 
             
            			var i = nodes.length, node, value;
         | 
| 9777 9930 |  | 
| 9778 9931 | 
             
            			while (i--) {
         | 
| 9779 9932 | 
             
            				node = nodes[i];
         | 
| 9780 | 
            -
            				value = node.attr('class').replace( | 
| 9933 | 
            +
            				value = node.attr('class').replace(/(?:^|\s)mce(Item\w+|Selected)(?!\S)/g, '');
         | 
| 9781 9934 | 
             
            				node.attr('class', value.length > 0 ? value : null);
         | 
| 9782 9935 | 
             
            			}
         | 
| 9783 9936 | 
             
            		});
         | 
| @@ -10851,8 +11004,8 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', { | |
| 10851 11004 | 
             
            		update : function() {
         | 
| 10852 11005 | 
             
            			var t = this, s = t.settings, tb = DOM.get('menu_' + t.id + '_tbl'), co = DOM.get('menu_' + t.id + '_co'), tw, th;
         | 
| 10853 11006 |  | 
| 10854 | 
            -
            			tw = s.max_width ? Math.min(tb. | 
| 10855 | 
            -
            			th = s.max_height ? Math.min(tb. | 
| 11007 | 
            +
            			tw = s.max_width ? Math.min(tb.offsetWidth, s.max_width) : tb.offsetWidth;
         | 
| 11008 | 
            +
            			th = s.max_height ? Math.min(tb.offsetHeight, s.max_height) : tb.offsetHeight;
         | 
| 10856 11009 |  | 
| 10857 11010 | 
             
            			if (!DOM.boxModel)
         | 
| 10858 11011 | 
             
            				t.element.setStyles({width : tw + 2, height : th + 2});
         | 
| @@ -11397,7 +11550,7 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', { | |
| 11397 11550 | 
             
            			m = t.settings.control_manager.createDropMenu(t.id + '_menu', {
         | 
| 11398 11551 | 
             
            				menu_line : 1,
         | 
| 11399 11552 | 
             
            				'class' : t.classPrefix + 'Menu mceNoIcons',
         | 
| 11400 | 
            -
            				max_width :  | 
| 11553 | 
            +
            				max_width : 250,
         | 
| 11401 11554 | 
             
            				max_height : 150
         | 
| 11402 11555 | 
             
            			});
         | 
| 11403 11556 |  | 
| @@ -13515,7 +13668,7 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { | |
| 13515 13668 | 
             
            		},
         | 
| 13516 13669 |  | 
| 13517 13670 | 
             
            		hide : function() {
         | 
| 13518 | 
            -
            			var self = this, doc =  | 
| 13671 | 
            +
            			var self = this, doc = self.getDoc();
         | 
| 13519 13672 |  | 
| 13520 13673 | 
             
            			// Fixed bug where IE has a blinking cursor left from the editor
         | 
| 13521 13674 | 
             
            			if (isIE && doc)
         | 
| @@ -14642,9 +14795,7 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { | |
| 14642 14795 | 
             
            			// Override justify commands
         | 
| 14643 14796 | 
             
            			'JustifyLeft,JustifyCenter,JustifyRight,JustifyFull' : function(command) {
         | 
| 14644 14797 | 
             
            				var name = 'align' + command.substring(7);
         | 
| 14645 | 
            -
            				 | 
| 14646 | 
            -
            				// and right align buttons can be active. This could occur when selected nodes have align right and the parent has align left.
         | 
| 14647 | 
            -
            				var nodes = selection.isCollapsed() ? [selection.getNode()] : selection.getSelectedBlocks();
         | 
| 14798 | 
            +
            				var nodes = selection.isCollapsed() ? [dom.getParent(selection.getNode(), dom.isBlock)] : selection.getSelectedBlocks();
         | 
| 14648 14799 | 
             
            				var matches = tinymce.map(nodes, function(node) {
         | 
| 14649 14800 | 
             
            					return !!formatter.matchNode(node, name);
         | 
| 14650 14801 | 
             
            				});
         | 
| @@ -14926,7 +15077,7 @@ tinymce.ForceBlocks = function(editor) { | |
| 14926 15077 | 
             
            	var settings = editor.settings, dom = editor.dom, selection = editor.selection, blockElements = editor.schema.getBlockElements();
         | 
| 14927 15078 |  | 
| 14928 15079 | 
             
            	function addRootBlocks() {
         | 
| 14929 | 
            -
            		var node = selection.getStart(), rootNode = editor.getBody(), rng, startContainer, startOffset, endContainer, endOffset, rootBlockNode, tempNode, offset = -0xFFFFFF;
         | 
| 15080 | 
            +
            		var node = selection.getStart(), rootNode = editor.getBody(), rng, startContainer, startOffset, endContainer, endOffset, rootBlockNode, tempNode, offset = -0xFFFFFF, wrapped;
         | 
| 14930 15081 |  | 
| 14931 15082 | 
             
            		if (!node || node.nodeType !== 1 || !settings.forced_root_block)
         | 
| 14932 15083 | 
             
            			return;
         | 
| @@ -14972,6 +15123,7 @@ tinymce.ForceBlocks = function(editor) { | |
| 14972 15123 | 
             
            				if (!rootBlockNode) {
         | 
| 14973 15124 | 
             
            					rootBlockNode = dom.create(settings.forced_root_block);
         | 
| 14974 15125 | 
             
            					node.parentNode.insertBefore(rootBlockNode, node);
         | 
| 15126 | 
            +
            					wrapped = true;
         | 
| 14975 15127 | 
             
            				}
         | 
| 14976 15128 |  | 
| 14977 15129 | 
             
            				tempNode = node;
         | 
| @@ -15003,13 +15155,16 @@ tinymce.ForceBlocks = function(editor) { | |
| 15003 15155 | 
             
            			}
         | 
| 15004 15156 | 
             
            		}
         | 
| 15005 15157 |  | 
| 15006 | 
            -
            		 | 
| 15158 | 
            +
            		// Only trigger nodeChange when we wrapped nodes to prevent a forever loop
         | 
| 15159 | 
            +
            		if (wrapped) {
         | 
| 15160 | 
            +
            			editor.nodeChanged();
         | 
| 15161 | 
            +
            		}
         | 
| 15007 15162 | 
             
            	};
         | 
| 15008 15163 |  | 
| 15009 15164 | 
             
            	// Force root blocks
         | 
| 15010 15165 | 
             
            	if (settings.forced_root_block) {
         | 
| 15011 15166 | 
             
            		editor.onKeyUp.add(addRootBlocks);
         | 
| 15012 | 
            -
            		editor. | 
| 15167 | 
            +
            		editor.onNodeChange.add(addRootBlocks);
         | 
| 15013 15168 | 
             
            	}
         | 
| 15014 15169 | 
             
            };
         | 
| 15015 15170 |  | 
| @@ -15105,6 +15260,8 @@ tinymce.ForceBlocks = function(editor) { | |
| 15105 15260 | 
             
            			if (v = ed.getParam('skin_variant'))
         | 
| 15106 15261 | 
             
            				s['class'] += ' ' + ed.getParam('skin') + 'Skin' + v.substring(0, 1).toUpperCase() + v.substring(1);
         | 
| 15107 15262 |  | 
| 15263 | 
            +
            			s['class'] += ed.settings.directionality == "rtl" ? ' mceRtl' : '';
         | 
| 15264 | 
            +
             | 
| 15108 15265 | 
             
            			id = t.prefix + id;
         | 
| 15109 15266 | 
             
            			cls = cc || t._cls.dropmenu || tinymce.ui.DropMenu;
         | 
| 15110 15267 | 
             
            			c = t.controls[id] = new cls(id, s);
         | 
| @@ -16218,9 +16375,8 @@ tinymce.ForceBlocks = function(editor) { | |
| 16218 16375 | 
             
            					if (startContainer != endContainer) {
         | 
| 16219 16376 | 
             
            						// WebKit will render the table incorrectly if we wrap a TD in a SPAN so lets see if the can use the first child instead
         | 
| 16220 16377 | 
             
            						// This will happen if you tripple click a table cell and use remove formatting
         | 
| 16221 | 
            -
            						 | 
| 16222 | 
            -
             | 
| 16223 | 
            -
            							startContainer = node;
         | 
| 16378 | 
            +
            						if (/^(TR|TD)$/.test(startContainer.nodeName) && startContainer.firstChild) {
         | 
| 16379 | 
            +
            							startContainer = (startContainer.nodeName == "TD" ? startContainer.firstChild : startContainer.firstChild.firstChild) || startContainer;
         | 
| 16224 16380 | 
             
            						}
         | 
| 16225 16381 |  | 
| 16226 16382 | 
             
            						// Wrap start/end nodes in span element since these might be cloned/moved
         | 
| @@ -17381,6 +17537,15 @@ tinymce.ForceBlocks = function(editor) { | |
| 17381 17537 | 
             
            					}
         | 
| 17382 17538 | 
             
            				});
         | 
| 17383 17539 |  | 
| 17540 | 
            +
            				// Remove bogus state if they got filled by contents using editor.selection.setContent
         | 
| 17541 | 
            +
            				selection.onSetContent.add(function() {
         | 
| 17542 | 
            +
            					dom.getParent(selection.getStart(), function(node) {
         | 
| 17543 | 
            +
            						if (node.id !== caretContainerId && dom.getAttrib(node, 'data-mce-bogus') && !dom.isEmpty(node)) {
         | 
| 17544 | 
            +
            							dom.setAttrib(node, 'data-mce-bogus', null);
         | 
| 17545 | 
            +
            						}
         | 
| 17546 | 
            +
            					});
         | 
| 17547 | 
            +
            				});
         | 
| 17548 | 
            +
             | 
| 17384 17549 | 
             
            				self._hasCaretEvents = true;
         | 
| 17385 17550 | 
             
            			}
         | 
| 17386 17551 |  |