summaryrefslogtreecommitdiff
path: root/program/js/tiny_mce/tiny_mce_src.js
diff options
context:
space:
mode:
Diffstat (limited to 'program/js/tiny_mce/tiny_mce_src.js')
-rw-r--r--program/js/tiny_mce/tiny_mce_src.js532
1 files changed, 400 insertions, 132 deletions
diff --git a/program/js/tiny_mce/tiny_mce_src.js b/program/js/tiny_mce/tiny_mce_src.js
index e38fb7efb..86b162b75 100644
--- a/program/js/tiny_mce/tiny_mce_src.js
+++ b/program/js/tiny_mce/tiny_mce_src.js
@@ -6,18 +6,20 @@
var tinymce = {
majorVersion : '3',
- minorVersion : '5.6',
+ minorVersion : '5.10',
- releaseDate : '2012-07-26',
+ releaseDate : '2013-10-24',
_init : function() {
var t = this, d = document, na = navigator, ua = na.userAgent, i, nl, n, base, p, v;
+ t.isIE11 = ua.indexOf('Trident/') != -1 && (ua.indexOf('rv:') != -1 || na.appName.indexOf('Netscape') != -1);
+
t.isOpera = win.opera && opera.buildNumber;
t.isWebKit = /WebKit/.test(ua);
- t.isIE = !t.isWebKit && !t.isOpera && (/MSIE/gi).test(ua) && (/Explorer/gi).test(na.appName);
+ t.isIE = !t.isWebKit && !t.isOpera && (/MSIE/gi).test(ua) && (/Explorer/gi).test(na.appName) || t.isIE11;
t.isIE6 = t.isIE && /MSIE [56]/.test(ua);
@@ -27,7 +29,7 @@
t.isIE9 = t.isIE && /MSIE [9]/.test(ua);
- t.isGecko = !t.isWebKit && /Gecko/.test(ua);
+ t.isGecko = !t.isWebKit && !t.isIE11 && /Gecko/.test(ua);
t.isMac = ua.indexOf('Mac') != -1;
@@ -107,12 +109,16 @@
if (!t)
return o !== undef;
- if (t == 'array' && (o.hasOwnProperty && o instanceof Array))
+ if (t == 'array' && tinymce.isArray(o))
return true;
return typeof(o) == t;
},
+ isArray: Array.isArray || function(obj) {
+ return Object.prototype.toString.call(obj) === "[object Array]";
+ },
+
makeMap : function(items, delim, map) {
var i;
@@ -921,7 +927,7 @@ tinymce.create('tinymce.util.Dispatcher', {
}
if (t == 'object') {
- if (o.hasOwnProperty && o instanceof Array) {
+ if (o.hasOwnProperty && Object.prototype.toString.call(o) === '[object Array]') {
for (i=0, v = '['; i<o.length; i++)
v += (i > 0 ? ',' : '') + serialize(o[i], quote);
@@ -1093,7 +1099,8 @@ tinymce.create('static tinymce.util.XHR', {
})(tinymce);
tinymce.util.Quirks = function(editor) {
- var VK = tinymce.VK, BACKSPACE = VK.BACKSPACE, DELETE = VK.DELETE, dom = editor.dom, selection = editor.selection, settings = editor.settings;
+ var VK = tinymce.VK, BACKSPACE = VK.BACKSPACE, DELETE = VK.DELETE, dom = editor.dom, selection = editor.selection,
+ settings = editor.settings, parser = editor.parser, serializer = editor.serializer, each = tinymce.each;
function setEditorCommandState(cmd, state) {
try {
@@ -1109,56 +1116,81 @@ tinymce.util.Quirks = function(editor) {
return documentMode ? documentMode : 6;
};
+ function isDefaultPrevented(e) {
+ return e.isDefaultPrevented();
+ };
+
function cleanupStylesWhenDeleting() {
function removeMergedFormatSpans(isDelete) {
- var rng, blockElm, node, clonedSpan;
+ var rng, blockElm, wrapperElm, bookmark, container, offset, elm;
+
+ function isAtStartOrEndOfElm() {
+ if (container.nodeType == 3) {
+ if (isDelete && offset == container.length) {
+ return true;
+ }
+
+ if (!isDelete && offset === 0) {
+ return true;
+ }
+ }
+ }
rng = selection.getRng();
+ var tmpRng = [rng.startContainer, rng.startOffset, rng.endContainer, rng.endOffset];
+
+ if (!rng.collapsed) {
+ isDelete = true;
+ }
- // Find root block
- blockElm = dom.getParent(rng.startContainer, dom.isBlock);
+ container = rng[(isDelete ? 'start' : 'end') + 'Container'];
+ offset = rng[(isDelete ? 'start' : 'end') + 'Offset'];
- // On delete clone the root span of the next block element
- if (isDelete)
- blockElm = dom.getNext(blockElm, dom.isBlock);
+ if (container.nodeType == 3) {
+ blockElm = dom.getParent(rng.startContainer, dom.isBlock);
- // Locate root span element and clone it since it would otherwise get merged by the "apple-style-span" on delete/backspace
- if (blockElm) {
- node = blockElm.firstChild;
+ // On delete clone the root span of the next block element
+ if (isDelete) {
+ blockElm = dom.getNext(blockElm, dom.isBlock);
+ }
- // Ignore empty text nodes
- while (node && node.nodeType == 3 && node.nodeValue.length === 0)
- node = node.nextSibling;
+ if (blockElm && (isAtStartOrEndOfElm() || !rng.collapsed)) {
+ // Wrap children of block in a EM and let WebKit stick is
+ // runtime styles junk into that EM
+ wrapperElm = dom.create('em', {'id': '__mceDel'});
+
+ each(tinymce.grep(blockElm.childNodes), function(node) {
+ wrapperElm.appendChild(node);
+ });
- if (node && node.nodeName === 'SPAN') {
- clonedSpan = node.cloneNode(false);
+ blockElm.appendChild(wrapperElm);
}
}
// Do the backspace/delete action
+ rng = dom.createRng();
+ rng.setStart(tmpRng[0], tmpRng[1]);
+ rng.setEnd(tmpRng[2], tmpRng[3]);
+ selection.setRng(rng);
editor.getDoc().execCommand(isDelete ? 'ForwardDelete' : 'Delete', false, null);
- // Find all odd apple-style-spans
- blockElm = dom.getParent(rng.startContainer, dom.isBlock);
- tinymce.each(dom.select('span.Apple-style-span,font.Apple-style-span', blockElm), function(span) {
- var bm = selection.getBookmark();
+ // Remove temp wrapper element
+ if (wrapperElm) {
+ bookmark = selection.getBookmark();
- if (clonedSpan) {
- dom.replace(clonedSpan.cloneNode(false), span, true);
- } else {
- dom.remove(span, true);
+ while (elm = dom.get('__mceDel')) {
+ dom.remove(elm, true);
}
- // Restore the selection
- selection.moveToBookmark(bm);
- });
- };
+ selection.moveToBookmark(bookmark);
+ }
+ }
editor.onKeyDown.add(function(editor, e) {
var isDelete;
isDelete = e.keyCode == DELETE;
- if (!e.isDefaultPrevented() && (isDelete || e.keyCode == BACKSPACE) && !VK.modifierPressed(e)) {
+ if (!isDefaultPrevented(e) && (isDelete || e.keyCode == BACKSPACE) && !VK.modifierPressed(e)) {
e.preventDefault();
removeMergedFormatSpans(isDelete);
}
@@ -1189,7 +1221,7 @@ tinymce.util.Quirks = function(editor) {
var keyCode = e.keyCode, isCollapsed;
// Empty the editor if it's needed for example backspace at <p><b>|</b></p>
- if (!e.isDefaultPrevented() && (keyCode == DELETE || keyCode == BACKSPACE)) {
+ if (!isDefaultPrevented(e) && (keyCode == DELETE || keyCode == BACKSPACE)) {
isCollapsed = editor.selection.isCollapsed();
// Selection is collapsed but the editor isn't empty
@@ -1217,7 +1249,7 @@ tinymce.util.Quirks = function(editor) {
function selectAll() {
editor.onKeyDown.add(function(editor, e) {
- if (e.keyCode == 65 && VK.metaKeyPressed(e)) {
+ if (!isDefaultPrevented(e) && e.keyCode == 65 && VK.metaKeyPressed(e)) {
e.preventDefault();
editor.execCommand('SelectAll');
}
@@ -1243,7 +1275,7 @@ tinymce.util.Quirks = function(editor) {
function removeHrOnBackspace() {
editor.onKeyDown.add(function(editor, e) {
- if (!e.isDefaultPrevented() && e.keyCode === BACKSPACE) {
+ if (!isDefaultPrevented(e) && e.keyCode === BACKSPACE) {
if (selection.isCollapsed() && selection.getRng(true).startOffset === 0) {
var node = selection.getNode();
var previousSibling = node.previousSibling;
@@ -1262,7 +1294,7 @@ tinymce.util.Quirks = function(editor) {
// wouldn't get proper focus if the user clicked on the HTML element
if (!Range.prototype.getClientRects) { // Detect getClientRects got introduced in FF 4
editor.onMouseDown.add(function(editor, e) {
- if (e.target.nodeName === "HTML") {
+ if (!isDefaultPrevented(e) && e.target.nodeName === "HTML") {
var body = editor.getBody();
// Blur the body it's focused but not correctly focused
@@ -1306,7 +1338,7 @@ tinymce.util.Quirks = function(editor) {
if (target !== editor.getBody()) {
dom.setAttrib(target, "style", null);
- tinymce.each(template, function(attr) {
+ each(template, function(attr) {
target.setAttributeNode(attr.cloneNode(true));
});
}
@@ -1325,7 +1357,7 @@ tinymce.util.Quirks = function(editor) {
editor.onKeyPress.add(function(editor, e) {
var applyAttributes;
- if ((e.keyCode == 8 || e.keyCode == 46) && isSelectionAcrossElements()) {
+ if (!isDefaultPrevented(e) && (e.keyCode == 8 || e.keyCode == 46) && isSelectionAcrossElements()) {
applyAttributes = getAttributeApplyFunction();
editor.getDoc().execCommand('delete', false, null);
applyAttributes();
@@ -1337,7 +1369,7 @@ tinymce.util.Quirks = function(editor) {
dom.bind(editor.getDoc(), 'cut', function(e) {
var applyAttributes;
- if (isSelectionAcrossElements()) {
+ if (!isDefaultPrevented(e) && isSelectionAcrossElements()) {
applyAttributes = getAttributeApplyFunction();
editor.onKeyUp.addToTop(blockEvent);
@@ -1376,7 +1408,7 @@ tinymce.util.Quirks = function(editor) {
function disableBackspaceIntoATable() {
editor.onKeyDown.add(function(editor, e) {
- if (!e.isDefaultPrevented() && e.keyCode === BACKSPACE) {
+ if (!isDefaultPrevented(e) && e.keyCode === BACKSPACE) {
if (selection.isCollapsed() && selection.getRng(true).startOffset === 0) {
var previousSibling = selection.getNode().previousSibling;
if (previousSibling && previousSibling.nodeName && previousSibling.nodeName.toLowerCase() === "table") {
@@ -1400,7 +1432,7 @@ tinymce.util.Quirks = function(editor) {
dom.addClass(editor.getBody(), 'mceHideBrInPre');
// Adds a \n before all BR elements in PRE to get them visual
- editor.parser.addNodeFilter('pre', function(nodes, name) {
+ parser.addNodeFilter('pre', function(nodes, name) {
var i = nodes.length, brNodes, j, brElm, sibling;
while (i--) {
@@ -1421,7 +1453,7 @@ tinymce.util.Quirks = function(editor) {
});
// Removes any \n before BR elements in PRE since other browsers and in contentEditable=false mode they will be visible
- editor.serializer.addNodeFilter('pre', function(nodes, name) {
+ serializer.addNodeFilter('pre', function(nodes, name) {
var i = nodes.length, brNodes, j, brElm, sibling;
while (i--) {
@@ -1464,7 +1496,7 @@ tinymce.util.Quirks = function(editor) {
var isDelete, rng, container, offset, brElm, sibling, collapsed;
isDelete = e.keyCode == DELETE;
- if (!e.isDefaultPrevented() && (isDelete || e.keyCode == BACKSPACE) && !VK.modifierPressed(e)) {
+ if (!isDefaultPrevented(e) && (isDelete || e.keyCode == BACKSPACE) && !VK.modifierPressed(e)) {
rng = selection.getRng();
container = rng.startContainer;
offset = rng.startOffset;
@@ -1473,6 +1505,12 @@ tinymce.util.Quirks = function(editor) {
// Override delete if the start container is a text node and is at the beginning of text or
// just before/after the last character to be deleted in collapsed mode
if (container.nodeType == 3 && container.nodeValue.length > 0 && ((offset === 0 && !collapsed) || (collapsed && offset === (isDelete ? 0 : 1)))) {
+ // Edge case when deleting <p><b><img> |x</b></p>
+ sibling = container.previousSibling;
+ if (sibling && sibling.nodeName == "IMG") {
+ return;
+ }
+
nonEmptyElements = editor.schema.getNonEmptyElements();
// Prevent default logic since it's broken
@@ -1504,7 +1542,7 @@ tinymce.util.Quirks = function(editor) {
editor.onKeyDown.add(function(editor, e) {
var rng, container, offset, root, parent;
- if (e.isDefaultPrevented() || e.keyCode != VK.BACKSPACE) {
+ if (isDefaultPrevented(e) || e.keyCode != VK.BACKSPACE) {
return;
}
@@ -1528,10 +1566,10 @@ tinymce.util.Quirks = function(editor) {
editor.formatter.toggle('blockquote', null, parent);
// Move the caret to the beginning of container
+ rng = dom.createRng();
rng.setStart(container, 0);
rng.setEnd(container, 0);
selection.setRng(rng);
- selection.collapse(false);
}
});
};
@@ -1556,7 +1594,7 @@ tinymce.util.Quirks = function(editor) {
function addBrAfterLastLinks() {
function fixLinks(editor, o) {
- tinymce.each(dom.select('a'), function(node) {
+ each(dom.select('a'), function(node) {
var parentNode = node.parentNode, root = dom.getRoot();
if (parentNode.lastChild === node) {
@@ -1606,7 +1644,7 @@ tinymce.util.Quirks = function(editor) {
editor.onKeyDown.add(function(editor, e) {
var rng;
- if (!e.isDefaultPrevented() && e.keyCode == BACKSPACE) {
+ if (!isDefaultPrevented(e) && e.keyCode == BACKSPACE) {
rng = editor.getDoc().selection.createRange();
if (rng && rng.item) {
e.preventDefault();
@@ -1624,7 +1662,7 @@ tinymce.util.Quirks = function(editor) {
// IE10+
if (getDocumentMode() >= 10) {
emptyBlocksCSS = '';
- tinymce.each('p div h1 h2 h3 h4 h5 h6'.split(' '), function(name, i) {
+ each('p div h1 h2 h3 h4 h5 h6'.split(' '), function(name, i) {
emptyBlocksCSS += (i > 0 ? ',' : '') + name + ':empty';
});
@@ -1741,7 +1779,7 @@ tinymce.util.Quirks = function(editor) {
width = height = 0;
}
- tinymce.each(resizeHandles, function(handle, name) {
+ each(resizeHandles, function(handle, name) {
var handleElm;
// Get existing or render resize handle
@@ -1838,7 +1876,7 @@ tinymce.util.Quirks = function(editor) {
var controlElm = dom.getParent(selection.getNode(), 'table,img');
// Remove data-mce-selected from all elements since they might have been copied using Ctrl+c/v
- tinymce.each(dom.select('img[data-mce-selected]'), function(img) {
+ each(dom.select('img[data-mce-selected]'), function(img) {
img.removeAttribute('data-mce-selected');
});
@@ -1865,6 +1903,57 @@ tinymce.util.Quirks = function(editor) {
});
}
+ function keepNoScriptContents() {
+ if (getDocumentMode() < 9) {
+ parser.addNodeFilter('noscript', function(nodes) {
+ var i = nodes.length, node, textNode;
+
+ while (i--) {
+ node = nodes[i];
+ textNode = node.firstChild;
+
+ if (textNode) {
+ node.attr('data-mce-innertext', textNode.value);
+ }
+ }
+ });
+
+ serializer.addNodeFilter('noscript', function(nodes) {
+ var i = nodes.length, node, textNode, value;
+
+ while (i--) {
+ node = nodes[i];
+ textNode = nodes[i].firstChild;
+
+ if (textNode) {
+ textNode.value = tinymce.html.Entities.decode(textNode.value);
+ } else {
+ // Old IE can't retain noscript value so an attribute is used to store it
+ value = node.attributes.map['data-mce-innertext'];
+ if (value) {
+ node.attr('data-mce-innertext', null);
+ textNode = new tinymce.html.Node('#text', 3);
+ textNode.value = value;
+ textNode.raw = true;
+ node.append(textNode);
+ }
+ }
+ }
+ });
+ }
+ }
+
+ function bodyHeight() {
+ editor.contentStyles.push('body {min-height: 100px}');
+ editor.onClick.add(function(ed, e) {
+ if (e.target.nodeName == 'HTML') {
+ editor.execCommand('SelectAll');
+ editor.selection.collapse(true);
+ editor.nodeChanged();
+ }
+ });
+ }
+
// All browsers
disableBackspaceIntoATable();
removeBlockQuoteOnBackSpace();
@@ -1888,17 +1977,23 @@ tinymce.util.Quirks = function(editor) {
}
// IE
- if (tinymce.isIE) {
+ if (tinymce.isIE && !tinymce.isIE11) {
removeHrOnBackspace();
ensureBodyHasRoleApplication();
addNewLinesBeforeBrInPre();
removePreSerializedStylesWhenSelectingControls();
deleteControlItemOnBackSpace();
renderEmptyBlocksFix();
+ keepNoScriptContents();
+ }
+
+ // IE 11+
+ if (tinymce.isIE11) {
+ bodyHeight();
}
// Gecko
- if (tinymce.isGecko) {
+ if (tinymce.isGecko && !tinymce.isIE11) {
removeHrOnBackspace();
focusBody();
removeStylesWhenDeletingAccrossBlockElements();
@@ -2135,6 +2230,12 @@ tinymce.html.Styles = function(settings, schema) {
function compress(prefix, suffix) {
var top, right, bottom, left;
+ // IE 11 will produce a border-image: none when getting the style attribute from <p style="border: 1px solid red"></p>
+ // So lets asume it shouldn't be there
+ if (styles['border-image'] === 'none') {
+ delete styles['border-image'];
+ }
+
// Get values and check it it needs compressing
top = styles[prefix + '-top' + suffix];
if (!top)
@@ -2449,7 +2550,7 @@ tinymce.html.Styles = function(settings, schema) {
'form[A|accept-charset|action|autocomplete|enctype|method|name|novalidate|target][C]' +
'fieldset[A|disabled|form|name][C|legend]' +
'label[A|form|for][B]' +
- 'input[A|type|accept|alt|autocomplete|checked|disabled|form|formaction|formenctype|formmethod|formnovalidate|formtarget|height|list|max|maxlength|min|' +
+ 'input[A|type|accept|alt|autocomplete|autofocus|checked|disabled|form|formaction|formenctype|formmethod|formnovalidate|formtarget|height|list|max|maxlength|min|' +
'multiple|pattern|placeholder|readonly|required|size|src|step|width|files|value|name][]' +
'button[A|autofocus|disabled|form|formaction|formenctype|formmethod|formnovalidate|formtarget|name|value|type][B]' +
'select[A|autofocus|disabled|form|multiple|name|size][option|optgroup]' +
@@ -2653,14 +2754,15 @@ tinymce.html.Styles = function(settings, schema) {
}
// Setup map objects
- whiteSpaceElementsMap = createLookupTable('whitespace_elements', 'pre script style textarea');
+ whiteSpaceElementsMap = createLookupTable('whitespace_elements', 'pre script noscript style textarea');
selfClosingElementsMap = createLookupTable('self_closing_elements', 'colgroup dd dt li option p td tfoot th thead tr');
shortEndedElementsMap = createLookupTable('short_ended_elements', 'area base basefont br col frame hr img input isindex link meta param embed source wbr');
boolAttrMap = createLookupTable('boolean_attributes', 'checked compact declare defer disabled ismap multiple nohref noresize noshade nowrap readonly selected autoplay loop controls');
- nonEmptyElementsMap = createLookupTable('non_empty_elements', 'td th iframe video audio object', shortEndedElementsMap);
- blockElementsMap = createLookupTable('block_elements', 'h1 h2 h3 h4 h5 h6 hr p div address pre form table tbody thead tfoot ' +
- 'th tr td li ol ul caption blockquote center dl dt dd dir fieldset ' +
- 'noscript menu isindex samp header footer article section hgroup aside nav figure option datalist select optgroup');
+ nonEmptyElementsMap = createLookupTable('non_empty_elements', 'td th iframe video audio object script', shortEndedElementsMap);
+ textBlockElementsMap = createLookupTable('text_block_elements', 'h1 h2 h3 h4 h5 h6 p div address pre form ' +
+ 'blockquote center dir fieldset header footer article section hgroup aside nav figure');
+ blockElementsMap = createLookupTable('block_elements', 'hr table tbody thead tfoot ' +
+ 'th tr td li ol ul caption dl dt dd noscript menu isindex samp option datalist select optgroup', textBlockElementsMap);
// Converts a wildcard expression string to a regexp for example *a will become /.*a/.
function patternToRegExp(str) {
@@ -2834,8 +2936,15 @@ tinymce.html.Styles = function(settings, schema) {
customElementsMap[name] = cloneName;
// If it's not marked as inline then add it to valid block elements
- if (!inline)
+ if (!inline) {
+ blockElementsMap[name.toUpperCase()] = {};
blockElementsMap[name] = {};
+ }
+
+ // Add elements clone if needed
+ if (!elements[name]) {
+ elements[name] = elements[cloneName];
+ }
// Add custom elements at span/div positions
each(children, function(element, child) {
@@ -2960,6 +3069,10 @@ tinymce.html.Styles = function(settings, schema) {
return blockElementsMap;
};
+ self.getTextBlockElements = function() {
+ return textBlockElementsMap;
+ };
+
self.getShortEndedElements = function() {
return shortEndedElementsMap;
};
@@ -3025,6 +3138,8 @@ tinymce.html.Styles = function(settings, schema) {
self.addCustomElements = addCustomElements;
self.addValidChildren = addValidChildren;
+
+ self.elements = elements;
};
})(tinymce);
@@ -3123,10 +3238,10 @@ tinymce.html.Styles = function(settings, schema) {
'(?:!DOCTYPE([\\w\\W]*?)>)|' + // DOCTYPE
'(?:\\?([^\\s\\/<>]+) ?([\\w\\W]*?)[?/]>)|' + // PI
'(?:\\/([^>]+)>)|' + // End element
- '(?:([A-Za-z0-9\\-\\:]+)((?:\\s+[^"\'>]+(?:(?:"[^"]*")|(?:\'[^\']*\')|[^>]*))*|\\/|\\s+)>)' + // Start element
+ '(?:([A-Za-z0-9\\-\\:\\.]+)((?:\\s+[^"\'>]+(?:(?:"[^"]*")|(?:\'[^\']*\')|[^>]*))*|\\/|\\s+)>)' + // Start element
')', 'g');
- attrRegExp = /([\w:\-]+)(?:\s*=\s*(?:(?:\"((?:\\.|[^\"])*)\")|(?:\'((?:\\.|[^\'])*)\')|([^>\s]+)))?/g;
+ attrRegExp = /([\w:\-]+)(?:\s*=\s*(?:(?:\"((?:[^\"])*)\")|(?:\'((?:[^\'])*)\')|([^>\s]+)))?/g;
specialElements = {
'script' : /<\/script[^>]*>/gi,
'style' : /<\/style[^>]*>/gi,
@@ -3609,7 +3724,7 @@ tinymce.html.Styles = function(settings, schema) {
i = node.attributes.length;
while (i--) {
name = node.attributes[i].name;
- if (name === "name" || name.indexOf('data-') === 0)
+ if (name === "name" || name.indexOf('data-mce-') === 0)
return false;
}
}
@@ -3665,17 +3780,40 @@ tinymce.html.Styles = function(settings, schema) {
function fixInvalidChildren(nodes) {
var ni, node, parent, parents, newParent, currentNode, tempNode, childNode, i,
- childClone, nonEmptyElements, nonSplitableElements, sibling, nextNode;
+ childClone, nonEmptyElements, nonSplitableElements, textBlockElements, sibling, nextNode;
nonSplitableElements = tinymce.makeMap('tr,td,th,tbody,thead,tfoot,table');
nonEmptyElements = schema.getNonEmptyElements();
+ textBlockElements = schema.getTextBlockElements();
for (ni = 0; ni < nodes.length; ni++) {
node = nodes[ni];
- // Already removed
- if (!node.parent)
+ // Already removed or fixed
+ if (!node.parent || node.fixed)
+ continue;
+
+ // If the invalid element is a text block and the text block is within a parent LI element
+ // Then unwrap the first text block and convert other sibling text blocks to LI elements similar to Word/Open Office
+ if (textBlockElements[node.name] && node.parent.name == 'li') {
+ // Move sibling text blocks after LI element
+ sibling = node.next;
+ while (sibling) {
+ if (textBlockElements[sibling.name]) {
+ sibling.name = 'li';
+ sibling.fixed = true;
+ node.parent.insert(sibling, node.parent);
+ } else {
+ break;
+ }
+
+ sibling = sibling.next;
+ }
+
+ // Unwrap current text block
+ node.unwrap(node);
continue;
+ }
// Get list of all parent nodes until we find a valid parent to stick the child into
parents = [node];
@@ -4054,7 +4192,8 @@ tinymce.html.Styles = function(settings, schema) {
}
// Trim start white space
- textNode = node.prev;
+ // Removed due to: #5424
+ /*textNode = node.prev;
if (textNode && textNode.type === 3) {
text = textNode.value.replace(startWhiteSpaceRegExp, '');
@@ -4062,7 +4201,7 @@ tinymce.html.Styles = function(settings, schema) {
textNode.value = text;
else
textNode.remove();
- }
+ }*/
}
// Check if we exited a whitespace preserved element
@@ -4572,6 +4711,12 @@ tinymce.dom = {};
}
}
+ // Page already loaded then fire it directly
+ if (doc.readyState == "complete") {
+ readyHandler();
+ return;
+ }
+
// Use W3C method
if (w3cEventModel) {
addEvent(win, 'DOMContentLoaded', readyHandler);
@@ -5115,6 +5260,11 @@ tinymce.dom.TreeWalker = function(start_node, root_node) {
blockElementsMap = s.schema ? s.schema.getBlockElements() : {};
t.isBlock = function(node) {
+ // Fix for #5446
+ if (!node) {
+ return false;
+ }
+
// This function is called in module pattern style since it might be executed with the wrong this scope
var type = node.nodeType;
@@ -5129,7 +5279,7 @@ tinymce.dom.TreeWalker = function(start_node, root_node) {
fixDoc: function(doc) {
var settings = this.settings, name;
- if (isIE && settings.schema) {
+ if (isIE && !tinymce.isIE11 && settings.schema) {
// Add missing HTML 4/5 elements to IE
('abbr article aside audio canvas ' +
'details figcaption figure footer ' +
@@ -5150,7 +5300,7 @@ tinymce.dom.TreeWalker = function(start_node, root_node) {
var self = this, clone, doc;
// TODO: Add feature detection here in the future
- if (!isIE || node.nodeType !== 1 || deep) {
+ if (!isIE || tinymce.isIE11 || node.nodeType !== 1 || deep) {
return node.cloneNode(deep);
}
@@ -5423,7 +5573,7 @@ tinymce.dom.TreeWalker = function(start_node, root_node) {
switch (na) {
case 'opacity':
// IE specific opacity
- if (isIE) {
+ if (isIE && ! tinymce.isIE11) {
s.filter = v === '' ? '' : "alpha(opacity=" + (v * 100) + ")";
if (!n.currentStyle || !n.currentStyle.hasLayout)
@@ -5435,7 +5585,7 @@ tinymce.dom.TreeWalker = function(start_node, root_node) {
break;
case 'float':
- isIE ? s.styleFloat = v : s.cssFloat = v;
+ (isIE && ! tinymce.isIE11) ? s.styleFloat = v : s.cssFloat = v;
break;
default:
@@ -5801,7 +5951,7 @@ tinymce.dom.TreeWalker = function(start_node, root_node) {
// IE 8 has a bug where dynamically loading stylesheets would produce a 1 item remaining bug
// This fix seems to resolve that issue by realcing the document ones a stylesheet finishes loading
// It's ugly but it seems to work fine.
- if (isIE && d.documentMode && d.recalc) {
+ if (isIE && !tinymce.isIE11 && d.documentMode && d.recalc) {
link.onload = function() {
if (d.recalc)
d.recalc();
@@ -6120,7 +6270,12 @@ tinymce.dom.TreeWalker = function(start_node, root_node) {
// Import
case 3:
- addClasses(r.styleSheet);
+ try {
+ addClasses(r.styleSheet);
+ } catch (ex) {
+ // Ignore
+ }
+
break;
}
});
@@ -9222,7 +9377,7 @@ window.tinymce.dom.Sizzle = Sizzle;
if (!t.win.getSelection)
t.tridentSel = new tinymce.dom.TridentSelection(t);
- if (tinymce.isIE && dom.boxModel)
+ if (tinymce.isIE && ! tinymce.isIE11 && dom.boxModel)
this._fixIESelection();
// Prevent leaks
@@ -9514,8 +9669,20 @@ window.tinymce.dom.Sizzle = Sizzle;
}
// Handle simple range
- if (type)
- return {rng : t.getRng()};
+ if (type) {
+ rng = t.getRng();
+
+ if (rng.setStart) {
+ rng = {
+ startContainer: rng.startContainer,
+ startOffset: rng.startOffset,
+ endContainer: rng.endContainer,
+ endOffset: rng.endOffset
+ };
+ }
+
+ return {rng : rng};
+ }
rng = t.getRng();
id = dom.uniqueId();
@@ -9581,7 +9748,7 @@ window.tinymce.dom.Sizzle = Sizzle;
},
moveToBookmark : function(bookmark) {
- var t = this, dom = t.dom, marker1, marker2, rng, root, startContainer, endContainer, startOffset, endOffset;
+ var t = this, dom = t.dom, marker1, marker2, rng, rng2, root, startContainer, endContainer, startOffset, endOffset;
function setEndPoint(start) {
var point = bookmark[start ? 'start' : 'end'], i, node, offset, children;
@@ -9711,8 +9878,24 @@ window.tinymce.dom.Sizzle = Sizzle;
}
} else if (bookmark.name) {
t.select(dom.select(bookmark.name)[bookmark.index]);
- } else if (bookmark.rng)
- t.setRng(bookmark.rng);
+ } else if (bookmark.rng) {
+ rng = bookmark.rng;
+
+ if (rng.startContainer) {
+ rng2 = t.dom.createRng();
+
+ try {
+ rng2.setStart(rng.startContainer, rng.startOffset);
+ rng2.setEnd(rng.endContainer, rng.endOffset);
+ } catch (e) {
+ // Might fail with index error
+ }
+
+ rng = rng2;
+ }
+
+ t.setRng(rng);
+ }
}
},
@@ -9811,7 +9994,7 @@ window.tinymce.dom.Sizzle = Sizzle;
}
// We have W3C ranges and it's IE then fake control selection since IE9 doesn't handle that correctly yet
- if (tinymce.isIE && rng && rng.setStart && doc.selection.createRange().item) {
+ if (tinymce.isIE && ! tinymce.isIE11 && rng && rng.setStart && doc.selection.createRange().item) {
elm = doc.selection.createRange().item(0);
rng = doc.createRange();
rng.setStartBefore(elm);
@@ -10224,6 +10407,16 @@ window.tinymce.dom.Sizzle = Sizzle;
return self;
},
+ scrollIntoView: function(elm) {
+ var y, viewPort, self = this, dom = self.dom;
+
+ viewPort = dom.getViewPort(self.editor.getWin());
+ y = dom.getPos(elm).y;
+ if (y < viewPort.y || y + 25 > viewPort.y + viewPort.h) {
+ self.editor.getWin().scrollTo(0, y < viewPort.y ? y : y - viewPort.h + 25);
+ }
+ },
+
destroy : function(manual) {
var self = this;
@@ -10396,6 +10589,18 @@ window.tinymce.dom.Sizzle = Sizzle;
}
});
+ htmlParser.addNodeFilter('noscript', function(nodes) {
+ var i = nodes.length, node;
+
+ while (i--) {
+ node = nodes[i].firstChild;
+
+ if (node) {
+ node.value = tinymce.html.Entities.decode(node.value);
+ }
+ }
+ });
+
// Force script into CDATA sections and remove the mce- prefix also add comments around styles
htmlParser.addNodeFilter('script,style', function(nodes, name) {
var i = nodes.length, node, value;
@@ -10654,7 +10859,7 @@ window.tinymce.dom.Sizzle = Sizzle;
// Add onload listener for non IE browsers since IE9
// fires onload event before the script is parsed and executed
- if (!tinymce.isIE)
+ if (!tinymce.isIE || tinymce.isIE11)
elm.onload = done;
// Add onerror event will get fired on some browsers but not all of them
@@ -11067,18 +11272,22 @@ window.tinymce.dom.Sizzle = Sizzle;
switch (evt.keyCode) {
case DOM_VK_LEFT:
if (enableLeftRight) t.moveFocus(-1);
+ Event.cancel(evt);
break;
case DOM_VK_RIGHT:
if (enableLeftRight) t.moveFocus(1);
+ Event.cancel(evt);
break;
case DOM_VK_UP:
if (enableUpDown) t.moveFocus(-1);
+ Event.cancel(evt);
break;
case DOM_VK_DOWN:
if (enableUpDown) t.moveFocus(1);
+ Event.cancel(evt);
break;
case DOM_VK_ESCAPE:
@@ -11775,7 +11984,7 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', {
else
h += '<span class="mceIcon ' + s['class'] + '"></span>' + (l ? '<span class="' + cp + 'Label">' + l + '</span>' : '');
- h += '<span class="mceVoiceLabel mceIconOnly" style="display: none;" id="' + this.id + '_voice">' + s.title + '</span>';
+ h += '<span class="mceVoiceLabel mceIconOnly" style="display: none;" id="' + this.id + '_voice">' + s.title + '</span>';
h += '</a>';
return h;
},
@@ -11800,9 +12009,11 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', {
return s.onclick.call(s.scope, e);
}
});
- tinymce.dom.Event.add(t.id, 'keyup', function(e) {
- if (!t.isDisabled() && e.keyCode==tinymce.VK.SPACEBAR)
+ tinymce.dom.Event.add(t.id, 'keydown', function(e) {
+ if (!t.isDisabled() && e.keyCode==tinymce.VK.SPACEBAR) {
+ tinymce.dom.Event.cancel(e);
return s.onclick.call(s.scope, e);
+ }
});
}
});
@@ -12215,7 +12426,7 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', {
// Accessibility keyhandler
Event.add(t.id, 'keydown', function(e) {
- var bf;
+ var bf, DOM_VK_LEFT = 37, DOM_VK_RIGHT = 39, DOM_VK_UP = 38, DOM_VK_DOWN = 40, DOM_VK_RETURN = 13, DOM_VK_SPACE = 32;
Event.remove(t.id, 'change', ch);
changeListenerAdded = false;
@@ -12227,14 +12438,12 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', {
Event.remove(t.id, 'blur', bf);
});
- //prevent default left and right keys on chrome - so that the keyboard navigation is used.
- if (tinymce.isWebKit && (e.keyCode==37 ||e.keyCode==39)) {
- return Event.prevent(e);
- }
-
- if (e.keyCode == 13 || e.keyCode == 32) {
+ if (e.keyCode == DOM_VK_RETURN || e.keyCode == DOM_VK_SPACE) {
onChange(e);
return Event.cancel(e);
+ } else if (e.keyCode == DOM_VK_DOWN || e.keyCode == DOM_VK_UP) {
+ // allow native implementation (navigate select element options)
+ e.stopImmediatePropagation();
}
});
@@ -13037,6 +13246,9 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
if (id === undef)
return this.editors;
+ if (!this.editors.hasOwnProperty(id))
+ return undef;
+
return this.editors[id];
},
@@ -13120,7 +13332,7 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
ed.render();
// Fix IE memory leaks
- if (tinymce.isIE) {
+ if (tinymce.isIE && ! tinymce.isIE11) {
w.attachEvent('onunload', clr);
}
@@ -13518,10 +13730,16 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
// Store away the selection when it's changed to it can be restored later with a editor.focus() call
if (isIE) {
t.onInit.add(function(ed) {
- ed.dom.bind(ed.getBody(), 'beforedeactivate keydown', function() {
- ed.lastIERng = ed.selection.getRng();
+ ed.dom.bind(ed.getBody(), 'beforedeactivate keydown keyup', function() {
+ ed.bookmark = ed.selection.getBookmark(1);
});
});
+
+ t.onNodeChange.add(function(ed) {
+ if (document.activeElement.id == ed.id + "_ifr") {
+ ed.bookmark = ed.selection.getBookmark(1);
+ }
+ });
}
}
@@ -13558,10 +13776,12 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
t.iframeHTML += '<base href="' + t.documentBaseURI.getURI() + '" />';
// IE8 doesn't support carets behind images setting ie7_compat would force IE8+ to run in IE7 compat mode.
- if (s.ie7_compat)
- t.iframeHTML += '<meta http-equiv="X-UA-Compatible" content="IE=7" />';
- else
- t.iframeHTML += '<meta http-equiv="X-UA-Compatible" content="IE=edge" />';
+ if (tinymce.isIE8) {
+ if (s.ie7_compat)
+ t.iframeHTML += '<meta http-equiv="X-UA-Compatible" content="IE=7" />';
+ else
+ t.iframeHTML += '<meta http-equiv="X-UA-Compatible" content="IE=edge" />';
+ }
t.iframeHTML += '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />';
@@ -13839,8 +14059,9 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
var oed, self = this, selection = self.selection, contentEditable = self.settings.content_editable, ieRng, controlElm, doc = self.getDoc(), body;
if (!skip_focus) {
- if (self.lastIERng) {
- selection.setRng(self.lastIERng);
+ if (self.bookmark) {
+ selection.moveToBookmark(self.bookmark);
+ self.bookmark = null;
}
// Get selected control element
@@ -13861,7 +14082,7 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
body = self.getBody();
// Check for setActive since it doesn't scroll to the element
- if (body.setActive) {
+ if (body.setActive && ! tinymce.isIE11) {
body.setActive();
} else {
body.focus();
@@ -14189,6 +14410,8 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
// We must save before we hide so Safari doesn't crash
self.save();
+
+ // defer the call to hide to prevent an IE9 crash #4921
DOM.hide(self.getContainer());
DOM.setStyle(self.id, 'display', self.orgDisplay);
},
@@ -14468,11 +14691,19 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
},
remove : function() {
- var self = this, elm = self.getContainer();
+ var self = this, elm = self.getContainer(), doc = self.getDoc();
if (!self.removed) {
self.removed = 1; // Cancels post remove event execution
- self.hide();
+
+ // Fixed bug where IE has a blinking cursor left from the editor
+ if (isIE && doc)
+ doc.execCommand('SelectAll');
+
+ // We must save before we hide so Safari doesn't crash
+ self.save();
+
+ DOM.setStyle(self.id, 'display', self.orgDisplay);
// Don't clear the window or document if content editable
// is enabled since other instances might still be present
@@ -15465,7 +15696,7 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
// Add undo level on save contents, drag end and blur/focusout
editor.onSaveContent.add(addNonTypingUndoLevel);
editor.dom.bind(editor.dom.getRoot(), 'dragend', addNonTypingUndoLevel);
- editor.dom.bind(editor.getDoc(), tinymce.isGecko ? 'blur' : 'focusout', function(e) {
+ editor.dom.bind(editor.getBody(), 'focusout', function(e) {
if (!editor.removed && self.typing) {
addNonTypingUndoLevel();
}
@@ -16248,6 +16479,7 @@ tinymce.ForceBlocks = function(editor) {
TreeWalker = tinymce.dom.TreeWalker,
rangeUtils = new tinymce.dom.RangeUtils(dom),
isValid = ed.schema.isValidChild,
+ isArray = tinymce.isArray,
isBlock = dom.isBlock,
forcedRootBlock = ed.settings.forced_root_block,
nodeIndex = dom.nodeIndex,
@@ -16259,9 +16491,13 @@ tinymce.ForceBlocks = function(editor) {
undef,
getContentEditable = dom.getContentEditable;
- function isArray(obj) {
- return obj instanceof Array;
- };
+ function isTextBlock(name) {
+ if (name.nodeType) {
+ name = name.nodeName;
+ }
+
+ return !!ed.schema.getTextBlockElements()[name.toLowerCase()];
+ }
function getParents(node, selector) {
return dom.getParents(node, selector, dom.getRoot());
@@ -16621,7 +16857,7 @@ tinymce.ForceBlocks = function(editor) {
// Is it valid to wrap this item
if (contentEditable && !hasContentEditableState && isValid(wrapName, nodeName) && isValid(parentName, wrapName) &&
- !(!node_specific && node.nodeType === 3 && node.nodeValue.length === 1 && node.nodeValue.charCodeAt(0) === 65279) && !isCaretNode(node)) {
+ !(!node_specific && node.nodeType === 3 && node.nodeValue.length === 1 && node.nodeValue.charCodeAt(0) === 65279) && !isCaretNode(node) && (!format.inline || !isBlock(node))) {
// Start wrapping
if (!currentWrapElm) {
// Wrap the node
@@ -16827,6 +17063,11 @@ tinymce.ForceBlocks = function(editor) {
function process(node) {
var children, i, l, localContentEditable, lastContentEditable, hasContentEditableState;
+ // Skip on text nodes as they have neither format to remove nor children
+ if (node.nodeType === 3) {
+ return;
+ }
+
// Node has a contentEditable value
if (node.nodeType === 1 && getContentEditable(node)) {
lastContentEditable = contentEditable;
@@ -17320,6 +17561,10 @@ tinymce.ForceBlocks = function(editor) {
siblingName = start ? 'previousSibling' : 'nextSibling';
root = dom.getRoot();
+ function isBogusBr(node) {
+ return node.nodeName == "BR" && node.getAttribute('data-mce-bogus') && !node.nextSibling;
+ };
+
// If it's a text node and the offset is inside the text
if (container.nodeType == 3 && !isWhiteSpaceNode(container)) {
if (start ? startOffset > 0 : endOffset < container.nodeValue.length) {
@@ -17334,7 +17579,7 @@ tinymce.ForceBlocks = function(editor) {
// Walk left/right
for (sibling = parent[siblingName]; sibling; sibling = sibling[siblingName]) {
- if (!isBookmarkNode(sibling) && !isWhiteSpaceNode(sibling)) {
+ if (!isBookmarkNode(sibling) && !isWhiteSpaceNode(sibling) && !isBogusBr(sibling)) {
return parent;
}
}
@@ -17493,7 +17738,7 @@ tinymce.ForceBlocks = function(editor) {
// Expand to first wrappable block element or any block element
if (!node)
- node = dom.getParent(container.nodeType == 3 ? container.parentNode : container, isBlock);
+ node = dom.getParent(container.nodeType == 3 ? container.parentNode : container, isTextBlock);
// Exclude inner lists from wrapping
if (node && format[0].wrapper)
@@ -17892,10 +18137,6 @@ tinymce.ForceBlocks = function(editor) {
return next;
};
- function isTextBlock(name) {
- return /^(h[1-6]|p|div|pre|address|dl|dt|dd)$/.test(name);
- };
-
function getContainer(rng, start) {
var container, offset, lastIdx, walker;
@@ -18131,11 +18372,23 @@ tinymce.ForceBlocks = function(editor) {
node.appendChild(dom.doc.createTextNode(INVISIBLE_CHAR));
node = node.firstChild;
- // Insert caret container after the formated node
- dom.insertAfter(caretContainer, formatNode);
+ var block = dom.getParent(formatNode, isTextBlock);
+
+ if (block && dom.isEmpty(block)) {
+ // Replace formatNode with caretContainer when removing format from empty block like <p><b>|</b></p>
+ formatNode.parentNode.replaceChild(caretContainer, formatNode);
+ } else {
+ // Insert caret container after the formated node
+ dom.insertAfter(caretContainer, formatNode);
+ }
// Move selection to text node
selection.setCursorLocation(node, 1);
+
+ // If the formatNode is empty, we can remove it safely.
+ if (dom.isEmpty(formatNode)) {
+ dom.remove(formatNode);
+ }
}
};
@@ -18325,7 +18578,7 @@ tinymce.onAddEditor.add(function(tinymce, ed) {
function renderBlockOnIE(block) {
var oldRng;
- if (tinymce.isIE && dom.isBlock(block)) {
+ if (tinymce.isIE && !tinymce.isIE11 && dom.isBlock(block)) {
oldRng = selection.getRng();
block.appendChild(dom.create('span', null, '\u00a0'));
selection.select(block);
@@ -18440,6 +18693,11 @@ tinymce.onAddEditor.add(function(tinymce, ed) {
if (settings.keep_styles !== false) {
do {
if (/^(SPAN|STRONG|B|EM|I|FONT|STRIKE|U)$/.test(node.nodeName)) {
+ // Never clone a caret containers
+ if (node.id == '_mce_caret') {
+ continue;
+ }
+
clonedNode = node.cloneNode(false);
dom.setAttrib(clonedNode, 'id', ''); // Remove ID since it needs to be document unique
@@ -18455,8 +18713,8 @@ tinymce.onAddEditor.add(function(tinymce, ed) {
}
// BR is needed in empty blocks on non IE browsers
- if (!tinymce.isIE) {
- caretNode.innerHTML = '<br>';
+ if (!tinymce.isIE || tinymce.isIE11) {
+ caretNode.innerHTML = '<br data-mce-bogus="1">';
}
return block;
@@ -18617,26 +18875,24 @@ tinymce.onAddEditor.add(function(tinymce, ed) {
undoManager.add();
};
- // Walks the parent block to the right and look for BR elements
- function hasRightSideBr() {
+ // Walks the parent block to the right and look for any contents
+ function hasRightSideContent() {
var walker = new TreeWalker(container, parentBlock), node;
- while (node = walker.current()) {
- if (node.nodeName == 'BR') {
+ while (node = walker.next()) {
+ if (nonEmptyElementsMap[node.nodeName.toLowerCase()] || node.length > 0) {
return true;
}
-
- node = walker.next();
}
}
-
+
// Inserts a BR element if the forced_root_block option is set to false or empty string
function insertBr() {
- var brElm, extraBr;
+ var brElm, extraBr, marker;
if (container && container.nodeType == 3 && offset >= container.nodeValue.length) {
// Insert extra BR element at the end block elements
- if (!tinymce.isIE && !hasRightSideBr()) {
+ if ((!tinymce.isIE || tinymce.isIE11) && !hasRightSideContent()) {
brElm = dom.create('br');
rng.insertNode(brElm);
rng.setStartAfter(brElm);
@@ -18649,10 +18905,16 @@ tinymce.onAddEditor.add(function(tinymce, ed) {
rng.insertNode(brElm);
// Rendering modes below IE8 doesn't display BR elements in PRE unless we have a \n before it
- if (tinymce.isIE && parentBlockName == 'PRE' && (!documentMode || documentMode < 8)) {
+ if ((tinymce.isIE && !tinymce.isIE11) && parentBlockName == 'PRE' && (!documentMode || documentMode < 8)) {
brElm.parentNode.insertBefore(dom.doc.createTextNode('\r'), brElm);
}
+ // Insert temp marker and scroll to that
+ marker = dom.create('span', {}, '&nbsp;');
+ brElm.parentNode.insertBefore(marker, brElm);
+ selection.scrollIntoView(marker);
+ dom.remove(marker);
+
if (!extraBr) {
rng.setStartAfter(brElm);
rng.setEndAfter(brElm);
@@ -18697,7 +18959,7 @@ tinymce.onAddEditor.add(function(tinymce, ed) {
var lastChild;
// IE will render the blocks correctly other browsers needs a BR
- if (!tinymce.isIE) {
+ if (!tinymce.isIE || tinymce.isIE11) {
block.normalize(); // Remove empty text nodes that got left behind by the extract
// Check if the block is empty or contains a floated last child
@@ -18772,6 +19034,12 @@ tinymce.onAddEditor.add(function(tinymce, ed) {
parentBlockName = parentBlock ? parentBlock.nodeName.toUpperCase() : ''; // IE < 9 & HTML5
containerBlockName = containerBlock ? containerBlock.nodeName.toUpperCase() : ''; // IE < 9 & HTML5
+ // Enter inside block contained within a LI then split or insert before/after LI
+ if (containerBlockName == 'LI' && !evt.ctrlKey) {
+ parentBlock = containerBlock;
+ parentBlockName = containerBlockName;
+ }
+
// Handle enter in LI
if (parentBlockName == 'LI') {
if (!newBlockName && shiftKey) {