tinymce-rails 4.5.2 → 4.5.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (29) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/source/tinymce/tinymce.js +236 -102
  3. data/lib/tinymce/rails/helper.rb +14 -9
  4. data/lib/tinymce/rails/version.rb +2 -2
  5. data/vendor/assets/javascripts/tinymce/plugins/anchor/plugin.js +1 -1
  6. data/vendor/assets/javascripts/tinymce/plugins/autolink/plugin.js +1 -1
  7. data/vendor/assets/javascripts/tinymce/plugins/autoresize/plugin.js +1 -1
  8. data/vendor/assets/javascripts/tinymce/plugins/codesample/plugin.js +1 -1
  9. data/vendor/assets/javascripts/tinymce/plugins/fullpage/plugin.js +1 -1
  10. data/vendor/assets/javascripts/tinymce/plugins/fullscreen/plugin.js +1 -1
  11. data/vendor/assets/javascripts/tinymce/plugins/image/plugin.js +1 -1
  12. data/vendor/assets/javascripts/tinymce/plugins/imagetools/plugin.js +1 -1
  13. data/vendor/assets/javascripts/tinymce/plugins/importcss/plugin.js +1 -1
  14. data/vendor/assets/javascripts/tinymce/plugins/link/plugin.js +1 -1
  15. data/vendor/assets/javascripts/tinymce/plugins/lists/plugin.js +1 -1
  16. data/vendor/assets/javascripts/tinymce/plugins/media/plugin.js +1 -1
  17. data/vendor/assets/javascripts/tinymce/plugins/paste/plugin.js +1 -1
  18. data/vendor/assets/javascripts/tinymce/plugins/searchreplace/plugin.js +1 -1
  19. data/vendor/assets/javascripts/tinymce/plugins/spellchecker/plugin.js +1 -1
  20. data/vendor/assets/javascripts/tinymce/plugins/table/plugin.js +2 -2
  21. data/vendor/assets/javascripts/tinymce/plugins/textcolor/plugin.js +1 -1
  22. data/vendor/assets/javascripts/tinymce/plugins/textpattern/plugin.js +1 -1
  23. data/vendor/assets/javascripts/tinymce/plugins/toc/plugin.js +1 -1
  24. data/vendor/assets/javascripts/tinymce/plugins/visualchars/plugin.js +1 -1
  25. data/vendor/assets/javascripts/tinymce/plugins/wordcount/plugin.js +1 -1
  26. data/vendor/assets/javascripts/tinymce/themes/inlite/theme.js +1 -1
  27. data/vendor/assets/javascripts/tinymce/themes/modern/theme.js +1 -1
  28. data/vendor/assets/javascripts/tinymce/tinymce.js +12 -12
  29. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 774856e68bfdc0e95ca168f1618932b9cdb08938
4
- data.tar.gz: aa4c60fc005a90f4c5f97a45ba7b669d422872f4
3
+ metadata.gz: 9808866a3ad5c5a46861b01522aafb0dba776911
4
+ data.tar.gz: be58c3335fbd9f2dc321ca66936752345ab1b636
5
5
  SHA512:
6
- metadata.gz: 4099dd85f4a21a4740bee21af2ed921a27c17b90f09bb89bdb23708934d1ef0d7161b7bc2a662b08d275e6456c48f97c5cd53d81aef3aaf2179bd7020273ca7a
7
- data.tar.gz: 21755728d8469875420cdccedafa14063f20d4f93e3b797cad17f6cc0f7c8f0e03a1b90e6a767083109dc2e828dd6814bd04991661c38bd8d48b6d400ddd10dd
6
+ metadata.gz: 85cbf78343282ee27f87884ab317ade4521eb490200883d3d754ac2b2169973ff08bbbf38c8da9a6897f1df9774e035c9569d6cd27a56437dca0ae649d8d8f31
7
+ data.tar.gz: 54a027cc2c06eb045f295e3564a1729c81ca03cf5535841aaab89b1734370876241bf841738f32d14940ca44a8850b4227602cdf0c1464c188225e2f53922676
@@ -1,4 +1,4 @@
1
- // 4.5.2 (2017-01-04)
1
+ // 4.5.3 (2017-02-01)
2
2
 
3
3
  /**
4
4
  * Compiled inline version. (Library mode)
@@ -7854,7 +7854,7 @@ define("tinymce/dom/DOMUtils", [
7854
7854
  * @method getParent
7855
7855
  * @param {Node/String} node DOM node to search parents on or ID string.
7856
7856
  * @param {function} selector Selection function or CSS selector to execute on each node.
7857
- * @param {Node} root Optional root element, never go below this point.
7857
+ * @param {Node} root Optional root element, never go beyond this point.
7858
7858
  * @return {Node} DOM Node or null if it wasn't found.
7859
7859
  */
