tinymce-rails 4.5.2 → 4.5.3

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.
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();