tinymce-rails 4.0.10 → 4.0.11

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 (42) hide show
  1. data/app/assets/source/tinymce/tinymce.jquery.js +349 -139
  2. data/app/assets/source/tinymce/tinymce.js +349 -139
  3. data/lib/tinymce/rails/version.rb +2 -2
  4. data/vendor/assets/javascripts/tinymce/jquery.tinymce.js +1 -1
  5. data/vendor/assets/javascripts/tinymce/plugins/advlist/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/autosave/plugin.js +1 -1
  9. data/vendor/assets/javascripts/tinymce/plugins/charmap/plugin.js +1 -1
  10. data/vendor/assets/javascripts/tinymce/plugins/code/plugin.js +1 -1
  11. data/vendor/assets/javascripts/tinymce/plugins/contextmenu/plugin.js +1 -1
  12. data/vendor/assets/javascripts/tinymce/plugins/directionality/plugin.js +1 -1
  13. data/vendor/assets/javascripts/tinymce/plugins/example/plugin.js +1 -1
  14. data/vendor/assets/javascripts/tinymce/plugins/fullpage/plugin.js +1 -1
  15. data/vendor/assets/javascripts/tinymce/plugins/fullscreen/plugin.js +1 -1
  16. data/vendor/assets/javascripts/tinymce/plugins/hr/plugin.js +1 -1
  17. data/vendor/assets/javascripts/tinymce/plugins/image/plugin.js +1 -1
  18. data/vendor/assets/javascripts/tinymce/plugins/insertdatetime/plugin.js +1 -1
  19. data/vendor/assets/javascripts/tinymce/plugins/layer/plugin.js +1 -1
  20. data/vendor/assets/javascripts/tinymce/plugins/legacyoutput/plugin.js +1 -1
  21. data/vendor/assets/javascripts/tinymce/plugins/nonbreaking/plugin.js +1 -1
  22. data/vendor/assets/javascripts/tinymce/plugins/noneditable/plugin.js +1 -1
  23. data/vendor/assets/javascripts/tinymce/plugins/pagebreak/plugin.js +1 -1
  24. data/vendor/assets/javascripts/tinymce/plugins/paste/plugin.js +1 -1
  25. data/vendor/assets/javascripts/tinymce/plugins/preview/plugin.js +1 -1
  26. data/vendor/assets/javascripts/tinymce/plugins/print/plugin.js +1 -1
  27. data/vendor/assets/javascripts/tinymce/plugins/save/plugin.js +1 -1
  28. data/vendor/assets/javascripts/tinymce/plugins/searchreplace/plugin.js +1 -1
  29. data/vendor/assets/javascripts/tinymce/plugins/spellchecker/plugin.js +1 -1
  30. data/vendor/assets/javascripts/tinymce/plugins/tabfocus/plugin.js +1 -1
  31. data/vendor/assets/javascripts/tinymce/plugins/table/plugin.js +1 -1
  32. data/vendor/assets/javascripts/tinymce/plugins/template/plugin.js +1 -1
  33. data/vendor/assets/javascripts/tinymce/plugins/visualblocks/plugin.js +1 -1
  34. data/vendor/assets/javascripts/tinymce/plugins/visualchars/plugin.js +1 -1
  35. data/vendor/assets/javascripts/tinymce/skins/lightgray/content.inline.min.css +1 -1
  36. data/vendor/assets/javascripts/tinymce/skins/lightgray/content.min.css +1 -1
  37. data/vendor/assets/javascripts/tinymce/skins/lightgray/skin.ie7.min.css +1 -1
  38. data/vendor/assets/javascripts/tinymce/skins/lightgray/skin.min.css +1 -1
  39. data/vendor/assets/javascripts/tinymce/themes/modern/theme.js +1 -1
  40. data/vendor/assets/javascripts/tinymce/tinymce.jquery.js +9 -9
  41. data/vendor/assets/javascripts/tinymce/tinymce.js +10 -10
  42. metadata +3 -3
@@ -1,4 +1,4 @@
1
- // 4.0.10 (2013-10-28)
1
+ // 4.0.11 (2013-11-20)
2
2
 
3
3
  /**
4
4
  * Compiled inline version. (Library mode)
@@ -3375,38 +3375,42 @@ define("tinymce/html/Styles", [], function() {
3375
3375
  var styles = {}, matches, name, value, isEncoded, urlConverter = settings.url_converter;
3376
3376
  var urlConverterScope = settings.url_converter_scope || this;
3377
3377
 
3378
- function compress(prefix, suffix) {
3378
+ function compress(prefix, suffix, noJoin) {
3379
3379
  var top, right, bottom, left;
3380
3380
 
3381
- // IE 11 will produce a border-image: none when getting the style attribute from <p style="border: 1px solid red"></p>
3382
- // So lets asume it shouldn't be there
3383
- if (styles['border-image'] === 'none') {
3384
- delete styles['border-image'];
3385
- }
3386
-
3387
- // Get values and check it it needs compressing
3388
3381
  top = styles[prefix + '-top' + suffix];
3389
3382
  if (!top) {
3390
3383
  return;
3391
3384
  }
3392
3385
 
3393
3386
  right = styles[prefix + '-right' + suffix];
3394
- if (top != right) {
3387
+ if (!right) {
3395
3388
  return;
3396
3389
  }
3397
3390
 
3398
3391
  bottom = styles[prefix + '-bottom' + suffix];
3399
- if (right != bottom) {
3392
+ if (!bottom) {
3400
3393
  return;
3401
3394
  }
3402
3395
 
3403
3396
  left = styles[prefix + '-left' + suffix];
3404
- if (bottom != left) {
3397
+ if (!left) {
3405
3398
  return;
3406
3399
  }
3407
3400
 
3408
- // Compress
3409
- styles[prefix + suffix] = left;
3401
+ var box = [top, right, bottom, left];
3402
+ i = box.length - 1;
3403
+ while (i--) {
3404
+ if (box[i] !== box[i + 1]) {
3405
+ break;
3406
+ }
3407
+ }
3408
+
3409
+ if (i > -1 && noJoin) {
3410
+ return;
3411
+ }
3412
+
3413
+ styles[prefix + suffix] = i == -1 ? box[0] : box.join(' ');
3410
3414
  delete styles[prefix + '-top' + suffix];
3411
3415
  delete styles[prefix + '-right' + suffix];
3412
3416
  delete styles[prefix + '-bottom' + suffix];
@@ -3419,7 +3423,7 @@ define("tinymce/html/Styles", [], function() {
3419
3423
  function canCompress(key) {
3420
3424
  var value = styles[key], i;
3421
3425
 
3422
- if (!value || value.indexOf(' ') < 0) {
3426
+ if (!value) {
3423
3427
  return;
3424
3428
  }
3425
3429
 
@@ -3542,9 +3546,8 @@ define("tinymce/html/Styles", [], function() {
3542
3546
 
3543
3547
  styleRegExp.lastIndex = matches.index + matches[0].length;
3544
3548
  }
3545
-
3546
3549
  // Compress the styles to reduce it's size for example IE will expand styles
3547
- compress("border", "");
3550
+ compress("border", "", true);
3548
3551
  compress("border", "-width");
3549
3552
  compress("border", "-color");
3550
3553
  compress("border", "-style");
@@ -3556,6 +3559,12 @@ define("tinymce/html/Styles", [], function() {
3556
3559
  if (styles.border === 'medium none') {
3557
3560
  delete styles.border;
3558
3561
  }
3562
+
3563
+ // IE 11 will produce a border-image: none when getting the style attribute from <p style="border: 1px solid red"></p>
3564
+ // So lets asume it shouldn't be there
3565
+ if (styles['border-image'] === 'none') {
3566
+ delete styles['border-image'];
3567
+ }
3559
3568
  }
3560
3569
 
3561
3570
  return styles;
@@ -5256,7 +5265,7 @@ define("tinymce/html/Entities", [
5256
5265
  */