7860
7860
  getParent: function(node, selector, root) {
@@ -7868,7 +7868,7 @@ define("tinymce/dom/DOMUtils", [
7868
7868
  * @method getParents
7869
7869
  * @param {Node/String} node DOM node to search parents on or ID string.
7870
7870
  * @param {function} selector Selection function to execute on each node or CSS pattern.
7871
- * @param {Node} root Optional root element, never go below this point.
7871
+ * @param {Node} root Optional root element, never go beyond this point.
7872
7872
  * @return {Array} Array of nodes or null if it wasn't found.
7873
7873
  */
7874
7874
  getParents: function(node, selector, root, collect) {
@@ -8981,12 +8981,13 @@ define("tinymce/dom/DOMUtils", [
8981
8981
  * @return {Boolean} true/false if the node is empty or not.
8982
8982
  */
8983
8983
  isEmpty: function(node, elements) {
8984
- var self = this, i, attributes, type, walker, name, brCount = 0;
8984
+ var self = this, i, attributes, type, whitespace, walker, name, brCount = 0;
8985
8985
 
8986
8986
  node = node.firstChild;
8987
8987
  if (node) {
8988
8988
  walker = new TreeWalker(node, node.parentNode);
8989
8989
  elements = elements || (self.schema ? self.schema.getNonEmptyElements() : null);
8990
+ whitespace = self.schema ? self.schema.getWhiteSpaceElements() : {};
8990
8991
 
8991
8992
  do {
8992
8993
  type = node.nodeType;
@@ -9029,7 +9030,12 @@ define("tinymce/dom/DOMUtils", [
9029
9030
  }
9030
9031
 
9031
9032
  // Keep non whitespace text nodes
9032
- if ((type === 3 && !whiteSpaceRegExp.test(node.nodeValue))) {
9033
+ if (type === 3 && !whiteSpaceRegExp.test(node.nodeValue)) {
9034
+ return false;
9035
+ }
9036
+
9037
+ // Keep whitespace preserve elements
9038
+ if (type === 3 && node.parentNode && whitespace[node.parentNode.nodeName] && whiteSpaceRegExp.test(node.nodeValue)) {
9033
9039
  return false;
9034
9040
  }
9035
9041
 
@@ -11558,11 +11564,14 @@ define("tinymce/html/Node", [], function() {
11558
11564
  * node.isEmpty({img: true});
11559
11565
  * @method isEmpty
11560
11566
  * @param {Object} elements Name/value object with elements that are automatically treated as non empty elements.
11567
+ * @param {Object} whitespace Name/value object with elements that are automatically treated whitespace preservables.
11561
11568
  * @return {Boolean} true/false if the node is empty or not.
11562
11569
  */
11563
- isEmpty: function(elements) {
11570
+ isEmpty: function(elements, whitespace) {
11564
11571
  var self = this, node = self.firstChild, i, name;
11565
11572
 
11573
+ whitespace = whitespace || {};
11574
+
11566
11575
  if (node) {
11567
11576
  do {
11568
11577
  if (node.type === 1) {
@@ -11592,7 +11601,12 @@ define("tinymce/html/Node", [], function() {
11592
11601
  }
11593
11602
 
11594
11603
  // Keep non whitespace text nodes
11595
- if ((node.type === 3 && !whiteSpaceRegExp.test(node.value))) {
11604
+ if (node.type === 3 && !whiteSpaceRegExp.test(node.value)) {
11605
+ return false;
11606
+ }
11607
+
11608
+ // Keep whitespace preserve elements
11609
+ if (node.type === 3 && node.parent && whitespace[node.parent.name] && whiteSpaceRegExp.test(node.value)) {
11596
11610
  return false;
11597
11611
  }
11598
11612
  } while ((node = walk(node, self)));
@@ -12026,13 +12040,17 @@ define("tinymce/html/Schema", [
12026
12040
  validClasses = compileElementMap(settings.valid_classes, 'map');
12027
12041
 
12028
12042
  // Setup map objects
12029
- whiteSpaceElementsMap = createLookupTable('whitespace_elements', 'pre script noscript style textarea video audio iframe object');
12043
+ whiteSpaceElementsMap = createLookupTable(
12044
+ 'whitespace_elements',
12045
+ 'pre script noscript style textarea video audio iframe object code'
12046
+ );
12030
12047
  selfClosingElementsMap = createLookupTable('self_closing_elements', 'colgroup dd dt li option p td tfoot th thead tr');
12031
12048
  shortEndedElementsMap = createLookupTable('short_ended_elements', 'area base basefont br col frame hr img input isindex link ' +
12032
12049
  'meta param embed source wbr track');
12033
12050
  boolAttrMap = createLookupTable('boolean_attributes', 'checked compact declare defer disabled ismap multiple nohref noresize ' +
12034
12051
  'noshade nowrap readonly selected autoplay loop controls');
12035
- nonEmptyElementsMap = createLookupTable('non_empty_elements', 'td th iframe video audio object script', shortEndedElementsMap);
12052
+ nonEmptyElementsMap = createLookupTable('non_empty_elements', 'td th iframe video audio object ' +
12053
+ 'script pre code', shortEndedElementsMap);
12036
12054
  moveCaretBeforeOnEnterElementsMap = createLookupTable('move_caret_before_on_enter_elements', 'table', nonEmptyElementsMap);
12037
12055
  textBlockElementsMap = createLookupTable('text_block_elements', 'h1 h2 h3 h4 h5 h6 p div address pre form ' +
12038
12056
  'blockquote center dir fieldset header footer article section hgroup aside nav figure');
@@ -13173,6 +13191,18 @@ define("tinymce/html/DomParser", [
13173
13191
  ], function(Node, Schema, SaxParser, Tools) {
13174
13192
  var makeMap = Tools.makeMap, each = Tools.each, explode = Tools.explode, extend = Tools.extend;
13175
13193
 
13194
+ var paddEmptyNode = function (settings, node) {
13195
+ if (settings.padd_empty_with_br) {
13196
+ node.empty().append(new Node('br', '1')).shortEnded = true;
13197
+ } else {
13198
+ node.empty().append(new Node('#text', '3')).value = '\u00a0';
13199
+ }
13200
+ };
13201
+
13202
+ var hasOnlyChild = function (node, name) {
13203
+ return node && node.firstChild === node.lastChild && node.firstChild.name === name;
13204
+ };
13205
+
13176
13206
  /**
13177
13207
  * Constructs a new DomParser instance.
13178
13208
  *
@@ -13191,10 +13221,11 @@ define("tinymce/html/DomParser", [
13191
13221
 
13192
13222
  function fixInvalidChildren(nodes) {
13193
13223
  var ni, node, parent, parents, newParent, currentNode, tempNode, childNode, i;
13194
- var nonEmptyElements, nonSplitableElements, textBlockElements, specialElements, sibling, nextNode;
13224
+ var nonEmptyElements, whitespaceElements, nonSplitableElements, textBlockElements, specialElements, sibling, nextNode;
13195
13225
 
13196
13226
  nonSplitableElements = makeMap('tr,td,th,tbody,thead,tfoot,table');
13197
13227
  nonEmptyElements = schema.getNonEmptyElements();
13228
+ whitespaceElements = schema.getWhiteSpaceElements();
13198
13229
  textBlockElements = schema.getTextBlockElements();
13199
13230
  specialElements = schema.getSpecialElements();
13200
13231
 
@@ -13261,7 +13292,7 @@ define("tinymce/html/DomParser", [
13261
13292
  currentNode = tempNode;
13262
13293
  }
13263
13294
 
13264
- if (!newParent.isEmpty(nonEmptyElements)) {
13295
+ if (!newParent.isEmpty(nonEmptyElements, whitespaceElements)) {
13265
13296
  parent.insert(newParent, parents[0], true);
13266
13297
  parent.insert(node, newParent);
13267
13298
  } else {
@@ -13270,7 +13301,7 @@ define("tinymce/html/DomParser", [
13270
13301
 
13271
13302
  // Check if the element is empty by looking through it's contents and special treatment for <p><br /></p>
13272
13303
  parent = parents[0];
13273
- if (parent.isEmpty(nonEmptyElements) || parent.firstChild === parent.lastChild && parent.firstChild.name === 'br') {
13304
+ if (parent.isEmpty(nonEmptyElements, whitespaceElements) || hasOnlyChild(parent, 'br')) {
13274
13305
  parent.empty().remove();
13275
13306
  }
13276
13307
  } else if (node.parent) {
@@ -13729,9 +13760,9 @@ define("tinymce/html/DomParser", [
13729
13760
 
13730
13761
  // Handle empty nodes
13731
13762
  if (elementRule.removeEmpty || elementRule.paddEmpty) {
13732
- if (node.isEmpty(nonEmptyElements)) {
13763
+ if (node.isEmpty(nonEmptyElements, whiteSpaceElements)) {
13733
13764
  if (elementRule.paddEmpty) {
13734
- node.empty().append(new Node('#text', '3')).value = '\u00a0';
13765
+ paddEmptyNode(settings, node);
13735
13766
  } else {
13736
13767
  // Leave nodes that have a name like <a name="name">
13737
13768
  if (!node.attributes.map.name && !node.attributes.map.id) {
@@ -13825,6 +13856,7 @@ define("tinymce/html/DomParser", [
13825
13856
  self.addNodeFilter('br', function(nodes) {
13826
13857
  var i, l = nodes.length, node, blockElements = extend({}, schema.getBlockElements());
13827
13858
  var nonEmptyElements = schema.getNonEmptyElements(), parent, lastParent, prev, prevName;
13859
+ var whiteSpaceElements = schema.getNonEmptyElements();
13828
13860
  var elementRule, textNode;
13829
13861
 
13830
13862
  // Remove brs from body element as well
@@ -13863,7 +13895,7 @@ define("tinymce/html/DomParser", [
13863
13895
  node.remove();
13864
13896
 
13865
13897
  // Is the parent to be considered empty after we removed the BR
13866
- if (parent.isEmpty(nonEmptyElements)) {
13898
+ if (parent.isEmpty(nonEmptyElements, whiteSpaceElements)) {
13867
13899
  elementRule = schema.getElementRule(parent.name);
13868
13900
 
13869
13901
  // Remove or padd the element depending on schema rule
@@ -13871,7 +13903,7 @@ define("tinymce/html/DomParser", [
13871
13903
  if (elementRule.removeEmpty) {
13872
13904
  parent.remove();
13873
13905
  } else if (elementRule.paddEmpty) {
13874
- parent.empty().append(new Node('#text', 3)).value = '\u00a0';
13906
+ paddEmptyNode(settings, parent);
13875
13907
  }
13876
13908
  }
13877
13909
  }
@@ -13890,7 +13922,7 @@ define("tinymce/html/DomParser", [
13890
13922
  parent = parent.parent;
13891
13923
  }
13892
13924
 
13893
- if (lastParent === parent) {
13925
+ if (lastParent === parent && settings.padd_empty_with_br !== true) {
13894
13926
  textNode = new Node('#text', 3);
13895
13927
  textNode.value = '\u00a0';
13896
13928
  node.replace(textNode);
@@ -13954,6 +13986,27 @@ define("tinymce/html/DomParser", [
13954
13986
  });
13955
13987
  }
13956
13988
 
13989
+ if (settings.fix_list_elements) {
13990
+ self.addNodeFilter('ul,ol', function(nodes) {
13991
+ var i = nodes.length, node, parentNode;
13992
+
13993
+ while (i--) {
13994
+ node = nodes[i];
13995
+ parentNode = node.parent;
13996
+
13997
+ if (parentNode.name === 'ul' || parentNode.name === 'ol') {
13998
+ if (node.prev && node.prev.name === 'li') {
13999
+ node.prev.append(node);
14000
+ } else {
14001
+ var li = new Node('li', 1);
14002
+ li.attr('style', 'list-style-type: none');
14003
+ node.wrap(li);
14004
+ }
14005
+ }
14006
+ }
14007
+ });
14008
+ }
14009
+
13957
14010
  if (settings.validate && schema.getValidClasses()) {
13958
14011
  self.addAttributeFilter('class', function(nodes) {
13959
14012
  var i = nodes.length, node, classList, ci, className, classValue;
@@ -14471,7 +14524,7 @@ define("tinymce/dom/Serializer", [
14471
14524
  bogusAllRegExp.lastIndex = index - matchLength;
14472
14525
  }
14473
14526
 
14474
- return trim(content);
14527
+ return content;
14475
14528
  }
14476
14529
 
14477
14530
  /**
@@ -14660,24 +14713,6 @@ define("tinymce/dom/Serializer", [
14660
14713
  }
14661
14714
  });
14662
14715
 
14663
- // Fix list elements, TODO: Replace this later
14664
- if (settings.fix_list_elements) {
14665
- htmlParser.addNodeFilter('ul,ol', function(nodes) {
14666
- var i = nodes.length, node, parentNode;
14667
-
14668
- while (i--) {
14669
- node = nodes[i];
14670
- parentNode = node.parent;
14671
-
14672
- if (parentNode.name === 'ul' || parentNode.name === 'ol') {
14673
- if (node.prev && node.prev.name === 'li') {
14674
- node.prev.append(node);
14675
- }
14676
- }
14677
- }
14678
- });
14679
- }
14680
-
14681
14716
  // Remove internal data attributes
14682
14717
  htmlParser.addAttributeFilter(
14683
14718
  'data-mce-src,data-mce-href,data-mce-style,' +
@@ -19176,10 +19211,11 @@ define("tinymce/Formatter", [
19176
19211
  "tinymce/dom/RangeUtils",
19177
19212
  "tinymce/dom/BookmarkManager",
19178
19213
  "tinymce/dom/ElementUtils",
19214
+ "tinymce/util/Fun",
19179
19215
  "tinymce/util/Tools",
19180
19216
  "tinymce/fmt/Preview",
19181
19217
  "tinymce/fmt/Hooks"
19182
- ], function(TreeWalker, RangeUtils, BookmarkManager, ElementUtils, Tools, Preview, Hooks) {
19218
+ ], function(TreeWalker, RangeUtils, BookmarkManager, ElementUtils, Fun, Tools, Preview, Hooks) {
19183
19219
  /**
19184
19220
  * Constructs a new formatter instance.
19185
19221
  *
@@ -19782,15 +19818,38 @@ define("tinymce/Formatter", [
19782
19818
  return count;
19783
19819
  }
19784
19820
 
19785
- function mergeStyles(node) {
19786
- var child, clone;
19787
-
19788
- each(node.childNodes, function(node) {
19789
- if (node.nodeType == 1 && !isBookmarkNode(node) && !isCaretNode(node)) {
19821
+ function getChildElementNode(root) {
19822
+ var child = false;
19823
+ each(root.childNodes, function(node) {
19824
+ if (isElementNode(node)) {
19790
19825
  child = node;
19791
- return FALSE; // break loop
19826
+ return false; // break loop
19792
19827
  }
19793
19828
  });
19829
+ return child;
19830
+ }
19831
+
19832
+ function matchNestedWrapper(node, filter) {
19833
+ do {
19834
+ if (getChildCount(node) !== 1) {
19835
+ break;
19836
+ }
19837
+
19838
+ node = getChildElementNode(node);
19839
+ if (!node) {
19840
+ break;
19841
+ } else if (filter(node)) {
19842
+ return node;
19843
+ }
19844
+ } while (node);
19845
+
19846
+ return null;
19847
+ }
19848
+
19849
+ function mergeStyles(node) {
19850
+ var child, clone;
19851
+
19852
+ child = getChildElementNode(node);
19794
19853
 
19795
19854
  // If child was found and of the same type as the current node
19796
19855
  if (child && !isBookmarkNode(child) && matchName(child, format)) {
@@ -19814,6 +19873,15 @@ define("tinymce/Formatter", [
19814
19873
  return;
19815
19874
  }
19816
19875
 
19876
+ // fontSize defines the line height for the whole branch of nested style wrappers,
19877
+ // therefore it should be set on the outermost wrapper
19878
+ if (!isBlock(node) && !getStyle(node, 'fontSize')) {
19879
+ var styleNode = matchNestedWrapper(node, hasStyle('fontSize'));
19880
+ if (styleNode) {
19881
+ apply('fontsize', {value: getStyle(styleNode, 'fontSize')}, node);
19882
+ }
19883
+ }
19884
+
19817
19885
  if (format.inline || format.wrapper) {
19818
19886
  // Merges the current node with it's children of similar type to reduce the number of elements
19819
19887
  if (!format.exact && childCount === 1) {
@@ -19834,19 +19902,20 @@ define("tinymce/Formatter", [
19834
19902
  });
19835
19903
  });
19836
19904
 
19837
- // Remove child if direct parent is of same type
19905
+ // Remove format if direct parent already has the same format
19838
19906
  if (matchNode(node.parentNode, name, vars)) {
19839
- dom.remove(node, 1);
19840
- node = 0;
19841
- return TRUE;
19907
+ if (removeFormat(format, vars, node)) {
19908
+ node = 0;
19909
+ }
19842
19910
  }
19843
19911
 
19844
- // Look for parent with similar style format
19912
+ // Remove format if any ancestor already has the same format
19845
19913
  if (format.merge_with_parents) {
19846
19914
  dom.getParent(node.parentNode, function(parent) {
19847
19915
  if (matchNode(parent, name, vars)) {
19848
- dom.remove(node, 1);
19849
- node = 0;
19916
+ if (removeFormat(format, vars, node)) {
19917
+ node = 0;
19918
+ }
19850
19919
  return TRUE;
19851
19920
  }
19852
19921
  });
@@ -19902,10 +19971,20 @@ define("tinymce/Formatter", [
19902
19971
  bookmark = selection.getBookmark();
19903
19972
  applyRngStyle(expandRng(selection.getRng(TRUE), formatList), bookmark);
19904
19973
 
19905
- // Colored nodes should be underlined so that the color of the underline matches the text color.
19906
- if (format.styles && (format.styles.color || format.styles.textDecoration)) {
19907
- walk(curSelNode, processUnderlineAndColor, 'childNodes');
19908
- processUnderlineAndColor(curSelNode);
19974
+ if (format.styles) {
19975
+ // Colored nodes should be underlined so that the color of the underline matches the text color.
19976
+ if (format.styles.color || format.styles.textDecoration) {
19977
+ walk(curSelNode, processUnderlineAndColor, 'childNodes');
19978
+ processUnderlineAndColor(curSelNode);
19979
+ }
19980
+
19981
+ // nodes with font-size should have their own background color as well to fit the line-height (see TINY-882)
19982
+ if (format.styles.backgroundColor) {
19983
+ processChildElements(curSelNode,
19984
+ hasStyle('fontSize'),
19985
+ applyStyle('backgroundColor', replaceVars(format.styles.backgroundColor, vars))
19986
+ );
19987
+ }
19909
19988
  }
19910
19989
 
19911
19990
  selection.moveToBookmark(bookmark);
@@ -20558,6 +20637,35 @@ define("tinymce/Formatter", [
20558
20637
  return str1.toLowerCase() == str2.toLowerCase();
20559
20638
  }
20560
20639
 
20640
+ function processChildElements(node, filter, process) {
20641
+ each(node.childNodes, function(node) {
20642
+ if (isElementNode(node)) {
20643
+ if (filter(node)) {
20644
+ process(node);
20645
+ }
20646
+ if (node.hasChildNodes()) {
20647
+ processChildElements(node, filter, process);
20648
+ }
20649
+ }
20650
+ });
20651
+ }
20652
+
20653
+ function isElementNode(node) {
20654
+ return node.nodeType == 1 && !isBookmarkNode(node) && !isWhiteSpaceNode(node) && !isCaretNode(node);
20655
+ }
20656
+
20657
+ function hasStyle(name) {
20658
+ return Fun.curry(function(name, node) {
20659
+ return !!(node && getStyle(node, name));
20660
+ }, name);
20661
+ }
20662
+
20663
+ function applyStyle(name, value) {
20664
+ return Fun.curry(function(name, value, node) {
20665
+ dom.setStyle(node, name, value);
20666
+ }, name, value);
20667
+ }
20668
+
20561
20669
  /**
20562
20670
  * Returns the style by name on the specified node. This method modifies the style
20563
20671
  * contents to make it more easy to match. This will resolve a few browser issues.
@@ -21945,14 +22053,15 @@ define("tinymce/undo/Levels", [
21945
22053
  };
21946
22054
 
21947
22055
  var createFromEditor = function (editor) {
21948
- var fragments, content;
22056
+ var fragments, content, trimmedFragments;
21949
22057
 
21950
22058
  fragments = Fragments.read(editor.getBody());
21951
- content = Arr.map(fragments, function (html) {
22059
+ trimmedFragments = Arr.map(fragments, function (html) {
21952
22060
  return editor.serializer.trimContent(html);
21953
- }).join('');
22061
+ });
22062
+ content = trimmedFragments.join('');
21954
22063
 
21955
- return hasIframes(content) ? createFragmentedLevel(fragments) : createCompleteLevel(content);
22064
+ return hasIframes(content) ? createFragmentedLevel(trimmedFragments) : createCompleteLevel(content);
21956
22065
  };
21957
22066
 
21958
22067
  var applyToEditor = function (editor, level, before) {
@@ -22002,9 +22111,8 @@ define("tinymce/undo/Levels", [
22002
22111
  define("tinymce/UndoManager", [
22003
22112
  "tinymce/util/VK",
22004
22113
  "tinymce/util/Tools",
22005
- "tinymce/undo/Levels",
22006
- "tinymce/Env"
22007
- ], function(VK, Tools, Levels, Env) {
22114
+ "tinymce/undo/Levels"
22115
+ ], function(VK, Tools, Levels) {
22008
22116
  return function(editor) {
22009
22117
  var self = this, index = 0, data = [], beforeBookmark, isFirstTypedCharacter, locks = 0;
22010
22118
 
@@ -22069,7 +22177,7 @@ define("tinymce/UndoManager", [
22069
22177
  editor.nodeChanged();
22070
22178
  }
22071
22179
 
22072
- if (keyCode === 46 || keyCode === 8 || (Env.mac && (keyCode === 91 || keyCode === 93))) {
22180
+ if (keyCode === 46 || keyCode === 8) {
22073
22181
  editor.nodeChanged();
22074
22182
  }
22075
22183
 
@@ -23963,6 +24071,23 @@ define("tinymce/InsertContent", [
23963
24071
  ], function(Env, Tools, Serializer, CaretWalker, CaretPosition, ElementUtils, NodeType, InsertList) {
23964
24072
  var isTableCell = NodeType.matchNodeNames('td th');
23965
24073
 
24074
+ var validInsertion = function (editor, value, parentNode) {
24075
+ // Should never insert content into bogus elements, since these can
24076
+ // be resize handles or similar
24077
+ if (parentNode.getAttribute('data-mce-bogus') === 'all') {
24078
+ parentNode.parentNode.insertBefore(editor.dom.createFragment(value), parentNode);
24079
+ } else {
24080
+ // Check if parent is empty or only has one BR element then set the innerHTML of that parent
24081
+ var node = parentNode.firstChild;
24082
+ var node2 = parentNode.lastChild;
24083
+ if (!node || (node === node2 && node.nodeName === 'BR')) {///
24084
+ editor.dom.setHTML(parentNode, value);
24085
+ } else {
24086
+ editor.selection.setContent(value);
24087
+ }
24088
+ }
24089
+ };
24090
+
23966
24091
  var insertHtmlAtCaret = function(editor, value, details) {
23967
24092
  var parser, serializer, parentNode, rootNode, fragment, args;
23968
24093
  var marker, rng, node, node2, bookmarkHtml, merge;
@@ -24227,15 +24352,7 @@ define("tinymce/InsertContent", [
24227
24352
  // If parser says valid we can insert the contents into that parent
24228
24353
  if (!parserArgs.invalid) {
24229
24354
  value = serializer.serialize(fragment);
24230
-
24231
- // Check if parent is empty or only has one BR element then set the innerHTML of that parent
24232
- node = parentNode.firstChild;
24233
- node2 = parentNode.lastChild;
24234
- if (!node || (node === node2 && node.nodeName === 'BR')) {
24235
- dom.setHTML(parentNode, value);
24236
- } else {
24237
- selection.setContent(value);
24238
- }
24355
+ validInsertion(editor, value, parentNode);
24239
24356
  } else {
24240
24357
  // If the fragment was invalid within that context then we need
24241
24358
  // to parse and process the parent it's inserted into
@@ -24340,8 +24457,9 @@ define("tinymce/EditorCommands", [
24340
24457
  "tinymce/util/Tools",
24341
24458
  "tinymce/dom/RangeUtils",
24342
24459
  "tinymce/dom/TreeWalker",
24343
- "tinymce/InsertContent"
24344
- ], function(Env, Tools, RangeUtils, TreeWalker, InsertContent) {
24460
+ "tinymce/InsertContent",
24461
+ "tinymce/dom/NodeType"
24462
+ ], function(Env, Tools, RangeUtils, TreeWalker, InsertContent, NodeType) {
24345
24463
  // Added for compression purposes
24346
24464
  var each = Tools.each, extend = Tools.extend;
24347
24465
  var map = Tools.map, inArray = Tools.inArray, explode = Tools.explode;
@@ -24866,10 +24984,12 @@ define("tinymce/EditorCommands", [
24866
24984
  var root = dom.getRoot(), rng;
24867
24985
 
24868
24986
  if (selection.getRng().setStart) {
24869
- rng = dom.createRng();
24870
- rng.setStart(root, 0);
24871
- rng.setEnd(root, root.childNodes.length);
24872
- selection.setRng(rng);
24987
+ var editingHost = dom.getParent(selection.getStart(), NodeType.isContentEditableTrue);
24988
+ if (editingHost) {
24989
+ rng = dom.createRng();
24990
+ rng.selectNodeContents(editingHost);
24991
+ selection.setRng(rng);
24992
+ }
24873
24993
  } else {
24874
24994
  // IE will render it's own root level block elements and sometimes
24875
24995
  // even put font elements in them when the user starts typing. So we need to
@@ -34450,6 +34570,9 @@ define("tinymce/util/Quirks", [
34450
34570
  * prevent empty paragraphs from being produced at beginning/end of contents.
34451
34571
  */
34452
34572
  function emptyEditorOnDeleteEverything() {
34573
+ var deepEqual = function (a, b) {
34574
+ return a.getNode() === b.getNode() || a.isEqual(b);
34575
+ };
34453
34576
  function isEverythingSelected(editor) {
34454
34577
  var caretWalker = new CaretWalker(editor.getBody());
34455
34578
  var rng = editor.selection.getRng();
@@ -34459,8 +34582,8 @@ define("tinymce/util/Quirks", [
34459
34582
  var next = caretWalker.next(endCaretPos);
34460
34583
 
34461
34584
  return !editor.selection.isCollapsed() &&
34462
- (!prev || prev.isAtStart()) &&
34463
- (!next || (next.isAtEnd() && startCaretPos.getNode() !== next.getNode()));
34585
+ (!prev || (prev.isAtStart() && deepEqual(startCaretPos, prev) === false)) &&
34586
+ (!next || (next.isAtEnd() && deepEqual(startCaretPos, next) === false));
34464
34587
  }
34465
34588
 
34466
34589
  // Type over case delete and insert this won't cover typeover with a IME but at least it covers the common case
@@ -36751,8 +36874,8 @@ define("tinymce/DragDropOverrides", [
36751
36874
  var isContentEditableFalse = NodeType.isContentEditableFalse,
36752
36875
  isContentEditableTrue = NodeType.isContentEditableTrue;
36753
36876
 
36754
- var isDraggable = function (elm) {
36755
- return isContentEditableFalse(elm);
36877
+ var isDraggable = function (rootElm, elm) {
36878
+ return isContentEditableFalse(elm) && elm !== rootElm;
36756
36879
  };
36757
36880
 
36758
36881
  var isValidDropTarget = function (editor, targetElement, dragElement) {
@@ -36857,7 +36980,7 @@ define("tinymce/DragDropOverrides", [
36857
36980
  if (isLeftMouseButtonPressed(e)) {
36858
36981
  var ceElm = Arr.find(editor.dom.getParents(e.target), Fun.or(isContentEditableFalse, isContentEditableTrue));
36859
36982
 
36860
- if (isDraggable(ceElm)) {
36983
+ if (isDraggable(editor.getBody(), ceElm)) {
36861
36984
  var elmPos = editor.dom.getPos(ceElm);
36862
36985
  var bodyElm = editor.getBody();
36863
36986
  var docElm = editor.getDoc().documentElement;
@@ -38986,7 +39109,7 @@ define("tinymce/Editor", [
38986
39109
  while (i--) {
38987
39110
  node = nodes[i];
38988
39111
 
38989
- if (node.isEmpty(nonEmptyElements)) {
39112
+ if (node.isEmpty(nonEmptyElements) && node.getAll('br').length === 0) {
38990
39113
  node.append(new Node('br', 1)).shortEnded = true;
38991
39114
  }
38992
39115
  }
@@ -39079,7 +39202,7 @@ define("tinymce/Editor", [
39079
39202
  // Remove empty contents
39080
39203
  if (settings.padd_empty_editor) {
39081
39204
  self.on('PostProcess', function(e) {
39082
- e.content = e.content.replace(/^(<p[^>]*>(&nbsp;|&#160;|\s|\u00a0|)<\/p>[\r\n]*|<br \/>[\r\n]*)$/, '');
39205
+ e.content = e.content.replace(/^(<p[^>]*>(&nbsp;|&#160;|\s|\u00a0|<br \/>|)<\/p>[\r\n]*|<br \/>[\r\n]*)$/, '');
39083
39206
  });
39084
39207
  }
39085
39208
 
@@ -39918,7 +40041,7 @@ define("tinymce/Editor", [
39918
40041
 
39919
40042
  // Get raw contents or by default the cleaned contents
39920
40043
  if (args.format == 'raw') {
39921
- content = self.serializer.getTrimmedContent();
40044
+ content = Tools.trim(self.serializer.getTrimmedContent());
39922
40045
  } else if (args.format == 'text') {
39923
40046
  content = body.innerText || body.textContent;
39924
40047
  } else {
@@ -40477,6 +40600,17 @@ define("tinymce/FocusManager", [
40477
40600
  ], function(DOMUtils, Delay, Env) {
40478
40601
  var selectionChangeHandler, documentFocusInHandler, documentMouseUpHandler, DOM = DOMUtils.DOM;
40479
40602
 
40603
+ var isUIElement = function (editor, elm) {
40604
+ var customSelector = editor ? editor.settings.custom_ui_selector : '';
40605
+ var parent = DOM.getParent(elm, function (elm) {
40606
+ return (
40607
+ FocusManager.isEditorUIElement(elm) ||
40608
+ (customSelector ? editor.dom.is(elm, customSelector) : false)
40609
+ );
40610
+ });
40611
+ return parent !== null;
40612
+ };
40613
+
40480
40614
  /**
40481
40615
  * Constructs a new focus manager instance.
40482
40616
  *
@@ -40528,10 +40662,6 @@ define("tinymce/FocusManager", [
40528
40662
  return rng;
40529
40663
  }
40530
40664
 
40531
- function isUIElement(elm) {
40532
- return !!DOM.getParent(elm, FocusManager.isEditorUIElement);
40533
- }
40534
-
40535
40665
  function registerEvents(e) {
40536
40666
  var editor = e.editor;
40537
40667
 
@@ -40630,7 +40760,7 @@ define("tinymce/FocusManager", [
40630
40760
  var focusedEditor = editorManager.focusedEditor;
40631
40761
 
40632
40762
  // Still the same editor the blur was outside any editor UI
40633
- if (!isUIElement(getActiveElement()) && focusedEditor == editor) {
40763
+ if (!isUIElement(editor, getActiveElement()) && focusedEditor == editor) {
40634
40764
  editor.fire('blur', {focusedEditor: null});
40635
40765
  editorManager.focusedEditor = null;
40636
40766
 
@@ -40658,7 +40788,7 @@ define("tinymce/FocusManager", [
40658
40788
  }
40659
40789
 
40660
40790
  // Fire a blur event if the element isn't a UI element
40661
- if (target != document.body && !isUIElement(target) && editorManager.focusedEditor == activeEditor) {
40791
+ if (target != document.body && !isUIElement(activeEditor, target) && editorManager.focusedEditor == activeEditor) {
40662
40792
  activeEditor.fire('blur', {focusedEditor: null});
40663
40793
  editorManager.focusedEditor = null;
40664
40794
  }
@@ -40717,6 +40847,8 @@ define("tinymce/FocusManager", [
40717
40847
  return elm.className.toString().indexOf('mce-') !== -1;
40718
40848
  };
40719
40849
 
40850
+ FocusManager._isUIElement = isUIElement;
40851
+
40720
40852
  return FocusManager;
40721
40853
  });
40722
40854
 
@@ -40843,7 +40975,7 @@ define("tinymce/EditorManager", [
40843
40975
  * @property minorVersion
40844
40976
  * @type String
40845
40977
  */
40846
- minorVersion: '5.2',
40978
+ minorVersion: '5.3',
40847
40979
 
40848
40980
  /**
40849
40981
  * Release date of TinyMCE build.
@@ -40851,7 +40983,7 @@ define("tinymce/EditorManager", [
40851
40983
  * @property releaseDate
40852
40984
  * @type String
40853
40985
  */
40854
- releaseDate: '2017-01-04',
40986
+ releaseDate: '2017-02-01',
40855
40987
 
40856
40988
  /**
40857
40989
  * Collection of editor instances.
@@ -45417,7 +45549,7 @@ define("tinymce/fmt/FontInfo", [
45417
45549
  elm = elm.parentNode;
45418
45550
  }
45419
45551
 
45420
- return 0;
45552
+ return '';
45421
45553
  };
45422
45554
 
45423
45555
  var toPt = function (fontSize) {
@@ -45439,12 +45571,14 @@ define("tinymce/fmt/FontInfo", [
45439
45571
 
45440
45572
  var getFontSize = function (rootElm, elm) {
45441
45573
  var specifiedFontSize = getSpecifiedFontProp('fontSize', rootElm, elm);
45442
- return specifiedFontSize ? specifiedFontSize : getComputedFontProp('fontSize', elm);
45574
+ return specifiedFontSize !== '' ? specifiedFontSize : getComputedFontProp('fontSize', elm);
45443
45575
  };
45444
45576
 
45445
45577
  var getFontFamily = function (rootElm, elm) {
45446
45578
  var specifiedFontSize = getSpecifiedFontProp('fontFamily', rootElm, elm);
45447
- return normalizeFontFamily(specifiedFontSize ? specifiedFontSize : getComputedFontProp('fontFamily', elm));
45579
+ var fontValue = specifiedFontSize !== '' ? specifiedFontSize : getComputedFontProp('fontFamily', elm);
45580
+
45581
+ return fontValue !== undefined ? normalizeFontFamily(fontValue) : '';
45448
45582
  };
45449
45583
 
45450
45584
  return {
@@ -45849,10 +45983,9 @@ define("tinymce/ui/FormatControls", [
45849
45983
  return function() {
45850
45984
  var self = this;
45851
45985
 
45852
- type = type == 'redo' ? 'hasRedo' : 'hasUndo';
45853
-
45854
45986
  function checkState() {
45855
- return editor.undoManager ? editor.undoManager[type]() : false;
45987
+ var typeFn = type == 'redo' ? 'hasRedo' : 'hasUndo';
45988
+ return editor.undoManager ? editor.undoManager[typeFn]() : false;
45856
45989
  }
45857
45990
 
45858
45991
  self.disabled(!checkState());
@@ -46932,10 +47065,10 @@ define("tinymce/ui/MenuButton", [
46932
47065
  *
46933
47066
  * @method showMenu
46934
47067
  */
46935
- showMenu: function() {
47068
+ showMenu: function(toggle) {
46936
47069
  var self = this, menu;
46937
47070
 
46938
- if (self.menu && self.menu.visible()) {
47071
+ if (self.menu && self.menu.visible() && toggle !== false) {
46939
47072
  return self.hideMenu();
46940
47073
  }
46941
47074
 
@@ -47071,7 +47204,8 @@ define("tinymce/ui/MenuButton", [
47071
47204
 
47072
47205
  self.on('click', function(e) {
47073
47206
  if (e.control === self && isChildOf(e.target, self.getEl())) {
47074
- self.showMenu();
47207
+ self.focus();
47208
+ self.showMenu(!e.aria);
47075
47209
 
47076
47210
  if (e.aria) {
47077
47211
  self.menu.items().filter(':visible')[0].focus();