tinymce-rails 3.5.6 → 3.5.7

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.
@@ -6,9 +6,9 @@
6
6
  var tinymce = {
7
7
  majorVersion : '3',
8
8
 
9
- minorVersion : '5.6',
9
+ minorVersion : '5.7',
10
10
 
11
- releaseDate : '2012-07-26',
11
+ releaseDate : '2012-09-20',
12
12
 
13
13
  _init : function() {
14
14
  var t = this, d = document, na = navigator, ua = na.userAgent, i, nl, n, base, p, v;
@@ -107,12 +107,16 @@
107
107
  if (!t)
108
108
  return o !== undef;
109
109
 
110
- if (t == 'array' && (o.hasOwnProperty && o instanceof Array))
110
+ if (t == 'array' && tinymce.isArray(o))
111
111
  return true;
112
112
 
113
113
  return typeof(o) == t;
114
114
  },
115
115
 
116
+ isArray: Array.isArray || function(obj) {
117
+ return Object.prototype.toString.call(obj) === "[object Array]";
118
+ },
119
+
116
120
  makeMap : function(items, delim, map) {
117
121
  var i;
118
122
 
@@ -921,7 +925,7 @@ tinymce.create('tinymce.util.Dispatcher', {
921
925
  }
922
926
 
923
927
  if (t == 'object') {
924
- if (o.hasOwnProperty && o instanceof Array) {
928
+ if (o.hasOwnProperty && Object.prototype.toString.call(o) === '[object Array]') {
925
929
  for (i=0, v = '['; i<o.length; i++)
926
930
  v += (i > 0 ? ',' : '') + serialize(o[i], quote);
927
931
 
@@ -1093,7 +1097,8 @@ tinymce.create('static tinymce.util.XHR', {
1093
1097
  })(tinymce);
1094
1098
 
1095
1099
  tinymce.util.Quirks = function(editor) {
1096
- var VK = tinymce.VK, BACKSPACE = VK.BACKSPACE, DELETE = VK.DELETE, dom = editor.dom, selection = editor.selection, settings = editor.settings;
1100
+ var VK = tinymce.VK, BACKSPACE = VK.BACKSPACE, DELETE = VK.DELETE, dom = editor.dom, selection = editor.selection,
1101
+ settings = editor.settings, parser = editor.parser, serializer = editor.serializer;
1097
1102
 
1098
1103
  function setEditorCommandState(cmd, state) {
1099
1104
  try {
@@ -1109,6 +1114,10 @@ tinymce.util.Quirks = function(editor) {
1109
1114
  return documentMode ? documentMode : 6;
1110
1115
  };
1111
1116
 
1117
+ function isDefaultPrevented(e) {
1118
+ return e.isDefaultPrevented();
1119
+ };
1120
+
1112
1121
  function cleanupStylesWhenDeleting() {
1113
1122
  function removeMergedFormatSpans(isDelete) {
1114
1123
  var rng, blockElm, node, clonedSpan;
@@ -1158,7 +1167,7 @@ tinymce.util.Quirks = function(editor) {
1158
1167
  var isDelete;
1159
1168
 
1160
1169
  isDelete = e.keyCode == DELETE;
1161
- if (!e.isDefaultPrevented() && (isDelete || e.keyCode == BACKSPACE) && !VK.modifierPressed(e)) {
1170
+ if (!isDefaultPrevented(e) && (isDelete || e.keyCode == BACKSPACE) && !VK.modifierPressed(e)) {
1162
1171
  e.preventDefault();
1163
1172
  removeMergedFormatSpans(isDelete);
1164
1173
  }
@@ -1189,7 +1198,7 @@ tinymce.util.Quirks = function(editor) {
1189
1198
  var keyCode = e.keyCode, isCollapsed;
1190
1199
 
1191
1200
  // Empty the editor if it's needed for example backspace at <p><b>|</b></p>
1192
- if (!e.isDefaultPrevented() && (keyCode == DELETE || keyCode == BACKSPACE)) {
1201
+ if (!isDefaultPrevented(e) && (keyCode == DELETE || keyCode == BACKSPACE)) {
1193
1202
  isCollapsed = editor.selection.isCollapsed();
1194
1203
 
1195
1204
  // Selection is collapsed but the editor isn't empty
@@ -1217,7 +1226,7 @@ tinymce.util.Quirks = function(editor) {
1217
1226
 
1218
1227
  function selectAll() {
1219
1228
  editor.onKeyDown.add(function(editor, e) {
1220
- if (e.keyCode == 65 && VK.metaKeyPressed(e)) {
1229
+ if (!isDefaultPrevented(e) && e.keyCode == 65 && VK.metaKeyPressed(e)) {
1221
1230
  e.preventDefault();
1222
1231
  editor.execCommand('SelectAll');
1223
1232
  }
@@ -1243,7 +1252,7 @@ tinymce.util.Quirks = function(editor) {
1243
1252
 
1244
1253
  function removeHrOnBackspace() {
1245
1254
  editor.onKeyDown.add(function(editor, e) {
1246
- if (!e.isDefaultPrevented() && e.keyCode === BACKSPACE) {
1255
+ if (!isDefaultPrevented(e) && e.keyCode === BACKSPACE) {
1247
1256
  if (selection.isCollapsed() && selection.getRng(true).startOffset === 0) {
1248
1257
  var node = selection.getNode();
1249
1258
  var previousSibling = node.previousSibling;
@@ -1262,7 +1271,7 @@ tinymce.util.Quirks = function(editor) {
1262
1271
  // wouldn't get proper focus if the user clicked on the HTML element
1263
1272
  if (!Range.prototype.getClientRects) { // Detect getClientRects got introduced in FF 4
1264
1273
  editor.onMouseDown.add(function(editor, e) {
1265
- if (e.target.nodeName === "HTML") {
1274
+ if (!isDefaultPrevented(e) && e.target.nodeName === "HTML") {
1266
1275
  var body = editor.getBody();
1267
1276
 
1268
1277
  // Blur the body it's focused but not correctly focused
@@ -1325,7 +1334,7 @@ tinymce.util.Quirks = function(editor) {
1325
1334
  editor.onKeyPress.add(function(editor, e) {
1326
1335
  var applyAttributes;
1327
1336
 
1328
- if ((e.keyCode == 8 || e.keyCode == 46) && isSelectionAcrossElements()) {
1337
+ if (!isDefaultPrevented(e) && (e.keyCode == 8 || e.keyCode == 46) && isSelectionAcrossElements()) {
1329
1338
  applyAttributes = getAttributeApplyFunction();
1330
1339
  editor.getDoc().execCommand('delete', false, null);
1331
1340
  applyAttributes();
@@ -1337,7 +1346,7 @@ tinymce.util.Quirks = function(editor) {
1337
1346
  dom.bind(editor.getDoc(), 'cut', function(e) {
1338
1347
  var applyAttributes;
1339
1348
 
1340
- if (isSelectionAcrossElements()) {
1349
+ if (!isDefaultPrevented(e) && isSelectionAcrossElements()) {
1341
1350
  applyAttributes = getAttributeApplyFunction();
1342
1351
  editor.onKeyUp.addToTop(blockEvent);
1343
1352
 
@@ -1376,7 +1385,7 @@ tinymce.util.Quirks = function(editor) {
1376
1385
 
1377
1386
  function disableBackspaceIntoATable() {
1378
1387
  editor.onKeyDown.add(function(editor, e) {
1379
- if (!e.isDefaultPrevented() && e.keyCode === BACKSPACE) {
1388
+ if (!isDefaultPrevented(e) && e.keyCode === BACKSPACE) {
1380
1389
  if (selection.isCollapsed() && selection.getRng(true).startOffset === 0) {
1381
1390
  var previousSibling = selection.getNode().previousSibling;
1382
1391
  if (previousSibling && previousSibling.nodeName && previousSibling.nodeName.toLowerCase() === "table") {
@@ -1400,7 +1409,7 @@ tinymce.util.Quirks = function(editor) {
1400
1409
  dom.addClass(editor.getBody(), 'mceHideBrInPre');
1401
1410
 
1402
1411
  // Adds a \n before all BR elements in PRE to get them visual
1403
- editor.parser.addNodeFilter('pre', function(nodes, name) {
1412
+ parser.addNodeFilter('pre', function(nodes, name) {
1404
1413
  var i = nodes.length, brNodes, j, brElm, sibling;
1405
1414
 
1406
1415
  while (i--) {
@@ -1421,7 +1430,7 @@ tinymce.util.Quirks = function(editor) {
1421
1430
  });
1422
1431
 
1423
1432
  // Removes any \n before BR elements in PRE since other browsers and in contentEditable=false mode they will be visible
1424
- editor.serializer.addNodeFilter('pre', function(nodes, name) {
1433
+ serializer.addNodeFilter('pre', function(nodes, name) {
1425
1434
  var i = nodes.length, brNodes, j, brElm, sibling;
1426
1435
 
1427
1436
  while (i--) {
@@ -1464,7 +1473,7 @@ tinymce.util.Quirks = function(editor) {
1464
1473
  var isDelete, rng, container, offset, brElm, sibling, collapsed;
1465
1474
 
1466
1475
  isDelete = e.keyCode == DELETE;
1467
- if (!e.isDefaultPrevented() && (isDelete || e.keyCode == BACKSPACE) && !VK.modifierPressed(e)) {
1476
+ if (!isDefaultPrevented(e) && (isDelete || e.keyCode == BACKSPACE) && !VK.modifierPressed(e)) {
1468
1477
  rng = selection.getRng();
1469
1478
  container = rng.startContainer;
1470
1479
  offset = rng.startOffset;
@@ -1504,7 +1513,7 @@ tinymce.util.Quirks = function(editor) {
1504
1513
  editor.onKeyDown.add(function(editor, e) {
1505
1514
  var rng, container, offset, root, parent;
1506
1515
 
1507
- if (e.isDefaultPrevented() || e.keyCode != VK.BACKSPACE) {
1516
+ if (isDefaultPrevented(e) || e.keyCode != VK.BACKSPACE) {
1508
1517
  return;
1509
1518
  }
1510
1519
 
@@ -1528,10 +1537,10 @@ tinymce.util.Quirks = function(editor) {
1528
1537
  editor.formatter.toggle('blockquote', null, parent);
1529
1538
 
1530
1539
  // Move the caret to the beginning of container
1540
+ rng = dom.createRng();
1531
1541
  rng.setStart(container, 0);
1532
1542
  rng.setEnd(container, 0);
1533
1543
  selection.setRng(rng);
1534
- selection.collapse(false);
1535
1544
  }
1536
1545
  });
1537
1546
  };
@@ -1606,7 +1615,7 @@ tinymce.util.Quirks = function(editor) {
1606
1615
  editor.onKeyDown.add(function(editor, e) {
1607
1616
  var rng;
1608
1617
 
1609
- if (!e.isDefaultPrevented() && e.keyCode == BACKSPACE) {
1618
+ if (!isDefaultPrevented(e) && e.keyCode == BACKSPACE) {
1610
1619
  rng = editor.getDoc().selection.createRange();
1611
1620
  if (rng && rng.item) {
1612
1621
  e.preventDefault();
@@ -1865,6 +1874,46 @@ tinymce.util.Quirks = function(editor) {
1865
1874
  });
1866
1875
  }
1867
1876
 
1877
+ function keepNoScriptContents() {
1878
+ if (getDocumentMode() < 9) {
1879
+ parser.addNodeFilter('noscript', function(nodes) {
1880
+ var i = nodes.length, node, textNode;
1881
+
1882
+ while (i--) {
1883
+ node = nodes[i];
1884
+ textNode = node.firstChild;
1885
+
1886
+ if (textNode) {
1887
+ node.attr('data-mce-innertext', textNode.value);
1888
+ }
1889
+ }
1890
+ });
1891
+
1892
+ serializer.addNodeFilter('noscript', function(nodes) {
1893
+ var i = nodes.length, node, textNode, value;
1894
+
1895
+ while (i--) {
1896
+ node = nodes[i];
1897
+ textNode = nodes[i].firstChild;
1898
+
1899
+ if (textNode) {
1900
+ textNode.value = tinymce.html.Entities.decode(textNode.value);
1901
+ } else {
1902
+ // Old IE can't retain noscript value so an attribute is used to store it
1903
+ value = node.attributes.map['data-mce-innertext'];
1904
+ if (value) {
1905
+ node.attr('data-mce-innertext', null);
1906
+ textNode = new tinymce.html.Node('#text', 3);
1907
+ textNode.value = value;
1908
+ textNode.raw = true;
1909
+ node.append(textNode);
1910
+ }
1911
+ }
1912
+ }
1913
+ });
1914
+ }
1915
+ }
1916
+
1868
1917
  // All browsers
1869
1918
  disableBackspaceIntoATable();
1870
1919
  removeBlockQuoteOnBackSpace();
@@ -1895,6 +1944,7 @@ tinymce.util.Quirks = function(editor) {
1895
1944
  removePreSerializedStylesWhenSelectingControls();
1896
1945
  deleteControlItemOnBackSpace();
1897
1946
  renderEmptyBlocksFix();
1947
+ keepNoScriptContents();
1898
1948
  }
1899
1949
 
1900
1950
  // Gecko
@@ -2449,7 +2499,7 @@ tinymce.html.Styles = function(settings, schema) {
2449
2499
  'form[A|accept-charset|action|autocomplete|enctype|method|name|novalidate|target][C]' +
2450
2500
  'fieldset[A|disabled|form|name][C|legend]' +
2451
2501
  'label[A|form|for][B]' +
2452
- 'input[A|type|accept|alt|autocomplete|checked|disabled|form|formaction|formenctype|formmethod|formnovalidate|formtarget|height|list|max|maxlength|min|' +
2502
+ 'input[A|type|accept|alt|autocomplete|autofocus|checked|disabled|form|formaction|formenctype|formmethod|formnovalidate|formtarget|height|list|max|maxlength|min|' +
2453
2503
  'multiple|pattern|placeholder|readonly|required|size|src|step|width|files|value|name][]' +
2454
2504
  'button[A|autofocus|disabled|form|formaction|formenctype|formmethod|formnovalidate|formtarget|name|value|type][B]' +
2455
2505
  'select[A|autofocus|disabled|form|multiple|name|size][option|optgroup]' +
@@ -2653,14 +2703,15 @@ tinymce.html.Styles = function(settings, schema) {
2653
2703
  }
2654
2704
 
2655
2705
  // Setup map objects
2656
- whiteSpaceElementsMap = createLookupTable('whitespace_elements', 'pre script style textarea');
2706
+ whiteSpaceElementsMap = createLookupTable('whitespace_elements', 'pre script noscript style textarea');
2657
2707
  selfClosingElementsMap = createLookupTable('self_closing_elements', 'colgroup dd dt li option p td tfoot th thead tr');
2658
2708
  shortEndedElementsMap = createLookupTable('short_ended_elements', 'area base basefont br col frame hr img input isindex link meta param embed source wbr');
2659
2709
  boolAttrMap = createLookupTable('boolean_attributes', 'checked compact declare defer disabled ismap multiple nohref noresize noshade nowrap readonly selected autoplay loop controls');
2660
2710
  nonEmptyElementsMap = createLookupTable('non_empty_elements', 'td th iframe video audio object', shortEndedElementsMap);
2661
- blockElementsMap = createLookupTable('block_elements', 'h1 h2 h3 h4 h5 h6 hr p div address pre form table tbody thead tfoot ' +
2662
- 'th tr td li ol ul caption blockquote center dl dt dd dir fieldset ' +
2663
- 'noscript menu isindex samp header footer article section hgroup aside nav figure option datalist select optgroup');
2711
+ textBlockElementsMap = createLookupTable('text_block_elements', 'h1 h2 h3 h4 h5 h6 p div address pre form ' +
2712
+ 'blockquote center dir fieldset header footer article section hgroup aside nav figure');
2713
+ blockElementsMap = createLookupTable('block_elements', 'hr table tbody thead tfoot ' +
2714
+ 'th tr td li ol ul caption dl dt dd noscript menu isindex samp option datalist select optgroup', textBlockElementsMap);
2664
2715
 
2665
2716
  // Converts a wildcard expression string to a regexp for example *a will become /.*a/.
2666
2717
  function patternToRegExp(str) {
@@ -2834,8 +2885,15 @@ tinymce.html.Styles = function(settings, schema) {
2834
2885
  customElementsMap[name] = cloneName;
2835
2886
 
2836
2887
  // If it's not marked as inline then add it to valid block elements
2837
- if (!inline)
2888
+ if (!inline) {
2889
+ blockElementsMap[name.toUpperCase()] = {};
2838
2890
  blockElementsMap[name] = {};
2891
+ }
2892
+
2893
+ // Add elements clone if needed
2894
+ if (!elements[name]) {
2895
+ elements[name] = elements[cloneName];
2896
+ }
2839
2897
 
2840
2898
  // Add custom elements at span/div positions
2841
2899
  each(children, function(element, child) {
@@ -2960,6 +3018,10 @@ tinymce.html.Styles = function(settings, schema) {
2960
3018
  return blockElementsMap;
2961
3019
  };
2962
3020
 
3021
+ self.getTextBlockElements = function() {
3022
+ return textBlockElementsMap;
3023
+ };
3024
+
2963
3025
  self.getShortEndedElements = function() {
2964
3026
  return shortEndedElementsMap;
2965
3027
  };
@@ -3025,6 +3087,8 @@ tinymce.html.Styles = function(settings, schema) {
3025
3087
  self.addCustomElements = addCustomElements;
3026
3088
 
3027
3089
  self.addValidChildren = addValidChildren;
3090
+
3091
+ self.elements = elements;
3028
3092
  };
3029
3093
  })(tinymce);
3030
3094
 
@@ -3082,7 +3146,7 @@ tinymce.html.Styles = function(settings, schema) {
3082
3146
  value = name in fillAttrsMap ? name : decode(value || val2 || val3 || ''); // Handle boolean attribute than value attribute
3083
3147
 
3084
3148
  // Validate name and value
3085
- if (validate && !isInternalElement && name.indexOf('data-') !== 0) {
3149
+ if (validate && !isInternalElement && name.indexOf('data-mce-') !== 0) {
3086
3150
  attrRule = validAttributesMap[name];
3087
3151
 
3088
3152
  // Find rule by pattern matching
@@ -3123,10 +3187,10 @@ tinymce.html.Styles = function(settings, schema) {
3123
3187
  '(?:!DOCTYPE([\\w\\W]*?)>)|' + // DOCTYPE
3124
3188
  '(?:\\?([^\\s\\/<>]+) ?([\\w\\W]*?)[?/]>)|' + // PI
3125
3189
  '(?:\\/([^>]+)>)|' + // End element
3126
- '(?:([A-Za-z0-9\\-\\:]+)((?:\\s+[^"\'>]+(?:(?:"[^"]*")|(?:\'[^\']*\')|[^>]*))*|\\/|\\s+)>)' + // Start element
3190
+ '(?:([A-Za-z0-9\\-\\:\\.]+)((?:\\s+[^"\'>]+(?:(?:"[^"]*")|(?:\'[^\']*\')|[^>]*))*|\\/|\\s+)>)' + // Start element
3127
3191
  ')', 'g');
3128
3192
 
3129
- attrRegExp = /([\w:\-]+)(?:\s*=\s*(?:(?:\"((?:\\.|[^\"])*)\")|(?:\'((?:\\.|[^\'])*)\')|([^>\s]+)))?/g;
3193
+ attrRegExp = /([\w:\-]+)(?:\s*=\s*(?:(?:\"((?:[^\"])*)\")|(?:\'((?:[^\'])*)\')|([^>\s]+)))?/g;
3130
3194
  specialElements = {
3131
3195
  'script' : /<\/script[^>]*>/gi,
3132
3196
  'style' : /<\/style[^>]*>/gi,
@@ -3609,7 +3673,7 @@ tinymce.html.Styles = function(settings, schema) {
3609
3673
  i = node.attributes.length;
3610
3674
  while (i--) {
3611
3675
  name = node.attributes[i].name;
3612
- if (name === "name" || name.indexOf('data-') === 0)
3676
+ if (name === "name" || name.indexOf('data-mce-') === 0)
3613
3677
  return false;
3614
3678
  }
3615
3679
  }
@@ -3665,18 +3729,41 @@ tinymce.html.Styles = function(settings, schema) {
3665
3729
 
3666
3730
  function fixInvalidChildren(nodes) {
3667
3731
  var ni, node, parent, parents, newParent, currentNode, tempNode, childNode, i,
3668
- childClone, nonEmptyElements, nonSplitableElements, sibling, nextNode;
3732
+ childClone, nonEmptyElements, nonSplitableElements, textBlockElements, sibling, nextNode;
3669
3733
 
3670
3734
  nonSplitableElements = tinymce.makeMap('tr,td,th,tbody,thead,tfoot,table');
3671
3735
  nonEmptyElements = schema.getNonEmptyElements();
3736
+ textBlockElements = schema.getTextBlockElements();
3672
3737
 
3673
3738
  for (ni = 0; ni < nodes.length; ni++) {
3674
3739
  node = nodes[ni];
3675
3740
 
3676
- // Already removed
3677
- if (!node.parent)
3741
+ // Already removed or fixed
3742
+ if (!node.parent || node.fixed)
3678
3743
  continue;
3679
3744
 
3745
+ // If the invalid element is a text block and the text block is within a parent LI element
3746
+ // Then unwrap the first text block and convert other sibling text blocks to LI elements similar to Word/Open Office
3747
+ if (textBlockElements[node.name] && node.parent.name == 'li') {
3748
+ // Move sibling text blocks after LI element
3749
+ sibling = node.next;
3750
+ while (sibling) {
3751
+ if (textBlockElements[sibling.name]) {
3752
+ sibling.name = 'li';
3753
+ sibling.fixed = true;
3754
+ node.parent.insert(sibling, node.parent);
3755
+ } else {
3756
+ break;
3757
+ }
3758
+
3759
+ sibling = sibling.next;
3760
+ }
3761
+
3762
+ // Unwrap current text block
3763
+ node.unwrap(node);
3764
+ continue;
3765
+ }
3766
+
3680
3767
  // Get list of all parent nodes until we find a valid parent to stick the child into
3681
3768
  parents = [node];
3682
3769
  for (parent = node.parent; parent && !schema.isValidChild(parent.name, node.name) && !nonSplitableElements[parent.name]; parent = parent.parent)
@@ -4054,7 +4141,8 @@ tinymce.html.Styles = function(settings, schema) {
4054
4141
  }
4055
4142
 
4056
4143
  // Trim start white space
4057
- textNode = node.prev;
4144
+ // Removed due to: #5424
4145
+ /*textNode = node.prev;
4058
4146
  if (textNode && textNode.type === 3) {
4059
4147
  text = textNode.value.replace(startWhiteSpaceRegExp, '');
4060
4148
 
@@ -4062,7 +4150,7 @@ tinymce.html.Styles = function(settings, schema) {
4062
4150
  textNode.value = text;
4063
4151
  else
4064
4152
  textNode.remove();
4065
- }
4153
+ }*/
4066
4154
  }
4067
4155
 
4068
4156
  // Check if we exited a whitespace preserved element
@@ -4572,6 +4660,12 @@ tinymce.dom = {};
4572
4660
  }
4573
4661
  }
4574
4662
 
4663
+ // Page already loaded then fire it directly
4664
+ if (doc.readyState == "complete") {
4665
+ readyHandler();
4666
+ return;
4667
+ }
4668
+
4575
4669
  // Use W3C method
4576
4670
  if (w3cEventModel) {
4577
4671
  addEvent(win, 'DOMContentLoaded', readyHandler);
@@ -10396,6 +10490,18 @@ window.tinymce.dom.Sizzle = Sizzle;
10396
10490
  }
10397
10491
  });
10398
10492
 
10493
+ htmlParser.addNodeFilter('noscript', function(nodes) {
10494
+ var i = nodes.length, node;
10495
+
10496
+ while (i--) {
10497
+ node = nodes[i].firstChild;
10498
+
10499
+ if (node) {
10500
+ node.value = tinymce.html.Entities.decode(node.value);
10501
+ }
10502
+ }
10503
+ });
10504
+
10399
10505
  // Force script into CDATA sections and remove the mce- prefix also add comments around styles
10400
10506
  htmlParser.addNodeFilter('script,style', function(nodes, name) {
10401
10507
  var i = nodes.length, node, value;
@@ -13037,6 +13143,9 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
13037
13143
  if (id === undef)
13038
13144
  return this.editors;
13039
13145
 
13146
+ if (!this.editors.hasOwnProperty(id))
13147
+ return undef;
13148
+
13040
13149
  return this.editors[id];
13041
13150
  },
13042
13151
 
@@ -14189,7 +14298,11 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
14189
14298
 
14190
14299
  // We must save before we hide so Safari doesn't crash
14191
14300
  self.save();
14192
- DOM.hide(self.getContainer());
14301
+
14302
+ // defer the call to hide to prevent an IE9 crash #4921
14303
+ setTimeout(function() {
14304
+ DOM.hide(self.getContainer());
14305
+ }, 1);
14193
14306
  DOM.setStyle(self.id, 'display', self.orgDisplay);
14194
14307
  },
14195
14308
 
@@ -16248,6 +16361,7 @@ tinymce.ForceBlocks = function(editor) {
16248
16361
  TreeWalker = tinymce.dom.TreeWalker,
16249
16362
  rangeUtils = new tinymce.dom.RangeUtils(dom),
16250
16363
  isValid = ed.schema.isValidChild,
16364
+ isArray = tinymce.isArray,
16251
16365
  isBlock = dom.isBlock,
16252
16366
  forcedRootBlock = ed.settings.forced_root_block,
16253
16367
  nodeIndex = dom.nodeIndex,
@@ -16259,9 +16373,9 @@ tinymce.ForceBlocks = function(editor) {
16259
16373
  undef,
16260
16374
  getContentEditable = dom.getContentEditable;
16261
16375
 
16262
- function isArray(obj) {
16263
- return obj instanceof Array;
16264
- };
16376
+ function isTextBlock(name) {
16377
+ return !!ed.schema.getTextBlocks()[name.toLowerCase()];
16378
+ }
16265
16379
 
16266
16380
  function getParents(node, selector) {
16267
16381
  return dom.getParents(node, selector, dom.getRoot());
@@ -17320,6 +17434,10 @@ tinymce.ForceBlocks = function(editor) {
17320
17434
  siblingName = start ? 'previousSibling' : 'nextSibling';
17321
17435
  root = dom.getRoot();
17322
17436
 
17437
+ function isBogusBr(node) {
17438
+ return node.nodeName == "BR" && node.getAttribute('data-mce-bogus') && !node.nextSibling;
17439
+ };
17440
+
17323
17441
  // If it's a text node and the offset is inside the text
17324
17442
  if (container.nodeType == 3 && !isWhiteSpaceNode(container)) {
17325
17443
  if (start ? startOffset > 0 : endOffset < container.nodeValue.length) {
@@ -17334,7 +17452,7 @@ tinymce.ForceBlocks = function(editor) {
17334
17452
 
17335
17453
  // Walk left/right
17336
17454
  for (sibling = parent[siblingName]; sibling; sibling = sibling[siblingName]) {
17337
- if (!isBookmarkNode(sibling) && !isWhiteSpaceNode(sibling)) {
17455
+ if (!isBookmarkNode(sibling) && !isWhiteSpaceNode(sibling) && !isBogusBr(sibling)) {
17338
17456
  return parent;
17339
17457
  }
17340
17458
  }
@@ -17493,7 +17611,7 @@ tinymce.ForceBlocks = function(editor) {
17493
17611
 
17494
17612
  // Expand to first wrappable block element or any block element
17495
17613
  if (!node)
17496
- node = dom.getParent(container.nodeType == 3 ? container.parentNode : container, isBlock);
17614
+ node = dom.getParent(container.nodeType == 3 ? container.parentNode : container, isTextBlock);
17497
17615
 
17498
17616
  // Exclude inner lists from wrapping
17499
17617
  if (node && format[0].wrapper)
@@ -18440,6 +18558,11 @@ tinymce.onAddEditor.add(function(tinymce, ed) {
18440
18558
  if (settings.keep_styles !== false) {
18441
18559
  do {
18442
18560
  if (/^(SPAN|STRONG|B|EM|I|FONT|STRIKE|U)$/.test(node.nodeName)) {
18561
+ // Never clone a caret containers
18562
+ if (node.id == '_mce_caret') {
18563
+ continue;
18564
+ }
18565
+
18443
18566
  clonedNode = node.cloneNode(false);
18444
18567
  dom.setAttrib(clonedNode, 'id', ''); // Remove ID since it needs to be document unique
18445
18568
 
@@ -18456,7 +18579,7 @@ tinymce.onAddEditor.add(function(tinymce, ed) {
18456
18579
 
18457
18580
  // BR is needed in empty blocks on non IE browsers
18458
18581
  if (!tinymce.isIE) {
18459
- caretNode.innerHTML = '<br>';
18582
+ caretNode.innerHTML = '<br data-mce-bogus="1">';
18460
18583
  }
18461
18584
 
18462
18585
  return block;
@@ -18772,6 +18895,12 @@ tinymce.onAddEditor.add(function(tinymce, ed) {
18772
18895
  parentBlockName = parentBlock ? parentBlock.nodeName.toUpperCase() : ''; // IE < 9 & HTML5
18773
18896
  containerBlockName = containerBlock ? containerBlock.nodeName.toUpperCase() : ''; // IE < 9 & HTML5
18774
18897
 
18898
+ // Enter inside block contained within a LI then split or insert before/after LI
18899
+ if (containerBlockName == 'LI' && !evt.ctrlKey) {
18900
+ parentBlock = containerBlock;
18901
+ parentBlockName = containerBlockName;
18902
+ }
18903
+
18775
18904
  // Handle enter in LI
18776
18905
  if (parentBlockName == 'LI') {
18777
18906
  if (!newBlockName && shiftKey) {