5257
5266
 
5258
5267
  /**
5259
- * This class contains various environment constrants like browser versions etc.
5268
+ * This class contains various environment constants like browser versions etc.
5260
5269
  * Normally you don't want to sniff specific browser versions but sometimes you have
5261
5270
  * to when it's impossible to feature detect. So use this with care.
5262
5271
  *
@@ -7777,9 +7786,14 @@ define("tinymce/AddOnManager", [
7777
7786
  *
7778
7787
  * @method requireLangPack
7779
7788
  * @param {String} name Short name of the add-on.
7789
+ * @param {String} languages Optional comma or space separated list of languages to check if it matches the name.
7780
7790
  */
7781
- requireLangPack: function(name) {
7791
+ requireLangPack: function(name, languages) {
7782
7792
  if (AddOnManager.language && AddOnManager.languageLoad !== false) {
7793
+ if (languages && new RegExp('([, ]|\\b)' + AddOnManager.language + '([, ]|\\b)').test(languages) === false) {
7794
+ return;
7795
+ }
7796
+
7783
7797
  ScriptLoader.ScriptLoader.add(this.urls[name] + '/langs/' + AddOnManager.language + '.js');
7784
7798
  }
7785
7799
  },
@@ -9499,7 +9513,8 @@ define("tinymce/html/SaxParser", [
9499
9513
  var validate, elementRule, isValidElement, attr, attribsValue, validAttributesMap, validAttributePatterns;
9500
9514
  var attributesRequired, attributesDefault, attributesForced;
9501
9515
  var anyAttributesRequired, selfClosing, tokenRegExp, attrRegExp, specialElements, attrValue, idCount = 0;
9502
- var decode = Entities.decode, fixSelfClosing, filteredAttrs = Tools.makeMap('src,href');
9516
+ var decode = Entities.decode, fixSelfClosing, filteredUrlAttrs = Tools.makeMap('src,href');
9517
+ var scriptUriRegExp = /(java|vb)script:/i;
9503
9518
 
9504
9519
  function processEndTag(name) {
9505
9520
  var pos, i;
@@ -9565,9 +9580,22 @@ define("tinymce/html/SaxParser", [
9565
9580
  }
9566
9581
  }
9567
9582
 
9568
- if (filteredAttrs[name] && !settings.allow_script_urls) {
9569
- if (/(java|vb)script:/i.test(decodeURIComponent(value.replace(trimRegExp, '')))) {
9570
- return;
9583
+ // Block any javascript: urls
9584
+ if (filteredUrlAttrs[name] && !settings.allow_script_urls) {
9585
+ var uri = value.replace(trimRegExp, '');
9586
+
9587
+ try {
9588
+ // Might throw malformed URI sequence
9589
+ uri = decodeURIComponent(uri);
9590
+ if (scriptUriRegExp.test(uri)) {
9591
+ return;
9592
+ }
9593
+ } catch (ex) {
9594
+ // Fallback to non UTF-8 decoder
9595
+ uri = unescape(uri);
9596
+ if (scriptUriRegExp.test(uri)) {
9597
+ return;
9598
+ }
9571
9599
  }
9572
9600
  }
9573
9601
 
@@ -11858,7 +11886,7 @@ define("tinymce/util/VK", [
11858
11886
 
11859
11887
  metaKeyPressed: function(e) {
11860
11888
  // Check if ctrl or meta key is pressed also check if alt is false for Polish users
11861
- return (Env.mac ? e.ctrlKey || e.metaKey : e.ctrlKey) && !e.altKey;
11889
+ return (Env.mac ? e.metaKey : e.ctrlKey) && !e.altKey;
11862
11890
  }
11863
11891
  };
11864
11892
  });
@@ -12403,17 +12431,24 @@ define("tinymce/dom/Selection", [
12403
12431
  Selection.prototype = {
12404
12432
  /**
12405
12433
  * Move the selection cursor range to the specified node and offset.
12434
+ * If there is no node specified it will move it to the first suitable location within the body.
12406
12435
  *
12407
12436
  * @method setCursorLocation
12408
- * @param {Node} node Node to put the cursor in.
12409
- * @param {Number} offset Offset from the start of the node to put the cursor at.
12437
+ * @param {Node} node Optional node to put the cursor in.
12438
+ * @param {Number} offset Optional offset from the start of the node to put the cursor at.
12410
12439
  */
12411
12440
  setCursorLocation: function(node, offset) {
12412
12441
  var self = this, rng = self.dom.createRng();
12413
- rng.setStart(node, offset);
12414
- rng.setEnd(node, offset);
12415
- self.setRng(rng);
12416
- self.collapse(false);
12442
+
12443
+ if (!node) {
12444
+ self._moveEndPoint(rng, self.editor.getBody(), true);
12445
+ self.setRng(rng);
12446
+ } else {
12447
+ rng.setStart(node, offset);
12448
+ rng.setEnd(node, offset);
12449
+ self.setRng(rng);
12450
+ self.collapse(false);
12451
+ }
12417
12452
  },
12418
12453
 
12419
12454
  /**
@@ -13023,54 +13058,11 @@ define("tinymce/dom/Selection", [
13023
13058
  * tinymce.activeEditor.selection.select(tinymce.activeEditor.dom.select('p')[0]);
13024
13059
  */
13025
13060
  select: function(node, content) {
13026
- var self = this, dom = self.dom, rng = dom.createRng(), idx, nonEmptyElementsMap;
13061
+ var self = this, dom = self.dom, rng = dom.createRng(), idx;
13027
13062
 
13028
13063
  // Clear stored range set by FocusManager
13029
13064
  self.lastFocusBookmark = null;
13030
13065
 
13031
- nonEmptyElementsMap = dom.schema.getNonEmptyElements();
13032
-
13033
- function setPoint(node, start) {
13034
- var root = node, walker = new TreeWalker(node, root);
13035
-
13036
- do {
13037
- // Text node
13038
- if (node.nodeType == 3 && trim(node.nodeValue).length !== 0) {
13039
- if (start) {
13040
- rng.setStart(node, 0);
13041
- } else {
13042
- rng.setEnd(node, node.nodeValue.length);
13043
- }
13044
-
13045
- return;
13046
- }
13047
-
13048
- // BR/IMG/INPUT elements
13049
- if (nonEmptyElementsMap[node.nodeName]) {
13050
- if (start) {
13051
- rng.setStartBefore(node);
13052
- } else {
13053
- if (node.nodeName == 'BR') {
13054
- rng.setEndBefore(node);
13055
- } else {
13056
- rng.setEndAfter(node);
13057
- }
13058
- }
13059
-
13060
- return;
13061
- }
13062
- } while ((node = (start ? walker.next() : walker.prev())));
13063
-
13064
- // Failed to find any text node or other suitable location then move to the root of body
13065
- if (root.nodeName == 'BODY') {
13066
- if (start) {
13067
- rng.setStart(root, 0);
13068
- } else {
13069
- rng.setEnd(root, root.childNodes.length);
13070
- }
13071
- }
13072
- }
13073
-
13074
13066
  if (node) {
13075
13067
  if (!content && self.controlSelection.controlSelect(node)) {
13076
13068
  return;
@@ -13082,8 +13074,8 @@ define("tinymce/dom/Selection", [
13082
13074
 
13083
13075
  // Find first/last text node or BR element
13084
13076
  if (content) {
13085
- setPoint(node, 1);
13086
- setPoint(node);
13077
+ self._moveEndPoint(rng, node, true);
13078
+ self._moveEndPoint(rng, node);
13087
13079
  }
13088
13080
 
13089
13081
  self.setRng(rng);
@@ -13734,6 +13726,59 @@ define("tinymce/dom/Selection", [
13734
13726
  }
13735
13727
  },
13736
13728
 
13729
+ _moveEndPoint: function(rng, node, start) {
13730
+ var root = node, walker = new TreeWalker(node, root);
13731
+ var nonEmptyElementsMap = this.dom.schema.getNonEmptyElements();
13732
+
13733
+ do {
13734
+ // Text node
13735
+ if (node.nodeType == 3 && trim(node.nodeValue).length !== 0) {
13736
+ if (start) {
13737
+ rng.setStart(node, 0);
13738
+ } else {
13739
+ rng.setEnd(node, node.nodeValue.length);
13740
+ }
13741
+
13742
+ return;
13743
+ }
13744
+
13745
+ // BR/IMG/INPUT elements
13746
+ if (nonEmptyElementsMap[node.nodeName]) {
13747
+ if (start) {
13748
+ rng.setStartBefore(node);
13749
+ } else {
13750
+ if (node.nodeName == 'BR') {
13751
+ rng.setEndBefore(node);
13752
+ } else {
13753
+ rng.setEndAfter(node);
13754
+ }
13755
+ }
13756
+
13757
+ return;
13758
+ }
13759
+
13760
+ // Found empty text block old IE can place the selection inside those
13761
+ if (Env.ie && Env.ie < 11 && this.dom.isBlock(node) && this.dom.isEmpty(node)) {
13762
+ if (start) {
13763
+ rng.setStart(node, 0);
13764
+ } else {
13765
+ rng.setEnd(node, 0);
13766
+ }
13767
+
13768
+ return;
13769
+ }
13770
+ } while ((node = (start ? walker.next() : walker.prev())));
13771
+
13772
+ // Failed to find any text node or other suitable location then move to the root of body
13773
+ if (root.nodeName == 'BODY') {
13774
+ if (start) {
13775
+ rng.setStart(root, 0);
13776
+ } else {
13777
+ rng.setEnd(root, root.childNodes.length);
13778
+ }
13779
+ }
13780
+ },
13781
+
13737
13782
  destroy: function() {
13738
13783
  this.win = null;
13739
13784
  this.controlSelection.destroy();
@@ -16877,6 +16922,15 @@ define("tinymce/EnterKey", [
16877
16922
  }
16878
16923
  }
16879
16924
 
16925
+ // Old IE versions doesn't properly render blocks with br elements in them
16926
+ // For example <p><br></p> wont be rendered correctly in a contentEditable area
16927
+ // until you remove the br producing <p></p>
16928
+ if (Env.ie && Env.ie < 9 && parentBlock && parentBlock.firstChild) {
16929
+ if (parentBlock.firstChild == parentBlock.lastChild && parentBlock.firstChild.tagName == 'BR') {
16930
+ dom.remove(parentBlock.firstChild);
16931
+ }
16932
+ }
16933
+
16880
16934
  if (root.nodeName == 'LI') {
16881
16935
  var firstChild = firstNonWhiteSpaceNodeSibling(root.firstChild);
16882
16936
 
@@ -17749,17 +17803,28 @@ define("tinymce/EditorCommands", [
17749
17803
 
17750
17804
  // Present alert message about clipboard access not being available
17751
17805
  if (failed || !doc.queryCommandSupported(command)) {
17752
- editor.windowManager.alert(
17806
+ var msg = editor.translate(
17753
17807
  "Your browser doesn't support direct access to the clipboard. " +
17754
17808
  "Please use the Ctrl+X/C/V keyboard shortcuts instead."
17755
17809
  );
17810
+
17811
+ if (Env.mac) {
17812
+ msg = msg.replace(/Ctrl\+/g, '\u2318+');
17813
+ }
17814
+
17815
+ editor.windowManager.alert(msg);
17756
17816
  }
17757
17817
  },
17758
17818
 
17759
17819
  // Override unlink command
17760
17820
  unlink: function(command) {
17761
17821
  if (selection.isCollapsed()) {
17762
- selection.select(selection.getNode());
17822
+ var elm = selection.getNode();
17823
+ if (elm.tagName == 'A') {
17824
+ editor.dom.remove(elm, true);
17825
+ }
17826
+
17827
+ return;
17763
17828
  }
17764
17829
 
17765
17830
  execNativeCommand(command);
@@ -17921,7 +17986,7 @@ define("tinymce/EditorCommands", [
17921
17986
  // Setup parser and serializer
17922
17987
  parser = editor.parser;
17923
17988
  serializer = new Serializer({}, editor.schema);
17924
- bookmarkHtml = '<span id="mce_marker" data-mce-type="bookmark">&#xFEFF;</span>';
17989
+ bookmarkHtml = '<span id="mce_marker" data-mce-type="bookmark">&#xFEFF;&#200B;</span>';
17925
17990
 
17926
17991
  // Run beforeSetContent handlers on the HTML to be inserted
17927
17992
  args = {content: value, format: 'html', selection: true};
@@ -17937,11 +18002,16 @@ define("tinymce/EditorCommands", [
17937
18002
  value = value.replace(/\{\$caret\}/, bookmarkHtml);
17938
18003
 
17939
18004
  // If selection is at <body>|<p></p> then move it into <body><p>|</p>
18005
+ rng = selection.getRng();
18006
+ var caretElement = rng.startContainer || (rng.parentElement ? rng.parentElement() : null);
17940
18007
  var body = editor.getBody();
17941
- if (dom.isBlock(body.firstChild) && dom.isEmpty(body.firstChild)) {
17942
- body.firstChild.appendChild(dom.doc.createTextNode('\u00a0'));
17943
- selection.select(body.firstChild, true);
17944
- dom.remove(body.firstChild.lastChild);
18008
+ if (caretElement === body && selection.isCollapsed()) {
18009
+ if (dom.isBlock(body.firstChild) && dom.isEmpty(body.firstChild)) {
18010
+ rng = dom.createRng();
18011
+ rng.setStart(body.firstChild, 0);
18012
+ rng.setEnd(body.firstChild, 0);
18013
+ selection.setRng(rng);
18014
+ }
17945
18015
  }
17946
18016
 
17947
18017
  // Insert node maker where we will insert the new HTML and get it's parent
@@ -18160,16 +18230,42 @@ define("tinymce/EditorCommands", [
18160
18230
  },
18161
18231
 
18162
18232
  selectAll: function() {
18163
- var root = dom.getRoot(), rng = dom.createRng();
18233
+ var root = dom.getRoot(), rng;
18164
18234
 
18165
- // Old IE does a better job with selectall than new versions
18166
18235
  if (selection.getRng().setStart) {
18236
+ rng = dom.createRng();
18167
18237
  rng.setStart(root, 0);
18168
18238
  rng.setEnd(root, root.childNodes.length);
18169
-
18170
18239
  selection.setRng(rng);
18171
18240
  } else {
18172
- execNativeCommand('SelectAll');
18241
+ // IE will render it's own root level block elements and sometimes
18242
+ // even put font elements in them when the user starts typing. So we need to
18243
+ // move the selection to a more suitable element from this:
18244
+ // <body>|<p></p></body> to this: <body><p>|</p></body>
18245
+ rng = selection.getRng();
18246
+ if (!rng.item) {
18247
+ rng.moveToElementText(root);
18248
+ rng.select();
18249
+ }
18250
+ }
18251
+ },
18252
+
18253
+ "delete": function() {
18254
+ execNativeCommand("Delete");
18255
+
18256
+ // Check if body is empty after the delete call if so then set the contents
18257
+ // to an empty string and move the caret to any block produced by that operation
18258
+ // this fixes the issue with root blocks not being properly produced after a delete call on IE
18259
+ var body = editor.getBody();
18260
+
18261
+ if (dom.isEmpty(body)) {
18262
+ editor.setContent('');
18263
+
18264
+ if (body.firstChild && dom.isBlock(body.firstChild)) {
18265
+ editor.selection.setCursorLocation(body.firstChild, 0);
18266
+ } else {
18267
+ editor.selection.setCursorLocation(body, 0);
18268
+ }
18173
18269
  }
18174
18270
  },
18175
18271
 
@@ -18304,15 +18400,21 @@ define("tinymce/util/URI", [
18304
18400
  return;
18305
18401
  }
18306
18402
 
18403
+ var isProtocolRelative = url.indexOf('//') === 0;
18404
+
18307
18405
  // Absolute path with no host, fake host and protocol
18308
- if (url.indexOf('/') === 0 && url.indexOf('//') !== 0) {
18406
+ if (url.indexOf('/') === 0 && !isProtocolRelative) {
18309
18407
  url = (settings.base_uri ? settings.base_uri.protocol || 'http' : 'http') + '://mce_host' + url;
18310
18408
  }
18311
18409
 
18312
18410
  // Relative path http:// or protocol relative //path
18313
18411
  if (!/^[\w\-]*:?\/\//.test(url)) {
18314
18412
  base_url = settings.base_uri ? settings.base_uri.path : new URI(location.href).directory;
18315
- url = ((settings.base_uri && settings.base_uri.protocol) || 'http') + '://mce_host' + self.toAbsPath(base_url, url);
18413
+ if (settings.base_uri.protocol === "") {
18414
+ url = '//mce_host' + self.toAbsPath(base_url, url);
18415
+ } else {
18416
+ url = ((settings.base_uri && settings.base_uri.protocol) || 'http') + '://mce_host' + self.toAbsPath(base_url, url);
18417
+ }
18316
18418
  }
18317
18419
 
18318
18420
  // Parse URL (Credits goes to Steave, http://blog.stevenlevithan.com/archives/parseuri)
@@ -18353,6 +18455,10 @@ define("tinymce/util/URI", [
18353
18455
  self.source = '';
18354
18456
  }
18355
18457
 
18458
+ if (isProtocolRelative) {
18459
+ self.protocol = '';
18460
+ }
18461
+
18356
18462
  //t.path = t.path || '/';
18357
18463
  }
18358
18464
 
@@ -18398,14 +18504,15 @@ define("tinymce/util/URI", [
18398
18504
  uri = new URI(uri, {base_uri: self});
18399
18505
 
18400
18506
  // Not on same domain/port or protocol
18401
- if ((uri.host != 'mce_host' && self.host != uri.host && uri.host) || self.port != uri.port || self.protocol != uri.protocol) {
18507
+ if ((uri.host != 'mce_host' && self.host != uri.host && uri.host) || self.port != uri.port ||
18508
+ (self.protocol != uri.protocol && uri.protocol !== "")) {
18402
18509
  return uri.getURI();
18403
18510
  }
18404
18511
 
18405
18512
  var tu = self.getURI(), uu = uri.getURI();
18406
18513
 
18407
18514
  // Allow usage of the base_uri when relative_urls = true
18408
- if(tu == uu || (tu.charAt(tu.length - 1) == "/" && tu.substr(0, tu.length - 1) == uu)) {
18515
+ if (tu == uu || (tu.charAt(tu.length - 1) == "/" && tu.substr(0, tu.length - 1) == uu)) {
18409
18516
  return tu;
18410
18517
  }
18411
18518
 
@@ -18577,6 +18684,8 @@ define("tinymce/util/URI", [
18577
18684
  if (!noProtoHost) {
18578
18685
  if (self.protocol) {
18579
18686
  s += self.protocol + '://';
18687
+ } else {
18688
+ s += '//';
18580
18689
  }
18581
18690
 
18582
18691
  if (self.userInfo) {
@@ -20124,7 +20233,12 @@ define("tinymce/ui/Control", [
20124
20233
  * @method repaint
20125
20234
  */
20126
20235
  repaint: function() {
20127
- var self = this, style, bodyStyle, rect, borderBox, borderW = 0, borderH = 0, lastRepaintRect;
20236
+ var self = this, style, bodyStyle, rect, borderBox, borderW = 0, borderH = 0, lastRepaintRect, round;
20237
+
20238
+ // Use Math.round on all values on IE < 9
20239
+ round = !document.createRange ? Math.round : function(value) {
20240
+ return value;
20241
+ };
20128
20242
 
20129
20243
  style = self.getEl().style;
20130
20244
  rect = self._layoutRect;
@@ -20135,35 +20249,35 @@ define("tinymce/ui/Control", [
20135
20249
  borderH = borderBox.top + borderBox.bottom;
20136
20250
 
20137
20251
  if (rect.x !== lastRepaintRect.x) {
20138
- style.left = rect.x + 'px';
20252
+ style.left = round(rect.x) + 'px';
20139
20253
  lastRepaintRect.x = rect.x;
20140
20254
  }
20141
20255
 
20142
20256
  if (rect.y !== lastRepaintRect.y) {
20143
- style.top = rect.y + 'px';
20257
+ style.top = round(rect.y) + 'px';
20144
20258
  lastRepaintRect.y = rect.y;
20145
20259
  }
20146
20260
 
20147
20261
  if (rect.w !== lastRepaintRect.w) {
20148
- style.width = (rect.w - borderW) + 'px';
20262
+ style.width = round(rect.w - borderW) + 'px';
20149
20263
  lastRepaintRect.w = rect.w;
20150
20264
  }
20151
20265
 
20152
20266
  if (rect.h !== lastRepaintRect.h) {
20153
- style.height = (rect.h - borderH) + 'px';
20267
+ style.height = round(rect.h - borderH) + 'px';
20154
20268
  lastRepaintRect.h = rect.h;
20155
20269
  }
20156
20270
 
20157
20271
  // Update body if needed
20158
20272
  if (self._hasBody && rect.innerW !== lastRepaintRect.innerW) {
20159
20273
  bodyStyle = self.getEl('body').style;
20160
- bodyStyle.width = (rect.innerW) + 'px';
20274
+ bodyStyle.width = round(rect.innerW) + 'px';
20161
20275
  lastRepaintRect.innerW = rect.innerW;
20162
20276
  }
20163
20277
 
20164
20278
  if (self._hasBody && rect.innerH !== lastRepaintRect.innerH) {
20165
20279
  bodyStyle = bodyStyle || self.getEl('body').style;
20166
- bodyStyle.height = (rect.innerH) + 'px';
20280
+ bodyStyle.height = round(rect.innerH) + 'px';
20167
20281
  lastRepaintRect.innerH = rect.innerH;
20168
20282
  }
20169
20283
 
@@ -23507,7 +23621,7 @@ define("tinymce/ui/Window", [
23507
23621
  * @return {tinymce.ui.Control} Current control instance.
23508
23622
  */
23509
23623
  remove: function() {
23510
- var self = this;
23624
+ var self = this, prefix = self.classPrefix;
23511
23625
 
23512
23626
  self.dragHelper.destroy();
23513
23627
  self._super();
@@ -23515,6 +23629,11 @@ define("tinymce/ui/Window", [
23515
23629
  if (self.statusbar) {
23516
23630
  this.statusbar.remove();
23517
23631
  }
23632
+
23633
+ if (self._fullscreen) {
23634
+ DomUtils.removeClass(document.documentElement, prefix + 'fullscreen');
23635
+ DomUtils.removeClass(document.body, prefix + 'fullscreen');
23636
+ }
23518
23637
  }
23519
23638
  });
23520
23639
 
@@ -24126,6 +24245,16 @@ define("tinymce/util/Quirks", [
24126
24245
  }
24127
24246
 
24128
24247
  function allContentsSelected(rng) {
24248
+ if (!rng.setStart) {
24249
+ if (rng.item) {
24250
+ return false;
24251
+ }
24252
+
24253
+ var bodyRng = rng.duplicate();
24254
+ bodyRng.moveToElementText(editor.getBody());
24255
+ return RangeUtils.compareRanges(rng, bodyRng);
24256
+ }
24257
+
24129
24258
  var selection = serializeRng(rng);
24130
24259
 
24131
24260
  var allRng = dom.createRng();
@@ -24136,19 +24265,15 @@ define("tinymce/util/Quirks", [
24136
24265
  }
24137
24266
 
24138
24267
  editor.on('keydown', function(e) {
24139
- var keyCode = e.keyCode, isCollapsed;
24268
+ var keyCode = e.keyCode, isCollapsed, body;
24140
24269
 
24141
24270
  // Empty the editor if it's needed for example backspace at <p><b>|</b></p>
24142
24271
  if (!isDefaultPrevented(e) && (keyCode == DELETE || keyCode == BACKSPACE)) {
24143
24272
  isCollapsed = editor.selection.isCollapsed();
24273
+ body = editor.getBody();
24144
24274
 
24145
24275
  // Selection is collapsed but the editor isn't empty
24146
- if (isCollapsed && !dom.isEmpty(editor.getBody())) {
24147
- return;
24148
- }
24149
-
24150
- // IE deletes all contents correctly when everything is selected
24151
- if (isIE && !isCollapsed) {
24276
+ if (isCollapsed && !dom.isEmpty(body)) {
24152
24277
  return;
24153
24278
  }
24154
24279
 
@@ -24160,7 +24285,13 @@ define("tinymce/util/Quirks", [
24160
24285
  // Manually empty the editor
24161
24286
  e.preventDefault();
24162
24287
  editor.setContent('');
24163
- editor.selection.setCursorLocation(editor.getBody(), 0);
24288
+
24289
+ if (body.firstChild && dom.isBlock(body.firstChild)) {
24290
+ editor.selection.setCursorLocation(body.firstChild, 0);
24291
+ } else {
24292
+ editor.selection.setCursorLocation(body, 0);
24293
+ }
24294
+
24164
24295
  editor.nodeChanged();
24165
24296
  }
24166
24297
  });
@@ -24168,6 +24299,7 @@ define("tinymce/util/Quirks", [
24168
24299
 
24169
24300
  /**
24170
24301
  * WebKit doesn't select all the nodes in the body when you press Ctrl+A.
24302
+ * IE selects more than the contents <body>[<p>a</p>]</body> instead of <body><p>[a]</p]</body> see bug #6438
24171
24303
  * This selects the whole body so that backspace/delete logic will delete everything
24172
24304
  */
24173
24305
  function selectAll() {
@@ -24896,6 +25028,21 @@ define("tinymce/util/Quirks", [
24896
25028
  }
24897
25029
  }
24898
25030
 
25031
+ /**
25032
+ * Firefox on Mac OS will move the browser back to the previous page if you press CMD+Left arrow.
25033
+ * You might then loose all your work so we need to block that behavior and replace it with our own.
25034
+ */
25035
+ function blockCmdArrowNavigation() {
25036
+ if (Env.mac) {
25037
+ editor.on('keydown', function(e) {
25038
+ if (VK.metaKeyPressed(e) && (e.keyCode == 37 || e.keyCode == 39)) {
25039
+ e.preventDefault();
25040
+ editor.selection.getSel().modify('move', e.keyCode == 37 ? 'backward' : 'forward', 'word');
25041
+ }
25042
+ });
25043
+ }
25044
+ }
25045
+
24899
25046
  // All browsers
24900
25047
  disableBackspaceIntoATable();
24901
25048
  removeBlockQuoteOnBackSpace();
@@ -24914,6 +25061,7 @@ define("tinymce/util/Quirks", [
24914
25061
  if (Env.iOS) {
24915
25062
  selectionChangeNodeChanged();
24916
25063
  restoreFocusOnKeyDown();
25064
+ bodyHeight();
24917
25065
  } else {
24918
25066
  selectAll();
24919
25067
  }
@@ -24935,6 +25083,10 @@ define("tinymce/util/Quirks", [
24935
25083
  bodyHeight();
24936
25084
  }
24937
25085
 
25086
+ if (Env.ie) {
25087
+ selectAll();
25088
+ }
25089
+
24938
25090
  // Gecko
24939
25091
  if (isGecko) {
24940
25092
  removeHrOnBackspace();
@@ -24944,6 +25096,7 @@ define("tinymce/util/Quirks", [
24944
25096
  addBrAfterLastLinks();
24945
25097
  removeGhostSelection();
24946
25098
  showBrokenImageIcon();
25099
+ blockCmdArrowNavigation();
24947
25100
  }
24948
25101
  };
24949
25102
  });
@@ -25225,7 +25378,7 @@ define("tinymce/Shortcuts", [
25225
25378
  editor.on('keyup keypress keydown', function(e) {
25226
25379
  if (e.altKey || e.ctrlKey || e.metaKey) {
25227
25380
  each(shortcuts, function(shortcut) {
25228
- var ctrlKey = Env.mac ? (e.ctrlKey || e.metaKey) : e.ctrlKey;
25381
+ var ctrlKey = Env.mac ? e.metaKey : e.ctrlKey;
25229
25382
 
25230
25383
  if (shortcut.ctrl != ctrlKey || shortcut.alt != e.altKey || shortcut.shift != e.shiftKey) {
25231
25384
  return;
@@ -25831,9 +25984,6 @@ define("tinymce/Editor", [
25831
25984
  // Create all plugins
25832
25985
  each(settings.plugins.replace(/\-/g, '').split(/[ ,]/), initPlugin);
25833
25986
 
25834
- // Enables users to override the control factory
25835
- self.fire('BeforeRenderUI');
25836
-
25837
25987
  // Measure box
25838
25988
  if (settings.render_ui && self.theme) {
25839
25989
  self.orgDisplay = elm.style.display;
@@ -26847,7 +26997,7 @@ define("tinymce/Editor", [
26847
26997
  var self = this, doc = self.getDoc();
26848
26998
 
26849
26999
  // Fixed bug where IE has a blinking cursor left from the editor
26850
- if (ie && doc) {
27000
+ if (ie && doc && !self.inline) {
26851
27001
  doc.execCommand('SelectAll');
26852
27002
  }
26853
27003
 
@@ -27018,6 +27168,7 @@ define("tinymce/Editor", [
27018
27168
 
27019
27169
  // Check if forcedRootBlock is configured and that the block is a valid child of the body
27020
27170
  if (forcedRootBlockName && self.schema.isValidChild(body.nodeName.toLowerCase(), forcedRootBlockName.toLowerCase())) {
27171
+ // Padd with bogus BR elements on modern browsers and IE 7 and 8 since they don't render empty P tags properly
27021
27172
  content = ie && ie < 11 ? '' : '<br data-mce-bogus="1">';
27022
27173
  content = self.dom.createHTML(forcedRootBlockName, self.settings.forced_root_block_attrs, content);
27023
27174
  } else if (!ie || ie < 11) {
@@ -27328,7 +27479,7 @@ define("tinymce/Editor", [
27328
27479
 
27329
27480
  // Fixed bug where IE has a blinking cursor left from the editor
27330
27481
  var doc = self.getDoc();
27331
- if (ie && doc) {
27482
+ if (ie && doc && !self.inline) {
27332
27483
  doc.execCommand('SelectAll');
27333
27484
  }
27334
27485
 
@@ -27644,6 +27795,18 @@ define("tinymce/FocusManager", [
27644
27795
  return !!DOMUtils.DOM.getParent(elm, FocusManager.isEditorUIElement);
27645
27796
  }
27646
27797
 
27798
+ function isNodeInBody(node) {
27799
+ var body = editor.getBody();
27800
+
27801
+ while (node) {
27802
+ if (node == body) {
27803
+ return true;
27804
+ }
27805
+
27806
+ node = node.parentNode;
27807
+ }
27808
+ }
27809
+
27647
27810
  editor.on('init', function() {
27648
27811
  // On IE take selection snapshot onbeforedeactivate
27649
27812
  if ("onbeforedeactivate" in document && Env.ie < 11) {
@@ -27659,24 +27822,14 @@ define("tinymce/FocusManager", [
27659
27822
  } else if (editor.inline || Env.ie > 10) {
27660
27823
  // On other browsers take snapshot on nodechange in inline mode since they have Ghost selections for iframes
27661
27824
  editor.on('nodechange keyup', function() {
27662
- var isInBody, node = document.activeElement;
27825
+ var node = document.activeElement;
27663
27826
 
27664
27827
  // IE 11 reports active element as iframe not body of iframe
27665
27828
  if (node && node.id == editor.id + '_ifr') {
27666
27829
  node = editor.getBody();
27667
27830
  }
27668
27831
 
27669
- // Check if selection is within editor body
27670
- while (node) {
27671
- if (node == editor.getBody()) {
27672
- isInBody = true;
27673
- break;
27674
- }
27675
-
27676
- node = node.parentNode;
27677
- }
27678
-
27679
- if (isInBody) {
27832
+ if (isNodeInBody(node)) {
27680
27833
  lastRng = editor.selection.getRng();
27681
27834
  }
27682
27835
  });
@@ -27736,7 +27889,14 @@ define("tinymce/FocusManager", [
27736
27889
  lastRng = null;
27737
27890
  });
27738
27891
 
27739
- editor.on('focusout', function() {
27892
+ editor.on('focusout', function(e) {
27893
+ // Moving focus to elements within the body that have a control seleciton on IE
27894
+ // will fire an focusout event so we need to check if the event is fired on the body
27895
+ // or on a sub element see #6456
27896
+ if (e.target !== editor.getBody() && isNodeInBody(e.target)) {
27897
+ return;
27898
+ }
27899
+
27740
27900
  editor.selection.lastFocusBookmark = createBookmark(lastRng);
27741
27901
 
27742
27902
  window.setTimeout(function() {
@@ -27825,7 +27985,7 @@ define("tinymce/EditorManager", [
27825
27985
  * @property minorVersion
27826
27986
  * @type String
27827
27987
  */
27828
- minorVersion : '0.10',
27988
+ minorVersion : '0.11',
27829
27989
 
27830
27990
  /**
27831
27991
  * Release date of TinyMCE build.
@@ -27833,7 +27993,7 @@ define("tinymce/EditorManager", [
27833
27993
  * @property releaseDate
27834
27994
  * @type String
27835
27995
  */
27836
- releaseDate: '2013-10-28',
27996
+ releaseDate: '2013-11-20',
27837
27997
 
27838
27998
  /**
27839
27999
  * Collection of editor instances.
@@ -27885,7 +28045,11 @@ define("tinymce/EditorManager", [
27885
28045
  for (var i = 0; i < scripts.length; i++) {
27886
28046
  var src = scripts[i].src;
27887
28047
 
27888
- if (/tinymce(\.jquery|)(\.min|\.dev|)\.js/.test(src)) {
28048
+ // Script types supported:
28049
+ // tinymce.js tinymce.min.js tinymce.dev.js
28050
+ // tinymce.jquery.js tinymce.jquery.min.js tinymce.jquery.dev.js
28051
+ // tinymce.full.js tinymce.full.min.js tinymce.full.dev.js
28052
+ if (/tinymce(\.full|\.jquery|)(\.min|\.dev|)\.js/.test(src)) {
27889
28053
  if (src.indexOf('.min') != -1) {
27890
28054
  suffix = '.min';
27891
28055
  }
@@ -29575,6 +29739,43 @@ define("tinymce/ui/Button", [
29575
29739
  }
29576
29740
  },
29577
29741
 
29742
+ /**
29743
+ * Sets/gets the current button icon.
29744
+ *
29745
+ * @method icon
29746
+ * @param {String} [icon] New icon identifier.
29747
+ * @return {String|tinymce.ui.MenuButton} Current icon or current MenuButton instance.
29748
+ */
29749
+ icon: function(icon) {
29750
+ var self = this, prefix = self.classPrefix;
29751
+
29752
+ if (typeof(icon) == 'undefined') {
29753
+ return self.settings.icon;
29754
+ }
29755
+
29756
+ self.settings.icon = icon;
29757
+ icon = icon ? prefix + 'ico ' + prefix + 'i-' + self.settings.icon : '';
29758
+
29759
+ if (self._rendered) {
29760
+ var btnElm = self.getEl().firstChild, iconElm = btnElm.getElementsByTagName('i')[0];
29761
+
29762
+ if (icon) {
29763
+ if (!iconElm || iconElm != btnElm.firstChild) {
29764
+ iconElm = document.createElement('i');
29765
+ btnElm.insertBefore(iconElm, btnElm.firstChild);
29766
+ }
29767
+
29768
+ iconElm.className = icon;
29769
+ } else if (iconElm) {
29770
+ btnElm.removeChild(iconElm);
29771
+ }
29772
+
29773
+ self.text(self._text); // Set text again to fix whitespace between icon + text
29774
+ }
29775
+
29776
+ return self;
29777
+ },
29778
+
29578
29779
  /**
29579
29780
  * Repaints the button for example after it's been resizes by a layout engine.
29580
29781
  *
@@ -31046,7 +31247,7 @@ define("tinymce/ui/FlexLayout", [
31046
31247
  ctrl = maxSizeItems[i];
31047
31248
  ctrlLayoutRect = ctrl.layoutRect();
31048
31249
  maxSize = ctrlLayoutRect[maxSizeName];
31049
- size = ctrlLayoutRect[minSizeName] + Math.ceil(ctrlLayoutRect.flex * ratio);
31250
+ size = ctrlLayoutRect[minSizeName] + ctrlLayoutRect.flex * ratio;
31050
31251
 
31051
31252
  if (size > maxSize) {
31052
31253
  availableSpace -= (ctrlLayoutRect[maxSizeName] - ctrlLayoutRect[minSizeName]);
@@ -31105,7 +31306,7 @@ define("tinymce/ui/FlexLayout", [
31105
31306
 
31106
31307
  // Calculate new size based on flex
31107
31308
  if (ctrlLayoutRect.flex > 0) {
31108
- size += Math.ceil(ctrlLayoutRect.flex * ratio);
31309
+ size += ctrlLayoutRect.flex * ratio;
31109
31310
  }
31110
31311
 
31111
31312
  rect[sizeName] = size;
@@ -31228,7 +31429,7 @@ define("tinymce/ui/FormatControls", [
31228
31429
 
31229
31430
  // Default preview
31230
31431
  if (!previewStyles) {
31231
- previewStyles = 'font-family font-size font-weight text-decoration ' +
31432
+ previewStyles = 'font-family font-size font-weight font-style text-decoration ' +
31232
31433
  'text-transform color background-color border border-radius';
31233
31434
  }
31234
31435
 
@@ -31982,7 +32183,7 @@ define("tinymce/ui/GridLayout", [
31982
32183
  // Calculate new column widths based on flex values
31983
32184
  var ratio = availableWidth / totalFlex;
31984
32185
  for (x = 0; x < cols; x++) {
31985
- colWidths[x] += flexWidths ? Math.ceil(flexWidths[x] * ratio) : ratio;
32186
+ colWidths[x] += flexWidths ? flexWidths[x] * ratio : ratio;
31986
32187
  }
31987
32188
 
31988
32189
  // Move/resize controls
@@ -32571,7 +32772,7 @@ define("tinymce/ui/MenuButton", [
32571
32772
  if (self._rendered) {
32572
32773
  children = self.getEl('open').getElementsByTagName('span');
32573
32774
  for (i = 0; i < children.length; i++) {
32574
- children[i].innerHTML = self.encode(text);
32775
+ children[i].innerHTML = (self.settings.icon && text ? '\u00a0' : '') + self.encode(text);
32575
32776
  }
32576
32777
  }
32577
32778
 
@@ -32737,8 +32938,9 @@ define("tinymce/ui/ListBox", [
32737
32938
  */
32738
32939
  define("tinymce/ui/MenuItem", [
32739
32940
  "tinymce/ui/Widget",
32740
- "tinymce/ui/Factory"
32741
- ], function(Widget, Factory) {
32941
+ "tinymce/ui/Factory",
32942
+ "tinymce/Env"
32943
+ ], function(Widget, Factory, Env) {
32742
32944
  "use strict";
32743
32945
 
32744
32946
  return Widget.extend({
@@ -32932,7 +33134,7 @@ define("tinymce/ui/MenuItem", [
32932
33134
  */
32933
33135
  renderHtml: function() {
32934
33136
  var self = this, id = self._id, settings = self.settings, prefix = self.classPrefix, text = self.encode(self._text);
32935
- var icon = self.settings.icon, image = '';
33137
+ var icon = self.settings.icon, image = '', shortcut = settings.shortcut;
32936
33138
 
32937
33139
  if (icon) {
32938
33140
  self.parent().addClass('menu-has-icons');
@@ -32943,14 +33145,22 @@ define("tinymce/ui/MenuItem", [
32943
33145
  image = ' style="background-image: url(\'' + settings.image + '\')"';
32944
33146
  }
32945
33147
 
33148
+ if (shortcut && Env.mac) {
33149
+ // format shortcut for Mac
33150
+ shortcut = shortcut.replace(/ctrl\+alt\+/i, '&#x2325;&#x2318;'); // ctrl+cmd
33151
+ shortcut = shortcut.replace(/ctrl\+/i, '&#x2318;'); // ctrl symbol
33152
+ shortcut = shortcut.replace(/alt\+/i, '&#x2325;'); // cmd symbol
33153
+ shortcut = shortcut.replace(/shift\+/i, '&#x21E7;'); // shift symbol
33154
+ }
33155
+
32946
33156
  icon = prefix + 'ico ' + prefix + 'i-' + (self.settings.icon || 'none');
32947
33157
 
32948
33158
  return (
32949
33159
  '<div id="' + id + '" class="' + self.classes() + '" tabindex="-1">' +
32950
33160
  (text !== '-' ? '<i class="' + icon + '"' + image + '></i>&nbsp;' : '') +
32951
33161
  (text !== '-' ? '<span id="' + id + '-text" class="' + prefix + 'text">' + text + '</span>' : '') +
32952
- (settings.shortcut ? '<div id="' + id + '-shortcut" class="' + prefix + 'menu-shortcut">' +
32953
- settings.shortcut + '</div>' : '') +
33162
+ (shortcut ? '<div id="' + id + '-shortcut" class="' + prefix + 'menu-shortcut">' +
33163
+ shortcut + '</div>' : '') +
32954
33164
  (settings.menu ? '<div class="' + prefix + 'caret"></div>' : '') +
32955
33165
  '</div>'
32956
33166
  );