tinymce-rails 4.0.10 → 4.0.11

Sign up to get free protection for your applications and to get access to all the features.
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)
@@ -190,38 +190,42 @@ define("tinymce/html/Styles", [], function() {
190
190
  var styles = {}, matches, name, value, isEncoded, urlConverter = settings.url_converter;
191
191
  var urlConverterScope = settings.url_converter_scope || this;
192
192
 
193
- function compress(prefix, suffix) {
193
+ function compress(prefix, suffix, noJoin) {
194
194
  var top, right, bottom, left;
195
195
 
196
- // IE 11 will produce a border-image: none when getting the style attribute from <p style="border: 1px solid red"></p>
197
- // So lets asume it shouldn't be there
198
- if (styles['border-image'] === 'none') {
199
- delete styles['border-image'];
200
- }
201
-
202
- // Get values and check it it needs compressing
203
196
  top = styles[prefix + '-top' + suffix];
204
197
  if (!top) {
205
198
  return;
206
199
  }
207
200
 
208
201
  right = styles[prefix + '-right' + suffix];
209
- if (top != right) {
202
+ if (!right) {
210
203
  return;
211
204
  }
212
205
 
213
206
  bottom = styles[prefix + '-bottom' + suffix];
214
- if (right != bottom) {
207
+ if (!bottom) {
215
208
  return;
216
209
  }
217
210
 
218
211
  left = styles[prefix + '-left' + suffix];
219
- if (bottom != left) {
212
+ if (!left) {
220
213
  return;
221
214
  }
222
215
 
223
- // Compress
224
- styles[prefix + suffix] = left;
216
+ var box = [top, right, bottom, left];
217
+ i = box.length - 1;
218
+ while (i--) {
219
+ if (box[i] !== box[i + 1]) {
220
+ break;
221
+ }
222
+ }
223
+
224
+ if (i > -1 && noJoin) {
225
+ return;
226
+ }
227
+
228
+ styles[prefix + suffix] = i == -1 ? box[0] : box.join(' ');
225
229
  delete styles[prefix + '-top' + suffix];
226
230
  delete styles[prefix + '-right' + suffix];
227
231
  delete styles[prefix + '-bottom' + suffix];
@@ -234,7 +238,7 @@ define("tinymce/html/Styles", [], function() {
234
238
  function canCompress(key) {
235
239
  var value = styles[key], i;
236
240
 
237
- if (!value || value.indexOf(' ') < 0) {
241
+ if (!value) {
238
242
  return;
239
243
  }
240
244
 
@@ -357,9 +361,8 @@ define("tinymce/html/Styles", [], function() {
357
361
 
358
362
  styleRegExp.lastIndex = matches.index + matches[0].length;
359
363
  }
360
-
361
364
  // Compress the styles to reduce it's size for example IE will expand styles
362
- compress("border", "");
365
+ compress("border", "", true);
363
366
  compress("border", "-width");
364
367
  compress("border", "-color");
365
368
  compress("border", "-style");
@@ -371,6 +374,12 @@ define("tinymce/html/Styles", [], function() {
371
374
  if (styles.border === 'medium none') {
372
375
  delete styles.border;
373
376
  }
377
+
378
+ // IE 11 will produce a border-image: none when getting the style attribute from <p style="border: 1px solid red"></p>
379
+ // So lets asume it shouldn't be there
380
+ if (styles['border-image'] === 'none') {
381
+ delete styles['border-image'];
382
+ }
374
383
  }
375
384
 
376
385
  return styles;
@@ -2625,7 +2634,7 @@ define("tinymce/html/Entities", [
2625
2634
  */
2626
2635
 
2627
2636
  /**
2628
- * This class contains various environment constrants like browser versions etc.
2637
+ * This class contains various environment constants like browser versions etc.
2629
2638
  * Normally you don't want to sniff specific browser versions but sometimes you have
2630
2639
  * to when it's impossible to feature detect. So use this with care.
2631
2640
  *
@@ -5146,9 +5155,14 @@ define("tinymce/AddOnManager", [
5146
5155
  *
5147
5156
  * @method requireLangPack
5148
5157
  * @param {String} name Short name of the add-on.
5158
+ * @param {String} languages Optional comma or space separated list of languages to check if it matches the name.
5149
5159
  */
5150
- requireLangPack: function(name) {
5160
+ requireLangPack: function(name, languages) {
5151
5161
  if (AddOnManager.language && AddOnManager.languageLoad !== false) {
5162
+ if (languages && new RegExp('([, ]|\\b)' + AddOnManager.language + '([, ]|\\b)').test(languages) === false) {
5163
+ return;
5164
+ }
5165
+
5152
5166
  ScriptLoader.ScriptLoader.add(this.urls[name] + '/langs/' + AddOnManager.language + '.js');
5153
5167
  }
5154
5168
  },
@@ -6868,7 +6882,8 @@ define("tinymce/html/SaxParser", [
6868
6882
  var validate, elementRule, isValidElement, attr, attribsValue, validAttributesMap, validAttributePatterns;
6869
6883
  var attributesRequired, attributesDefault, attributesForced;
6870
6884
  var anyAttributesRequired, selfClosing, tokenRegExp, attrRegExp, specialElements, attrValue, idCount = 0;
6871
- var decode = Entities.decode, fixSelfClosing, filteredAttrs = Tools.makeMap('src,href');
6885
+ var decode = Entities.decode, fixSelfClosing, filteredUrlAttrs = Tools.makeMap('src,href');
6886
+ var scriptUriRegExp = /(java|vb)script:/i;
6872
6887
 
6873
6888
  function processEndTag(name) {
6874
6889
  var pos, i;
@@ -6934,9 +6949,22 @@ define("tinymce/html/SaxParser", [
6934
6949
  }
6935
6950
  }
6936
6951
 
6937
- if (filteredAttrs[name] && !settings.allow_script_urls) {
6938
- if (/(java|vb)script:/i.test(decodeURIComponent(value.replace(trimRegExp, '')))) {
6939
- return;
6952
+ // Block any javascript: urls
6953
+ if (filteredUrlAttrs[name] && !settings.allow_script_urls) {
6954
+ var uri = value.replace(trimRegExp, '');
6955
+
6956
+ try {
6957
+ // Might throw malformed URI sequence
6958
+ uri = decodeURIComponent(uri);
6959
+ if (scriptUriRegExp.test(uri)) {
6960
+ return;
6961
+ }
6962
+ } catch (ex) {
6963
+ // Fallback to non UTF-8 decoder
6964
+ uri = unescape(uri);
6965
+ if (scriptUriRegExp.test(uri)) {
6966
+ return;
6967
+ }
6940
6968
  }
6941
6969
  }
6942
6970
 
@@ -9227,7 +9255,7 @@ define("tinymce/util/VK", [
9227
9255
 
9228
9256
  metaKeyPressed: function(e) {
9229
9257
  // Check if ctrl or meta key is pressed also check if alt is false for Polish users
9230
- return (Env.mac ? e.ctrlKey || e.metaKey : e.ctrlKey) && !e.altKey;
9258
+ return (Env.mac ? e.metaKey : e.ctrlKey) && !e.altKey;
9231
9259
  }
9232
9260
  };
9233
9261
  });
@@ -9772,17 +9800,24 @@ define("tinymce/dom/Selection", [
9772
9800
  Selection.prototype = {
9773
9801
  /**
9774
9802
  * Move the selection cursor range to the specified node and offset.
9803
+ * If there is no node specified it will move it to the first suitable location within the body.
9775
9804
  *
9776
9805
  * @method setCursorLocation
9777
- * @param {Node} node Node to put the cursor in.
9778
- * @param {Number} offset Offset from the start of the node to put the cursor at.
9806
+ * @param {Node} node Optional node to put the cursor in.
9807
+ * @param {Number} offset Optional offset from the start of the node to put the cursor at.
9779
9808
  */
9780
9809
  setCursorLocation: function(node, offset) {
9781
9810
  var self = this, rng = self.dom.createRng();
9782
- rng.setStart(node, offset);
9783
- rng.setEnd(node, offset);
9784
- self.setRng(rng);
9785
- self.collapse(false);
9811
+
9812
+ if (!node) {
9813
+ self._moveEndPoint(rng, self.editor.getBody(), true);
9814
+ self.setRng(rng);
9815
+ } else {
9816
+ rng.setStart(node, offset);
9817
+ rng.setEnd(node, offset);
9818
+ self.setRng(rng);
9819
+ self.collapse(false);
9820
+ }
9786
9821
  },
9787
9822
 
9788
9823
  /**
@@ -10392,54 +10427,11 @@ define("tinymce/dom/Selection", [
10392
10427
  * tinymce.activeEditor.selection.select(tinymce.activeEditor.dom.select('p')[0]);
10393
10428
  */
10394
10429
  select: function(node, content) {
10395
- var self = this, dom = self.dom, rng = dom.createRng(), idx, nonEmptyElementsMap;
10430
+ var self = this, dom = self.dom, rng = dom.createRng(), idx;
10396
10431
 
10397
10432
  // Clear stored range set by FocusManager
10398
10433
  self.lastFocusBookmark = null;
10399
10434
 
10400
- nonEmptyElementsMap = dom.schema.getNonEmptyElements();
10401
-
10402
- function setPoint(node, start) {
10403
- var root = node, walker = new TreeWalker(node, root);
10404
-
10405
- do {
10406
- // Text node
10407
- if (node.nodeType == 3 && trim(node.nodeValue).length !== 0) {
10408
- if (start) {
10409
- rng.setStart(node, 0);
10410
- } else {
10411
- rng.setEnd(node, node.nodeValue.length);
10412
- }
10413
-
10414
- return;
10415
- }
10416
-
10417
- // BR/IMG/INPUT elements
10418
- if (nonEmptyElementsMap[node.nodeName]) {
10419
- if (start) {
10420
- rng.setStartBefore(node);
10421
- } else {
10422
- if (node.nodeName == 'BR') {
10423
- rng.setEndBefore(node);
10424
- } else {
10425
- rng.setEndAfter(node);
10426
- }
10427
- }
10428
-
10429
- return;
10430
- }
10431
- } while ((node = (start ? walker.next() : walker.prev())));
10432
-
10433
- // Failed to find any text node or other suitable location then move to the root of body
10434
- if (root.nodeName == 'BODY') {
10435
- if (start) {
10436
- rng.setStart(root, 0);
10437
- } else {
10438
- rng.setEnd(root, root.childNodes.length);
10439
- }
10440
- }
10441
- }
10442
-
10443
10435
  if (node) {
10444
10436
  if (!content && self.controlSelection.controlSelect(node)) {
10445
10437
  return;
@@ -10451,8 +10443,8 @@ define("tinymce/dom/Selection", [
10451
10443
 
10452
10444
  // Find first/last text node or BR element
10453
10445
  if (content) {
10454
- setPoint(node, 1);
10455
- setPoint(node);
10446
+ self._moveEndPoint(rng, node, true);
10447
+ self._moveEndPoint(rng, node);
10456
10448
  }
10457
10449
 
10458
10450
  self.setRng(rng);
@@ -11103,6 +11095,59 @@ define("tinymce/dom/Selection", [
11103
11095
  }
11104
11096
  },
11105
11097
 
11098
+ _moveEndPoint: function(rng, node, start) {
11099
+ var root = node, walker = new TreeWalker(node, root);
11100
+ var nonEmptyElementsMap = this.dom.schema.getNonEmptyElements();
11101
+
11102
+ do {
11103
+ // Text node
11104
+ if (node.nodeType == 3 && trim(node.nodeValue).length !== 0) {
11105
+ if (start) {
11106
+ rng.setStart(node, 0);
11107
+ } else {
11108
+ rng.setEnd(node, node.nodeValue.length);
11109
+ }
11110
+
11111
+ return;
11112
+ }
11113
+
11114
+ // BR/IMG/INPUT elements
11115
+ if (nonEmptyElementsMap[node.nodeName]) {
11116
+ if (start) {
11117
+ rng.setStartBefore(node);
11118
+ } else {
11119
+ if (node.nodeName == 'BR') {
11120
+ rng.setEndBefore(node);
11121
+ } else {
11122
+ rng.setEndAfter(node);
11123
+ }
11124
+ }
11125
+
11126
+ return;
11127
+ }
11128
+
11129
+ // Found empty text block old IE can place the selection inside those
11130
+ if (Env.ie && Env.ie < 11 && this.dom.isBlock(node) && this.dom.isEmpty(node)) {
11131
+ if (start) {
11132
+ rng.setStart(node, 0);
11133
+ } else {
11134
+ rng.setEnd(node, 0);
11135
+ }
11136
+
11137
+ return;
11138
+ }
11139
+ } while ((node = (start ? walker.next() : walker.prev())));
11140
+
11141
+ // Failed to find any text node or other suitable location then move to the root of body
11142
+ if (root.nodeName == 'BODY') {
11143
+ if (start) {
11144
+ rng.setStart(root, 0);
11145
+ } else {
11146
+ rng.setEnd(root, root.childNodes.length);
11147
+ }
11148
+ }
11149
+ },
11150
+
11106
11151
  destroy: function() {
11107
11152
  this.win = null;
11108
11153
  this.controlSelection.destroy();
@@ -14246,6 +14291,15 @@ define("tinymce/EnterKey", [
14246
14291
  }
14247
14292
  }
14248
14293
 
14294
+ // Old IE versions doesn't properly render blocks with br elements in them
14295
+ // For example <p><br></p> wont be rendered correctly in a contentEditable area
14296
+ // until you remove the br producing <p></p>
14297
+ if (Env.ie && Env.ie < 9 && parentBlock && parentBlock.firstChild) {
14298
+ if (parentBlock.firstChild == parentBlock.lastChild && parentBlock.firstChild.tagName == 'BR') {
14299
+ dom.remove(parentBlock.firstChild);
14300
+ }
14301
+ }
14302
+
14249
14303
  if (root.nodeName == 'LI') {
14250
14304
  var firstChild = firstNonWhiteSpaceNodeSibling(root.firstChild);
14251
14305
 
@@ -15118,17 +15172,28 @@ define("tinymce/EditorCommands", [
15118
15172
 
15119
15173
  // Present alert message about clipboard access not being available
15120
15174
  if (failed || !doc.queryCommandSupported(command)) {
15121
- editor.windowManager.alert(
15175
+ var msg = editor.translate(
15122
15176
  "Your browser doesn't support direct access to the clipboard. " +
15123
15177
  "Please use the Ctrl+X/C/V keyboard shortcuts instead."
15124
15178
  );
15179
+
15180
+ if (Env.mac) {
15181
+ msg = msg.replace(/Ctrl\+/g, '\u2318+');
15182
+ }
15183
+
15184
+ editor.windowManager.alert(msg);
15125
15185
  }
15126
15186
  },
15127
15187
 
15128
15188
  // Override unlink command
15129
15189
  unlink: function(command) {
15130
15190
  if (selection.isCollapsed()) {
15131
- selection.select(selection.getNode());
15191
+ var elm = selection.getNode();
15192
+ if (elm.tagName == 'A') {
15193
+ editor.dom.remove(elm, true);
15194
+ }
15195
+
15196
+ return;
15132
15197
  }
15133
15198
 
15134
15199
  execNativeCommand(command);
@@ -15290,7 +15355,7 @@ define("tinymce/EditorCommands", [
15290
15355
  // Setup parser and serializer
15291
15356
  parser = editor.parser;
15292
15357
  serializer = new Serializer({}, editor.schema);
15293
- bookmarkHtml = '<span id="mce_marker" data-mce-type="bookmark">&#xFEFF;</span>';
15358
+ bookmarkHtml = '<span id="mce_marker" data-mce-type="bookmark">&#xFEFF;&#200B;</span>';
15294
15359
 
15295
15360
  // Run beforeSetContent handlers on the HTML to be inserted
15296
15361
  args = {content: value, format: 'html', selection: true};
@@ -15306,11 +15371,16 @@ define("tinymce/EditorCommands", [
15306
15371
  value = value.replace(/\{\$caret\}/, bookmarkHtml);
15307
15372
 
15308
15373
  // If selection is at <body>|<p></p> then move it into <body><p>|</p>
15374
+ rng = selection.getRng();
15375
+ var caretElement = rng.startContainer || (rng.parentElement ? rng.parentElement() : null);
15309
15376
  var body = editor.getBody();
15310
- if (dom.isBlock(body.firstChild) && dom.isEmpty(body.firstChild)) {
15311
- body.firstChild.appendChild(dom.doc.createTextNode('\u00a0'));
15312
- selection.select(body.firstChild, true);
15313
- dom.remove(body.firstChild.lastChild);
15377
+ if (caretElement === body && selection.isCollapsed()) {
15378
+ if (dom.isBlock(body.firstChild) && dom.isEmpty(body.firstChild)) {
15379
+ rng = dom.createRng();
15380
+ rng.setStart(body.firstChild, 0);
15381
+ rng.setEnd(body.firstChild, 0);
15382
+ selection.setRng(rng);
15383
+ }
15314
15384
  }
15315
15385
 
15316
15386
  // Insert node maker where we will insert the new HTML and get it's parent
@@ -15529,16 +15599,42 @@ define("tinymce/EditorCommands", [
15529
15599
  },
15530
15600
 
15531
15601
  selectAll: function() {
15532
- var root = dom.getRoot(), rng = dom.createRng();
15602
+ var root = dom.getRoot(), rng;
15533
15603
 
15534
- // Old IE does a better job with selectall than new versions
15535
15604
  if (selection.getRng().setStart) {
15605
+ rng = dom.createRng();
15536
15606
  rng.setStart(root, 0);
15537
15607
  rng.setEnd(root, root.childNodes.length);
15538
-
15539
15608
  selection.setRng(rng);
15540
15609
  } else {
15541
- execNativeCommand('SelectAll');
15610
+ // IE will render it's own root level block elements and sometimes
15611
+ // even put font elements in them when the user starts typing. So we need to
15612
+ // move the selection to a more suitable element from this:
15613
+ // <body>|<p></p></body> to this: <body><p>|</p></body>
15614
+ rng = selection.getRng();
15615
+ if (!rng.item) {
15616
+ rng.moveToElementText(root);
15617
+ rng.select();
15618
+ }
15619
+ }
15620
+ },
15621
+
15622
+ "delete": function() {
15623
+ execNativeCommand("Delete");
15624
+
15625
+ // Check if body is empty after the delete call if so then set the contents
15626
+ // to an empty string and move the caret to any block produced by that operation
15627
+ // this fixes the issue with root blocks not being properly produced after a delete call on IE
15628
+ var body = editor.getBody();
15629
+
15630
+ if (dom.isEmpty(body)) {
15631
+ editor.setContent('');
15632
+
15633
+ if (body.firstChild && dom.isBlock(body.firstChild)) {
15634
+ editor.selection.setCursorLocation(body.firstChild, 0);
15635
+ } else {
15636
+ editor.selection.setCursorLocation(body, 0);
15637
+ }
15542
15638
  }
15543
15639
  },
15544
15640
 
@@ -15673,15 +15769,21 @@ define("tinymce/util/URI", [
15673
15769
  return;
15674
15770
  }
15675
15771
 
15772
+ var isProtocolRelative = url.indexOf('//') === 0;
15773
+
15676
15774
  // Absolute path with no host, fake host and protocol
15677
- if (url.indexOf('/') === 0 && url.indexOf('//') !== 0) {
15775
+ if (url.indexOf('/') === 0 && !isProtocolRelative) {
15678
15776
  url = (settings.base_uri ? settings.base_uri.protocol || 'http' : 'http') + '://mce_host' + url;
15679
15777
  }
15680
15778
 
15681
15779
  // Relative path http:// or protocol relative //path
15682
15780
  if (!/^[\w\-]*:?\/\//.test(url)) {
15683
15781
  base_url = settings.base_uri ? settings.base_uri.path : new URI(location.href).directory;
15684
- url = ((settings.base_uri && settings.base_uri.protocol) || 'http') + '://mce_host' + self.toAbsPath(base_url, url);
15782
+ if (settings.base_uri.protocol === "") {
15783
+ url = '//mce_host' + self.toAbsPath(base_url, url);
15784
+ } else {
15785
+ url = ((settings.base_uri && settings.base_uri.protocol) || 'http') + '://mce_host' + self.toAbsPath(base_url, url);
15786
+ }
15685
15787
  }
15686
15788
 
15687
15789
  // Parse URL (Credits goes to Steave, http://blog.stevenlevithan.com/archives/parseuri)
@@ -15722,6 +15824,10 @@ define("tinymce/util/URI", [
15722
15824
  self.source = '';
15723
15825
  }
15724
15826
 
15827
+ if (isProtocolRelative) {
15828
+ self.protocol = '';
15829
+ }
15830
+
15725
15831
  //t.path = t.path || '/';
15726
15832
  }
15727
15833
 
@@ -15767,14 +15873,15 @@ define("tinymce/util/URI", [
15767
15873
  uri = new URI(uri, {base_uri: self});
15768
15874
 
15769
15875
  // Not on same domain/port or protocol
15770
- if ((uri.host != 'mce_host' && self.host != uri.host && uri.host) || self.port != uri.port || self.protocol != uri.protocol) {
15876
+ if ((uri.host != 'mce_host' && self.host != uri.host && uri.host) || self.port != uri.port ||
15877
+ (self.protocol != uri.protocol && uri.protocol !== "")) {
15771
15878
  return uri.getURI();
15772
15879
  }
15773
15880
 
15774
15881
  var tu = self.getURI(), uu = uri.getURI();
15775
15882
 
15776
15883
  // Allow usage of the base_uri when relative_urls = true
15777
- if(tu == uu || (tu.charAt(tu.length - 1) == "/" && tu.substr(0, tu.length - 1) == uu)) {
15884
+ if (tu == uu || (tu.charAt(tu.length - 1) == "/" && tu.substr(0, tu.length - 1) == uu)) {
15778
15885
  return tu;
15779
15886
  }
15780
15887
 
@@ -15946,6 +16053,8 @@ define("tinymce/util/URI", [
15946
16053
  if (!noProtoHost) {
15947
16054
  if (self.protocol) {
15948
16055
  s += self.protocol + '://';
16056
+ } else {
16057
+ s += '//';
15949
16058
  }
15950
16059
 
15951
16060
  if (self.userInfo) {
@@ -17493,7 +17602,12 @@ define("tinymce/ui/Control", [
17493
17602
  * @method repaint
17494
17603
  */
17495
17604
  repaint: function() {
17496
- var self = this, style, bodyStyle, rect, borderBox, borderW = 0, borderH = 0, lastRepaintRect;
17605
+ var self = this, style, bodyStyle, rect, borderBox, borderW = 0, borderH = 0, lastRepaintRect, round;
17606
+
17607
+ // Use Math.round on all values on IE < 9
17608
+ round = !document.createRange ? Math.round : function(value) {
17609
+ return value;
17610
+ };
17497
17611
 
17498
17612
  style = self.getEl().style;
17499
17613
  rect = self._layoutRect;
@@ -17504,35 +17618,35 @@ define("tinymce/ui/Control", [
17504
17618
  borderH = borderBox.top + borderBox.bottom;
17505
17619
 
17506
17620
  if (rect.x !== lastRepaintRect.x) {
17507
- style.left = rect.x + 'px';
17621
+ style.left = round(rect.x) + 'px';
17508
17622
  lastRepaintRect.x = rect.x;
17509
17623
  }
17510
17624
 
17511
17625
  if (rect.y !== lastRepaintRect.y) {
17512
- style.top = rect.y + 'px';
17626
+ style.top = round(rect.y) + 'px';
17513
17627
  lastRepaintRect.y = rect.y;
17514
17628
  }
17515
17629
 
17516
17630
  if (rect.w !== lastRepaintRect.w) {
17517
- style.width = (rect.w - borderW) + 'px';
17631
+ style.width = round(rect.w - borderW) + 'px';
17518
17632
  lastRepaintRect.w = rect.w;
17519
17633
  }
17520
17634
 
17521
17635
  if (rect.h !== lastRepaintRect.h) {
17522
- style.height = (rect.h - borderH) + 'px';
17636
+ style.height = round(rect.h - borderH) + 'px';
17523
17637
  lastRepaintRect.h = rect.h;
17524
17638
  }
17525
17639
 
17526
17640
  // Update body if needed
17527
17641
  if (self._hasBody && rect.innerW !== lastRepaintRect.innerW) {
17528
17642
  bodyStyle = self.getEl('body').style;
17529
- bodyStyle.width = (rect.innerW) + 'px';
17643
+ bodyStyle.width = round(rect.innerW) + 'px';
17530
17644
  lastRepaintRect.innerW = rect.innerW;
17531
17645
  }
17532
17646
 
17533
17647
  if (self._hasBody && rect.innerH !== lastRepaintRect.innerH) {
17534
17648
  bodyStyle = bodyStyle || self.getEl('body').style;
17535
- bodyStyle.height = (rect.innerH) + 'px';
17649
+ bodyStyle.height = round(rect.innerH) + 'px';
17536
17650
  lastRepaintRect.innerH = rect.innerH;
17537
17651
  }
17538
17652
 
@@ -20876,7 +20990,7 @@ define("tinymce/ui/Window", [
20876
20990
  * @return {tinymce.ui.Control} Current control instance.
20877
20991
  */
20878
20992
  remove: function() {
20879
- var self = this;
20993
+ var self = this, prefix = self.classPrefix;
20880
20994
 
20881
20995
  self.dragHelper.destroy();
20882
20996
  self._super();
@@ -20884,6 +20998,11 @@ define("tinymce/ui/Window", [
20884
20998
  if (self.statusbar) {
20885
20999
  this.statusbar.remove();
20886
21000
  }
21001
+
21002
+ if (self._fullscreen) {
21003
+ DomUtils.removeClass(document.documentElement, prefix + 'fullscreen');
21004
+ DomUtils.removeClass(document.body, prefix + 'fullscreen');
21005
+ }
20887
21006
  }
20888
21007
  });
20889
21008
 
@@ -21495,6 +21614,16 @@ define("tinymce/util/Quirks", [
21495
21614
  }
21496
21615
 
21497
21616
  function allContentsSelected(rng) {
21617
+ if (!rng.setStart) {
21618
+ if (rng.item) {
21619
+ return false;
21620
+ }
21621
+
21622
+ var bodyRng = rng.duplicate();
21623
+ bodyRng.moveToElementText(editor.getBody());
21624
+ return RangeUtils.compareRanges(rng, bodyRng);
21625
+ }
21626
+
21498
21627
  var selection = serializeRng(rng);
21499
21628
 
21500
21629
  var allRng = dom.createRng();
@@ -21505,19 +21634,15 @@ define("tinymce/util/Quirks", [
21505
21634
  }
21506
21635
 
21507
21636
  editor.on('keydown', function(e) {
21508
- var keyCode = e.keyCode, isCollapsed;
21637
+ var keyCode = e.keyCode, isCollapsed, body;
21509
21638
 
21510
21639
  // Empty the editor if it's needed for example backspace at <p><b>|</b></p>
21511
21640
  if (!isDefaultPrevented(e) && (keyCode == DELETE || keyCode == BACKSPACE)) {
21512
21641
  isCollapsed = editor.selection.isCollapsed();
21642
+ body = editor.getBody();
21513
21643
 
21514
21644
  // Selection is collapsed but the editor isn't empty
21515
- if (isCollapsed && !dom.isEmpty(editor.getBody())) {
21516
- return;
21517
- }
21518
-
21519
- // IE deletes all contents correctly when everything is selected
21520
- if (isIE && !isCollapsed) {
21645
+ if (isCollapsed && !dom.isEmpty(body)) {
21521
21646
  return;
21522
21647
  }
21523
21648
 
@@ -21529,7 +21654,13 @@ define("tinymce/util/Quirks", [
21529
21654
  // Manually empty the editor
21530
21655
  e.preventDefault();
21531
21656
  editor.setContent('');
21532
- editor.selection.setCursorLocation(editor.getBody(), 0);
21657
+
21658
+ if (body.firstChild && dom.isBlock(body.firstChild)) {
21659
+ editor.selection.setCursorLocation(body.firstChild, 0);
21660
+ } else {
21661
+ editor.selection.setCursorLocation(body, 0);
21662
+ }
21663
+
21533
21664
  editor.nodeChanged();
21534
21665
  }
21535
21666
  });
@@ -21537,6 +21668,7 @@ define("tinymce/util/Quirks", [
21537
21668
 
21538
21669
  /**
21539
21670
  * WebKit doesn't select all the nodes in the body when you press Ctrl+A.
21671
+ * IE selects more than the contents <body>[<p>a</p>]</body> instead of <body><p>[a]</p]</body> see bug #6438
21540
21672
  * This selects the whole body so that backspace/delete logic will delete everything
21541
21673
  */
21542
21674
  function selectAll() {
@@ -22265,6 +22397,21 @@ define("tinymce/util/Quirks", [
22265
22397
  }
22266
22398
  }
22267
22399
 
22400
+ /**
22401
+ * Firefox on Mac OS will move the browser back to the previous page if you press CMD+Left arrow.
22402
+ * You might then loose all your work so we need to block that behavior and replace it with our own.
22403
+ */
22404
+ function blockCmdArrowNavigation() {
22405
+ if (Env.mac) {
22406
+ editor.on('keydown', function(e) {
22407
+ if (VK.metaKeyPressed(e) && (e.keyCode == 37 || e.keyCode == 39)) {
22408
+ e.preventDefault();
22409
+ editor.selection.getSel().modify('move', e.keyCode == 37 ? 'backward' : 'forward', 'word');
22410
+ }
22411
+ });
22412
+ }
22413
+ }
22414
+
22268
22415
  // All browsers
22269
22416
  disableBackspaceIntoATable();
22270
22417
  removeBlockQuoteOnBackSpace();
@@ -22283,6 +22430,7 @@ define("tinymce/util/Quirks", [
22283
22430
  if (Env.iOS) {
22284
22431
  selectionChangeNodeChanged();
22285
22432
  restoreFocusOnKeyDown();
22433
+ bodyHeight();
22286
22434
  } else {
22287
22435
  selectAll();
22288
22436
  }
@@ -22304,6 +22452,10 @@ define("tinymce/util/Quirks", [
22304
22452
  bodyHeight();
22305
22453
  }
22306
22454
 
22455
+ if (Env.ie) {
22456
+ selectAll();
22457
+ }
22458
+
22307
22459
  // Gecko
22308
22460
  if (isGecko) {
22309
22461
  removeHrOnBackspace();
@@ -22313,6 +22465,7 @@ define("tinymce/util/Quirks", [
22313
22465
  addBrAfterLastLinks();
22314
22466
  removeGhostSelection();
22315
22467
  showBrokenImageIcon();
22468
+ blockCmdArrowNavigation();
22316
22469
  }
22317
22470
  };
22318
22471
  });
@@ -22594,7 +22747,7 @@ define("tinymce/Shortcuts", [
22594
22747
  editor.on('keyup keypress keydown', function(e) {
22595
22748
  if (e.altKey || e.ctrlKey || e.metaKey) {
22596
22749
  each(shortcuts, function(shortcut) {
22597
- var ctrlKey = Env.mac ? (e.ctrlKey || e.metaKey) : e.ctrlKey;
22750
+ var ctrlKey = Env.mac ? e.metaKey : e.ctrlKey;
22598
22751
 
22599
22752
  if (shortcut.ctrl != ctrlKey || shortcut.alt != e.altKey || shortcut.shift != e.shiftKey) {
22600
22753
  return;
@@ -23200,9 +23353,6 @@ define("tinymce/Editor", [
23200
23353
  // Create all plugins
23201
23354
  each(settings.plugins.replace(/\-/g, '').split(/[ ,]/), initPlugin);
23202
23355
 
23203
- // Enables users to override the control factory
23204
- self.fire('BeforeRenderUI');
23205
-
23206
23356
  // Measure box
23207
23357
  if (settings.render_ui && self.theme) {
23208
23358
  self.orgDisplay = elm.style.display;
@@ -24216,7 +24366,7 @@ define("tinymce/Editor", [
24216
24366
  var self = this, doc = self.getDoc();
24217
24367
 
24218
24368
  // Fixed bug where IE has a blinking cursor left from the editor
24219
- if (ie && doc) {
24369
+ if (ie && doc && !self.inline) {
24220
24370
  doc.execCommand('SelectAll');
24221
24371
  }
24222
24372
 
@@ -24387,6 +24537,7 @@ define("tinymce/Editor", [
24387
24537
 
24388
24538
  // Check if forcedRootBlock is configured and that the block is a valid child of the body
24389
24539
  if (forcedRootBlockName && self.schema.isValidChild(body.nodeName.toLowerCase(), forcedRootBlockName.toLowerCase())) {
24540
+ // Padd with bogus BR elements on modern browsers and IE 7 and 8 since they don't render empty P tags properly
24390
24541
  content = ie && ie < 11 ? '' : '<br data-mce-bogus="1">';
24391
24542
  content = self.dom.createHTML(forcedRootBlockName, self.settings.forced_root_block_attrs, content);
24392
24543
  } else if (!ie || ie < 11) {
@@ -24697,7 +24848,7 @@ define("tinymce/Editor", [
24697
24848
 
24698
24849
  // Fixed bug where IE has a blinking cursor left from the editor
24699
24850
  var doc = self.getDoc();
24700
- if (ie && doc) {
24851
+ if (ie && doc && !self.inline) {
24701
24852
  doc.execCommand('SelectAll');
24702
24853
  }
24703
24854
 
@@ -25013,6 +25164,18 @@ define("tinymce/FocusManager", [
25013
25164
  return !!DOMUtils.DOM.getParent(elm, FocusManager.isEditorUIElement);
25014
25165
  }
25015
25166
 
25167
+ function isNodeInBody(node) {
25168
+ var body = editor.getBody();
25169
+
25170
+ while (node) {
25171
+ if (node == body) {
25172
+ return true;
25173
+ }
25174
+
25175
+ node = node.parentNode;
25176
+ }
25177
+ }
25178
+
25016
25179
  editor.on('init', function() {
25017
25180
  // On IE take selection snapshot onbeforedeactivate
25018
25181
  if ("onbeforedeactivate" in document && Env.ie < 11) {
@@ -25028,24 +25191,14 @@ define("tinymce/FocusManager", [
25028
25191
  } else if (editor.inline || Env.ie > 10) {
25029
25192
  // On other browsers take snapshot on nodechange in inline mode since they have Ghost selections for iframes
25030
25193
  editor.on('nodechange keyup', function() {
25031
- var isInBody, node = document.activeElement;
25194
+ var node = document.activeElement;
25032
25195
 
25033
25196
  // IE 11 reports active element as iframe not body of iframe
25034
25197
  if (node && node.id == editor.id + '_ifr') {
25035
25198
  node = editor.getBody();
25036
25199
  }
25037
25200
 
25038
- // Check if selection is within editor body
25039
- while (node) {
25040
- if (node == editor.getBody()) {
25041
- isInBody = true;
25042
- break;
25043
- }
25044
-
25045
- node = node.parentNode;
25046
- }
25047
-
25048
- if (isInBody) {
25201
+ if (isNodeInBody(node)) {
25049
25202
  lastRng = editor.selection.getRng();
25050
25203
  }
25051
25204
  });
@@ -25105,7 +25258,14 @@ define("tinymce/FocusManager", [
25105
25258
  lastRng = null;
25106
25259
  });
25107
25260
 
25108
- editor.on('focusout', function() {
25261
+ editor.on('focusout', function(e) {
25262
+ // Moving focus to elements within the body that have a control seleciton on IE
25263
+ // will fire an focusout event so we need to check if the event is fired on the body
25264
+ // or on a sub element see #6456
25265
+ if (e.target !== editor.getBody() && isNodeInBody(e.target)) {
25266
+ return;
25267
+ }
25268
+
25109
25269
  editor.selection.lastFocusBookmark = createBookmark(lastRng);
25110
25270
 
25111
25271
  window.setTimeout(function() {
@@ -25194,7 +25354,7 @@ define("tinymce/EditorManager", [
25194
25354
  * @property minorVersion
25195
25355
  * @type String
25196
25356
  */
25197
- minorVersion : '0.10',
25357
+ minorVersion : '0.11',
25198
25358
 
25199
25359
  /**
25200
25360
  * Release date of TinyMCE build.
@@ -25202,7 +25362,7 @@ define("tinymce/EditorManager", [
25202
25362
  * @property releaseDate
25203
25363
  * @type String
25204
25364
  */
25205
- releaseDate: '2013-10-28',
25365
+ releaseDate: '2013-11-20',
25206
25366
 
25207
25367
  /**
25208
25368
  * Collection of editor instances.
@@ -25254,7 +25414,11 @@ define("tinymce/EditorManager", [
25254
25414
  for (var i = 0; i < scripts.length; i++) {
25255
25415
  var src = scripts[i].src;
25256
25416
 
25257
- if (/tinymce(\.jquery|)(\.min|\.dev|)\.js/.test(src)) {
25417
+ // Script types supported:
25418
+ // tinymce.js tinymce.min.js tinymce.dev.js
25419
+ // tinymce.jquery.js tinymce.jquery.min.js tinymce.jquery.dev.js
25420
+ // tinymce.full.js tinymce.full.min.js tinymce.full.dev.js
25421
+ if (/tinymce(\.full|\.jquery|)(\.min|\.dev|)\.js/.test(src)) {
25258
25422
  if (src.indexOf('.min') != -1) {
25259
25423
  suffix = '.min';
25260
25424
  }
@@ -26944,6 +27108,43 @@ define("tinymce/ui/Button", [
26944
27108
  }
26945
27109
  },
26946
27110
 
27111
+ /**
27112
+ * Sets/gets the current button icon.
27113
+ *
27114
+ * @method icon
27115
+ * @param {String} [icon] New icon identifier.
27116
+ * @return {String|tinymce.ui.MenuButton} Current icon or current MenuButton instance.
27117
+ */
27118
+ icon: function(icon) {
27119
+ var self = this, prefix = self.classPrefix;
27120
+
27121
+ if (typeof(icon) == 'undefined') {
27122
+ return self.settings.icon;
27123
+ }
27124
+
27125
+ self.settings.icon = icon;
27126
+ icon = icon ? prefix + 'ico ' + prefix + 'i-' + self.settings.icon : '';
27127
+
27128
+ if (self._rendered) {
27129
+ var btnElm = self.getEl().firstChild, iconElm = btnElm.getElementsByTagName('i')[0];
27130
+
27131
+ if (icon) {
27132
+ if (!iconElm || iconElm != btnElm.firstChild) {
27133
+ iconElm = document.createElement('i');
27134
+ btnElm.insertBefore(iconElm, btnElm.firstChild);
27135
+ }
27136
+
27137
+ iconElm.className = icon;
27138
+ } else if (iconElm) {
27139
+ btnElm.removeChild(iconElm);
27140
+ }
27141
+
27142
+ self.text(self._text); // Set text again to fix whitespace between icon + text
27143
+ }
27144
+
27145
+ return self;
27146
+ },
27147
+
26947
27148
  /**
26948
27149
  * Repaints the button for example after it's been resizes by a layout engine.
26949
27150
  *
@@ -28415,7 +28616,7 @@ define("tinymce/ui/FlexLayout", [
28415
28616
  ctrl = maxSizeItems[i];
28416
28617
  ctrlLayoutRect = ctrl.layoutRect();
28417
28618
  maxSize = ctrlLayoutRect[maxSizeName];
28418
- size = ctrlLayoutRect[minSizeName] + Math.ceil(ctrlLayoutRect.flex * ratio);
28619
+ size = ctrlLayoutRect[minSizeName] + ctrlLayoutRect.flex * ratio;
28419
28620
 
28420
28621
  if (size > maxSize) {
28421
28622
  availableSpace -= (ctrlLayoutRect[maxSizeName] - ctrlLayoutRect[minSizeName]);
@@ -28474,7 +28675,7 @@ define("tinymce/ui/FlexLayout", [
28474
28675
 
28475
28676
  // Calculate new size based on flex
28476
28677
  if (ctrlLayoutRect.flex > 0) {
28477
- size += Math.ceil(ctrlLayoutRect.flex * ratio);
28678
+ size += ctrlLayoutRect.flex * ratio;
28478
28679
  }
28479
28680
 
28480
28681
  rect[sizeName] = size;
@@ -28597,7 +28798,7 @@ define("tinymce/ui/FormatControls", [
28597
28798
 
28598
28799
  // Default preview
28599
28800
  if (!previewStyles) {
28600
- previewStyles = 'font-family font-size font-weight text-decoration ' +
28801
+ previewStyles = 'font-family font-size font-weight font-style text-decoration ' +
28601
28802
  'text-transform color background-color border border-radius';
28602
28803
  }
28603
28804
 
@@ -29351,7 +29552,7 @@ define("tinymce/ui/GridLayout", [
29351
29552
  // Calculate new column widths based on flex values
29352
29553
  var ratio = availableWidth / totalFlex;
29353
29554
  for (x = 0; x < cols; x++) {
29354
- colWidths[x] += flexWidths ? Math.ceil(flexWidths[x] * ratio) : ratio;
29555
+ colWidths[x] += flexWidths ? flexWidths[x] * ratio : ratio;
29355
29556
  }
29356
29557
 
29357
29558
  // Move/resize controls
@@ -29940,7 +30141,7 @@ define("tinymce/ui/MenuButton", [
29940
30141
  if (self._rendered) {
29941
30142
  children = self.getEl('open').getElementsByTagName('span');
29942
30143
  for (i = 0; i < children.length; i++) {
29943
- children[i].innerHTML = self.encode(text);
30144
+ children[i].innerHTML = (self.settings.icon && text ? '\u00a0' : '') + self.encode(text);
29944
30145
  }
29945
30146
  }
29946
30147
 
@@ -30106,8 +30307,9 @@ define("tinymce/ui/ListBox", [
30106
30307
  */
30107
30308
  define("tinymce/ui/MenuItem", [
30108
30309
  "tinymce/ui/Widget",
30109
- "tinymce/ui/Factory"
30110
- ], function(Widget, Factory) {
30310
+ "tinymce/ui/Factory",
30311
+ "tinymce/Env"
30312
+ ], function(Widget, Factory, Env) {
30111
30313
  "use strict";
30112
30314
 
30113
30315
  return Widget.extend({
@@ -30301,7 +30503,7 @@ define("tinymce/ui/MenuItem", [
30301
30503
  */
30302
30504
  renderHtml: function() {
30303
30505
  var self = this, id = self._id, settings = self.settings, prefix = self.classPrefix, text = self.encode(self._text);
30304
- var icon = self.settings.icon, image = '';
30506
+ var icon = self.settings.icon, image = '', shortcut = settings.shortcut;
30305
30507
 
30306
30508
  if (icon) {
30307
30509
  self.parent().addClass('menu-has-icons');
@@ -30312,14 +30514,22 @@ define("tinymce/ui/MenuItem", [
30312
30514
  image = ' style="background-image: url(\'' + settings.image + '\')"';
30313
30515
  }
30314
30516
 
30517
+ if (shortcut && Env.mac) {
30518
+ // format shortcut for Mac
30519
+ shortcut = shortcut.replace(/ctrl\+alt\+/i, '&#x2325;&#x2318;'); // ctrl+cmd
30520
+ shortcut = shortcut.replace(/ctrl\+/i, '&#x2318;'); // ctrl symbol
30521
+ shortcut = shortcut.replace(/alt\+/i, '&#x2325;'); // cmd symbol
30522
+ shortcut = shortcut.replace(/shift\+/i, '&#x21E7;'); // shift symbol
30523
+ }
30524
+
30315
30525
  icon = prefix + 'ico ' + prefix + 'i-' + (self.settings.icon || 'none');
30316
30526
 
30317
30527
  return (
30318
30528
  '<div id="' + id + '" class="' + self.classes() + '" tabindex="-1">' +
30319
30529
  (text !== '-' ? '<i class="' + icon + '"' + image + '></i>&nbsp;' : '') +
30320
30530
  (text !== '-' ? '<span id="' + id + '-text" class="' + prefix + 'text">' + text + '</span>' : '') +
30321
- (settings.shortcut ? '<div id="' + id + '-shortcut" class="' + prefix + 'menu-shortcut">' +
30322
- settings.shortcut + '</div>' : '') +
30531
+ (shortcut ? '<div id="' + id + '-shortcut" class="' + prefix + 'menu-shortcut">' +
30532
+ shortcut + '</div>' : '') +
30323
30533
  (settings.menu ? '<div class="' + prefix + 'caret"></div>' : '') +
30324
30534
  '</div>'
30325
30535
  );