tinymce-rails 4.1.2 → 4.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8ed252e5480fab2a3bbb1983a01e1f957a35ab4e
4
- data.tar.gz: ee8dea59d4d5816febe74868d41a8d3704e1bf96
3
+ metadata.gz: 7b10bebdbdb38594580eae5b6efb7779ccbf7d90
4
+ data.tar.gz: 8f272bf38e6f925f8b7f661e78bd94322fbd5146
5
5
  SHA512:
6
- metadata.gz: 640e3793e032a0930269af99cb9e087bb6c37e06a72ac7c96c2db5a307d740c58148424711c4c12621fa7b22385d1e97fc4a1fe777f5ef86b07c4f84eff8ff10
7
- data.tar.gz: f52b7cdb924065fa538253e6f0fa13edb623274b86e068fca7aed80a2bc8bc8b24b036f067074d22e5beb8670abd8ca7297c54aabb9e2ca0baf91eb9eee45f5d
6
+ metadata.gz: d6c327d32ff8d7a2e7ab86f87870a35d46359a31bcfa4244e106f17ab3903e43dc50c24dc9937b3e7edd6b7ca4bf44784c9b8ae8c7ea76481d1689d1f6ed8e28
7
+ data.tar.gz: 46b11c4ac4f498ce446b35b9763f514fc693d36a5753415af8accc2008079e161bb84c508a1a3af0499891f1d1d3d6244c95855d200d58f80e47e5c7fc62011b
@@ -1,4 +1,4 @@
1
- // 4.1.2 (2014-07-15)
1
+ // 4.1.3 (2014-07-29)
2
2
 
3
3
  /**
4
4
  * Compiled inline version. (Library mode)
@@ -454,6 +454,7 @@ define("tinymce/dom/EventUtils", [], function() {
454
454
  events[id][name] = callbackList = [{func: callback, scope: scope}];
455
455
  callbackList.fakeName = fakeName;
456
456
  callbackList.capture = capture;
457
+ //callbackList.callback = callback;
457
458
 
458
459
  // Add the nativeHandler to the callback list so that we can later unbind it
459
460
  callbackList.nativeHandler = nativeHandler;
@@ -1450,7 +1451,7 @@ define("tinymce/dom/DomQuery", [
1450
1451
  'readonly': 'readOnly'
1451
1452
  };
1452
1453
  var cssFix = {
1453
- float: 'cssFloat'
1454
+ 'float': 'cssFloat'
1454
1455
  };
1455
1456
 
1456
1457
  var attrHooks = {}, cssHooks = {};
@@ -2778,7 +2779,7 @@ define("tinymce/dom/DomQuery", [
2778
2779
  DomQuery.overrideDefaults = function(callback) {
2779
2780
  var defaults;
2780
2781
 
2781
- function jQuerySub(selector, context) {
2782
+ function sub(selector, context) {
2782
2783
  defaults = defaults || callback();
2783
2784
 
2784
2785
  if (arguments.length === 0) {
@@ -2789,12 +2790,12 @@ define("tinymce/dom/DomQuery", [
2789
2790
  context = defaults.context;
2790
2791
  }
2791
2792
 
2792
- return new jQuerySub.fn.init(selector, context);
2793
+ return new sub.fn.init(selector, context);
2793
2794
  }
2794
2795
 
2795
- DomQuery.extend(jQuerySub, this);
2796
+ DomQuery.extend(sub, this);
2796
2797
 
2797
- return jQuerySub;
2798
+ return sub;
2798
2799
  };
2799
2800
 
2800
2801
  function appendHooks(targetHooks, prop, hooks) {
@@ -2853,7 +2854,9 @@ define("tinymce/dom/DomQuery", [
2853
2854
  }
2854
2855
 
2855
2856
  if (Env.ie && Env.ie < 9) {
2856
- cssFix.float = 'styleFloat';
2857
+ /*jshint sub:true */
2858
+ /*eslint dot-notation: 0*/
2859
+ cssFix['float'] = 'styleFloat';
2857
2860
 
2858
2861
  appendHooks(cssHooks, 'set', {
2859
2862
  opacity: function(elm, value) {
@@ -5304,6 +5307,10 @@ define("tinymce/dom/DOMUtils", [
5304
5307
  elm = self.$$(elm);
5305
5308
  originalValue = elm.attr(name);
5306
5309
 
5310
+ if (!elm.length) {
5311
+ return;
5312
+ }
5313
+
5307
5314
  hook = self.attrHooks[name];
5308
5315
  if (hook && hook.set) {
5309
5316
  hook.set(elm, value, name);
@@ -5357,11 +5364,14 @@ define("tinymce/dom/DOMUtils", [
5357
5364
 
5358
5365
  elm = self.$$(elm);
5359
5366
 
5360
- hook = self.attrHooks[name];
5361
- if (hook && hook.get) {
5362
- value = hook.get(elm, name);
5363
- } else {
5364
- value = elm.attr(name);
5367
+ if (elm.length) {
5368
+ hook = self.attrHooks[name];
5369
+
5370
+ if (hook && hook.get) {
5371
+ value = hook.get(elm, name);
5372
+ } else {
5373
+ value = elm.attr(name);
5374
+ }
5365
5375
  }
5366
5376
 
5367
5377
  if (typeof value == 'undefined') {
@@ -5380,21 +5390,22 @@ define("tinymce/dom/DOMUtils", [
5380
5390
  * @return {object} Absolute position of the specified element object with x, y fields.
5381
5391
  */
5382
5392
  getPos: function(elm, rootElm) {
5383
- var self = this, x = 0, y = 0, offsetParent, doc = self.doc, pos;
5393
+ var self = this, x = 0, y = 0, offsetParent, doc = self.doc, body = doc.body, pos;
5384
5394
 
5385
5395
  elm = self.get(elm);
5386
- rootElm = rootElm || doc.body;
5396
+ rootElm = rootElm || body;
5387
5397
 
5388
5398
  if (elm) {
5389
5399
  // Use getBoundingClientRect if it exists since it's faster than looping offset nodes
5390
- if (rootElm === doc.body && elm.getBoundingClientRect) {
5400
+ // Fallback to offsetParent calculations if the body isn't static better since it stops at the body root
5401
+ if (rootElm === body && elm.getBoundingClientRect && $(body).css('position') === 'static') {
5391
5402
  pos = elm.getBoundingClientRect();
5392
- rootElm = self.boxModel ? doc.documentElement : doc.body;
5403
+ rootElm = self.boxModel ? doc.documentElement : body;
5393
5404
 
5394
5405
  // Add scroll offsets from documentElement or body since IE with the wrong box model will use d.body and so do WebKit
5395
5406
  // Also remove the body/documentelement clientTop/clientLeft on IE 6, 7 since they offset the position
5396
- x = pos.left + (doc.documentElement.scrollLeft || doc.body.scrollLeft) - rootElm.clientLeft;
5397
- y = pos.top + (doc.documentElement.scrollTop || doc.body.scrollTop) - rootElm.clientTop;
5407
+ x = pos.left + (doc.documentElement.scrollLeft || body.scrollLeft) - rootElm.clientLeft;
5408
+ y = pos.top + (doc.documentElement.scrollTop || body.scrollTop) - rootElm.clientTop;
5398
5409
 
5399
5410
  return {x: x, y: y};
5400
5411
  }
@@ -7465,7 +7476,7 @@ define("tinymce/NodeChange", [
7465
7476
 
7466
7477
  // Gecko doesn't support the "selectionchange" event
7467
7478
  if (!('onselectionchange' in editor.getDoc())) {
7468
- editor.on('NodeChange Click MouseUp KeyUp', function(e) {
7479
+ editor.on('NodeChange Click MouseUp KeyUp Focus', function(e) {
7469
7480
  var nativeRng, fakeRng;
7470
7481
 
7471
7482
  // Since DOM Ranges mutate on modification
@@ -7495,7 +7506,7 @@ define("tinymce/NodeChange", [
7495
7506
  });
7496
7507
 
7497
7508
  editor.on('SelectionChange', function() {
7498
- var startElm = editor.selection.getStart();
7509
+ var startElm = editor.selection.getStart(true);
7499
7510
 
7500
7511
  // Selection change might fire when focus is lost so check if the start is still within the body
7501
7512
  if (!isSameElementPath(startElm) && editor.dom.isChildOf(startElm, editor.getBody())) {
@@ -7503,6 +7514,13 @@ define("tinymce/NodeChange", [
7503
7514
  }
7504
7515
  });
7505
7516
 
7517
+ // Fire an extra nodeChange on mouseup for compatibility reasons
7518
+ editor.on('MouseUp', function(e) {
7519
+ if (!e.isDefaultPrevented()) {
7520
+ editor.nodeChanged();
7521
+ }
7522
+ });
7523
+
7506
7524
  /**
7507
7525
  * Distpaches out a onNodeChange event to all observers. This method should be called when you
7508
7526
  * need to update the UI states or element path etc.
@@ -8073,7 +8091,7 @@ define("tinymce/html/Node", [], function() {
8073
8091
  define("tinymce/html/Schema", [
8074
8092
  "tinymce/util/Tools"
8075
8093
  ], function(Tools) {
8076
- var mapCache = {};
8094
+ var mapCache = {}, dummyObj = {};
8077
8095
  var makeMap = Tools.makeMap, each = Tools.each, extend = Tools.extend, explode = Tools.explode, inArray = Tools.inArray;
8078
8096
 
8079
8097
  function split(items, delim) {
@@ -8094,11 +8112,11 @@ define("tinymce/html/Schema", [
8094
8112
  function add(name, attributes, children) {
8095
8113
  var ni, i, attributesOrder, args = arguments;
8096
8114
 
8097
- function arrayToMap(array) {
8115
+ function arrayToMap(array, obj) {
8098
8116
  var map = {}, i, l;
8099
8117
 
8100
8118
  for (i = 0, l = array.length; i < l; i++) {
8101
- map[array[i]] = {};
8119
+ map[array[i]] = obj || {};
8102
8120
  }
8103
8121
 
8104
8122
  return map;
@@ -8127,7 +8145,7 @@ define("tinymce/html/Schema", [
8127
8145
  schema[name[ni]] = {
8128
8146
  attributes: arrayToMap(attributesOrder),
8129
8147
  attributesOrder: attributesOrder,
8130
- children: arrayToMap(children)
8148
+ children: arrayToMap(children, dummyObj)
8131
8149
  };
8132
8150
  }
8133
8151
  }
@@ -11850,6 +11868,7 @@ define("tinymce/dom/ControlSelection", [
11850
11868
  }
11851
11869
 
11852
11870
  editor.fire('ObjectResized', {target: selectedElm, width: width, height: height});
11871
+ dom.setAttrib(selectedElm, 'style', dom.getAttrib(selectedElm, 'style'));
11853
11872
  editor.nodeChanged();
11854
11873
  }
11855
11874
 
@@ -11997,7 +12016,7 @@ define("tinymce/dom/ControlSelection", [
11997
12016
  }
11998
12017
 
11999
12018
  function updateResizeRect(e) {
12000
- var controlElm;
12019
+ var startElm, controlElm;
12001
12020
 
12002
12021
  function isChildOrEqual(node, parent) {
12003
12022
  if (node) {
@@ -12019,9 +12038,10 @@ define("tinymce/dom/ControlSelection", [
12019
12038
 
12020
12039
  if (isChildOrEqual(controlElm, rootElement)) {
12021
12040
  disableGeckoResize();
12041
+ startElm = selection.getStart(true);
12022
12042
 
12023
- if (isChildOrEqual(selection.getStart(), controlElm) && isChildOrEqual(selection.getEnd(), controlElm)) {
12024
- if (!isIE || (controlElm != selection.getStart() && selection.getStart().nodeName !== 'IMG')) {
12043
+ if (isChildOrEqual(startElm, controlElm) && isChildOrEqual(selection.getEnd(true), controlElm)) {
12044
+ if (!isIE || (controlElm != startElm && startElm.nodeName !== 'IMG')) {
12025
12045
  showResizeRect(controlElm);
12026
12046
  return;
12027
12047
  }
@@ -12181,7 +12201,7 @@ define("tinymce/dom/ControlSelection", [
12181
12201
  }
12182
12202
  }
12183
12203
 
12184
- editor.on('nodechange mousedown mouseup ResizeEditor', updateResizeRect);
12204
+ editor.on('nodechange ResizeEditor', updateResizeRect);
12185
12205
 
12186
12206
  // Update resize rect while typing in a table
12187
12207
  editor.on('keydown keyup', function(e) {
@@ -12853,9 +12873,10 @@ define("tinymce/dom/Selection", [
12853
12873
  * node the parent element will be returned.
12854
12874
  *
12855
12875
  * @method getStart
12876
+ * @param {Boolean} real Optional state to get the real parent when the selection is collapsed not the closest element.
12856
12877
  * @return {Element} Start element of selection range.
12857
12878
  */
12858
- getStart: function() {
12879
+ getStart: function(real) {
12859
12880
  var self = this, rng = self.getRng(), startElement, parentElement, checkRng, node;
12860
12881
 
12861
12882
  if (rng.duplicate || rng.item) {
@@ -12887,7 +12908,9 @@ define("tinymce/dom/Selection", [
12887
12908
  startElement = rng.startContainer;
12888
12909
 
12889
12910
  if (startElement.nodeType == 1 && startElement.hasChildNodes()) {
12890
- startElement = startElement.childNodes[Math.min(startElement.childNodes.length - 1, rng.startOffset)];
12911
+ if (!real || !rng.collapsed) {
12912
+ startElement = startElement.childNodes[Math.min(startElement.childNodes.length - 1, rng.startOffset)];
12913
+ }
12891
12914
  }
12892
12915
 
12893
12916
  if (startElement && startElement.nodeType == 3) {
@@ -12903,9 +12926,10 @@ define("tinymce/dom/Selection", [
12903
12926
  * node the parent element will be returned.
12904
12927
  *
12905
12928
  * @method getEnd
12929
+ * @param {Boolean} real Optional state to get the real parent when the selection is collapsed not the closest element.
12906
12930
  * @return {Element} End element of selection range.
12907
12931
  */
12908
- getEnd: function() {
12932
+ getEnd: function(real) {
12909
12933
  var self = this, rng = self.getRng(), endElement, endOffset;
12910
12934
 
12911
12935
  if (rng.duplicate || rng.item) {
@@ -12930,7 +12954,9 @@ define("tinymce/dom/Selection", [
12930
12954
  endOffset = rng.endOffset;
12931
12955
 
12932
12956
  if (endElement.nodeType == 1 && endElement.hasChildNodes()) {
12933
- endElement = endElement.childNodes[endOffset > 0 ? endOffset - 1 : endOffset];
12957
+ if (!real || !rng.collapsed) {
12958
+ endElement = endElement.childNodes[endOffset > 0 ? endOffset - 1 : endOffset];
12959
+ }
12934
12960
  }
12935
12961
 
12936
12962
  if (endElement && endElement.nodeType == 3) {
@@ -13522,8 +13548,8 @@ define("tinymce/dom/Selection", [
13522
13548
  return;
13523
13549
  }
13524
13550
 
13525
- // BR/IMG/INPUT elements
13526
- if (nonEmptyElementsMap[node.nodeName]) {
13551
+ // BR/IMG/INPUT elements but not table cells
13552
+ if (nonEmptyElementsMap[node.nodeName] && !/^(TD|TH)$/.test(node.nodeName)) {
13527
13553
  if (start) {
13528
13554
  rng.setStartBefore(node);
13529
13555
  } else {
@@ -13979,8 +14005,8 @@ define("tinymce/Formatter", [
13979
14005
  {inline: 'strike', remove: 'all'}
13980
14006
  ],
13981
14007
 
13982
- forecolor: {inline: 'span', styles: {color: '%value'}, wrap_links: false, remove_similar: true},
13983
- hilitecolor: {inline: 'span', styles: {backgroundColor: '%value'}, wrap_links: false, remove_similar: true},
14008
+ forecolor: {inline: 'span', styles: {color: '%value'}, links: true, remove_similar: true},
14009
+ hilitecolor: {inline: 'span', styles: {backgroundColor: '%value'}, links: true, remove_similar: true},
13984
14010
  fontname: {inline: 'span', styles: {fontFamily: '%value'}},
13985
14011
  fontsize: {inline: 'span', styles: {fontSize: '%value'}},
13986
14012
  fontsize_class: {inline: 'span', attributes: {'class': '%value'}},
@@ -14316,22 +14342,12 @@ define("tinymce/Formatter", [
14316
14342
  each(nodes, process);
14317
14343
  });
14318
14344
 
14319
- // Wrap links inside as well, for example color inside a link when the wrapper is around the link
14320
- if (format.wrap_links === false) {
14345
+ // Apply formats to links as well to get the color of the underline to change as well
14346
+ if (format.links === true) {
14321
14347
  each(newWrappers, function(node) {
14322
14348
  function process(node) {
14323
- var i, currentWrapElm, children;
14324
-
14325
14349
  if (node.nodeName === 'A') {
14326
- currentWrapElm = dom.clone(wrapElm, FALSE);
14327
- newWrappers.push(currentWrapElm);
14328
-
14329
- children = grep(node.childNodes);
14330
- for (i = 0; i < children.length; i++) {
14331
- currentWrapElm.appendChild(children[i]);
14332
- }
14333
-
14334
- node.appendChild(currentWrapElm);
14350
+ setElementFormat(node, format);
14335
14351
  }
14336
14352
 
14337
14353
  each(grep(node.childNodes), process);
@@ -14401,24 +14417,10 @@ define("tinymce/Formatter", [
14401
14417
  // this: <span style="color:red"><b><span style="color:red; font-size:10px">text</span></b></span>
14402
14418
  // will become: <span style="color:red"><b><span style="font-size:10px">text</span></b></span>
14403
14419
  each(dom.select(format.inline, node), function(child) {
14404
- var parent;
14405
-
14406
14420
  if (isBookmarkNode(child)) {
14407
14421
  return;
14408
14422
  }
14409
14423
 
14410
- // When wrap_links is set to false we don't want
14411
- // to remove the format on children within links
14412
- if (format.wrap_links === false) {
14413
- parent = child.parentNode;
14414
-
14415
- do {
14416
- if (parent.nodeName === 'A') {
14417
- return;
14418
- }
14419
- } while ((parent = parent.parentNode));
14420
- }
14421
-
14422
14424
  removeFormat(format, vars, child, format.exact ? child : null);
14423
14425
  });
14424
14426
  });
@@ -14960,7 +14962,7 @@ define("tinymce/Formatter", [
14960
14962
 
14961
14963
  // Ignore bogus nodes like the <a> tag created by moveStart()
14962
14964
  parents = Tools.grep(parents, function(node) {
14963
- return !node.getAttribute('data-mce-bogus');
14965
+ return node.nodeType == 1 && !node.getAttribute('data-mce-bogus');
14964
14966
  });
14965
14967
 
14966
14968
  // Check for new formats
@@ -15040,8 +15042,8 @@ define("tinymce/Formatter", [
15040
15042
  // Initialize
15041
15043
  defaultFormats();
15042
15044
  addKeyboardShortcuts();
15043
- ed.on('BeforeGetContent', function() {
15044
- if (markCaretContainersBogus) {
15045
+ ed.on('BeforeGetContent', function(e) {
15046
+ if (markCaretContainersBogus && e.format != 'raw') {
15045
15047
  markCaretContainersBogus();
15046
15048
  }
15047
15049
  });
@@ -15531,6 +15533,10 @@ define("tinymce/Formatter", [
15531
15533
  };
15532
15534
  }
15533
15535
 
15536
+ function isColorFormatAndAnchor(node, format) {
15537
+ return format.links && node.tagName == 'A';
15538
+ }
15539
+
15534
15540
  /**
15535
15541
  * Removes the specified format for the specified node. It will also remove the node if it doesn't have
15536
15542
  * any attributes if the format specifies it to do so.
@@ -15546,7 +15552,7 @@ define("tinymce/Formatter", [
15546
15552
  var i, attrs, stylesModified;
15547
15553
 
15548
15554
  // Check if node matches format
15549
- if (!matchName(node, format)) {
15555
+ if (!matchName(node, format) && !isColorFormatAndAnchor(node, format)) {
15550
15556
  return FALSE;
15551
15557
  }
15552
15558
 
@@ -18759,7 +18765,7 @@ define("tinymce/util/EventDispatcher", [
18759
18765
  "focus blur focusin focusout click dblclick mousedown mouseup mousemove mouseover beforepaste paste cut copy selectionchange " +
18760
18766
  "mouseout mouseenter mouseleave wheel keydown keypress keyup input contextmenu dragstart dragend dragover " +
18761
18767
  "draggesture dragdrop drop drag submit " +
18762
- "compositionstart compositionend compositionupdate",
18768
+ "compositionstart compositionend compositionupdate touchstart touchend",
18763
18769
  ' '
18764
18770
  );
18765
18771
 
@@ -19953,7 +19959,6 @@ define("tinymce/ui/Control", [
19953
19959
  ], function(Class, Tools, EventDispatcher, Collection, DomUtils) {
19954
19960
  "use strict";
19955
19961
 
19956
- var elementIdCache = {};
19957
19962
  var hasMouseWheelEventSupport = "onmousewheel" in document;
19958
19963
  var hasWheelEventSupport = false;
19959
19964
  var classPrefix = "mce-";
@@ -19983,7 +19988,6 @@ define("tinymce/ui/Control", [
19983
19988
 
19984
19989
  var Control = Class.extend({
19985
19990
  Statics: {
19986
- elementIdCache: elementIdCache,
19987
19991
  classPrefix: classPrefix
19988
19992
  },
19989
19993
 
@@ -20026,6 +20030,7 @@ define("tinymce/ui/Control", [
20026
20030
  self._text = self._name = '';
20027
20031
  self._width = self._height = 0;
20028
20032
  self._aria = {role: settings.role};
20033
+ this._elmCache = {};
20029
20034
 
20030
20035
  // Setup classes
20031
20036
  classes = settings.classes;
@@ -20767,15 +20772,16 @@ define("tinymce/ui/Control", [
20767
20772
  *
20768
20773
  * @method getEl
20769
20774
  * @param {String} [suffix] Suffix to get element by.
20770
- * @param {Boolean} [dropCache] True if the cache for the element should be dropped.
20771
20775
  * @return {Element} HTML DOM element for the current control or it's children.
20772
20776
  */
20773
- getEl: function(suffix, dropCache) {
20774
- var elm, id = suffix ? this._id + '-' + suffix : this._id;
20777
+ getEl: function(suffix) {
20778
+ var id = suffix ? this._id + '-' + suffix : this._id;
20775
20779
 
20776
- elm = elementIdCache[id] = (dropCache === true ? null : elementIdCache[id]) || DomUtils.get(id);
20780
+ if (!this._elmCache[id]) {
20781
+ this._elmCache[id] = DomUtils.get(id);
20782
+ }
20777
20783
 
20778
- return elm;
20784
+ return this._elmCache[id];
20779
20785
  },
20780
20786
 
20781
20787
  /**
@@ -20986,16 +20992,7 @@ define("tinymce/ui/Control", [
20986
20992
  delete lookup[self._id];
20987
20993
  }
20988
20994
 
20989
- delete elementIdCache[self._id];
20990
-
20991
20995
  if (elm && elm.parentNode) {
20992
- var nodes = elm.getElementsByTagName('*');
20993
-
20994
- i = nodes.length;
20995
- while (i--) {
20996
- delete elementIdCache[nodes[i].id];
20997
- }
20998
-
20999
20996
  elm.parentNode.removeChild(elm);
21000
20997
  }
21001
20998
 
@@ -23148,8 +23145,15 @@ define("tinymce/ui/FloatPanel", [
23148
23145
 
23149
23146
  function bindWindowResizeHandler() {
23150
23147
  if (!windowResizeHandler) {
23148
+ var docElm = document.documentElement, clientWidth = docElm.clientWidth, clientHeight = docElm.clientHeight;
23149
+
23151
23150
  windowResizeHandler = function() {
23152
- FloatPanel.hideAll();
23151
+ // Workaround for #7065 IE 7 fires resize events event though the window wasn't resized
23152
+ if (!document.all || clientWidth != docElm.clientWidth || clientHeight != docElm.clientHeight) {
23153
+ clientWidth = docElm.clientWidth;
23154
+ clientHeight = docElm.clientHeight;
23155
+ FloatPanel.hideAll();
23156
+ }
23153
23157
  };
23154
23158
 
23155
23159
  DomUtils.on(window, 'resize', windowResizeHandler);
@@ -24095,6 +24099,14 @@ define("tinymce/WindowManager", [
24095
24099
 
24096
24100
  self.windows = windows;
24097
24101
 
24102
+ editor.on('remove', function() {
24103
+ var i = windows.length;
24104
+
24105
+ while (i--) {
24106
+ windows[i].close();
24107
+ }
24108
+ });
24109
+
24098
24110
  /**
24099
24111
  * Opens a new window.
24100
24112
  *
@@ -24421,7 +24433,7 @@ define("tinymce/util/Quirks", [
24421
24433
 
24422
24434
  // Make sure all elements has a data-mce-style attribute
24423
24435
  if (!elm.hasAttribute('data-mce-style') && elm.hasAttribute('style')) {
24424
- editor.dom.setAttrib(elm, 'style', elm.getAttribute('style'));
24436
+ editor.dom.setAttrib(elm, 'style', editor.dom.getAttrib(elm, 'style'));
24425
24437
  }
24426
24438
  });
24427
24439
 
@@ -24843,35 +24855,6 @@ define("tinymce/util/Quirks", [
24843
24855
  });
24844
24856
  }
24845
24857
 
24846
- /**
24847
- * Fire a nodeChanged when the selection is changed on WebKit this fixes selection issues on iOS5. It only fires the nodeChange
24848
- * event every 50ms since it would other wise update the UI when you type and it hogs the CPU.
24849
- */
24850
- function selectionChangeNodeChanged() {
24851
- var lastRng, selectionTimer;
24852
-
24853
- editor.on('selectionchange', function() {
24854
- if (selectionTimer) {
24855
- clearTimeout(selectionTimer);
24856
- selectionTimer = 0;
24857
- }
24858
-
24859
- selectionTimer = window.setTimeout(function() {
24860
- if (editor.removed) {
24861
- return;
24862
- }
24863
-
24864
- var rng = selection.getRng();
24865
-
24866
- // Compare the ranges to see if it was a real change or not
24867
- if (!lastRng || !RangeUtils.compareRanges(rng, lastRng)) {
24868
- editor.nodeChanged();
24869
- lastRng = rng;
24870
- }
24871
- }, 50);
24872
- });
24873
- }
24874
-
24875
24858
  /**
24876
24859
  * Screen readers on IE needs to have the role application set on the body.
24877
24860
  */
@@ -25398,6 +25381,53 @@ define("tinymce/util/Quirks", [
25398
25381
  editor.contentStyles.push('.mce-content-body {-webkit-touch-callout: none}');
25399
25382
  }
25400
25383
 
25384
+ /**
25385
+ * iOS Safari and possible other browsers have a bug where it won't fire
25386
+ * a click event when a contentEditable is focused. This function fakes click events
25387
+ * by using touchstart/touchend and measuring the time and distance travelled.
25388
+ */
25389
+ function touchClickEvent() {
25390
+ editor.on('touchstart', function(e) {
25391
+ var elm, time, startTouch, changedTouches;
25392
+
25393
+ elm = e.target;
25394
+ time = new Date().getTime();
25395
+ changedTouches = e.changedTouches;
25396
+
25397
+ if (!changedTouches || changedTouches.length > 1) {
25398
+ return;
25399
+ }
25400
+
25401
+ startTouch = changedTouches[0];
25402
+
25403
+ editor.once('touchend', function(e) {
25404
+ var endTouch = e.changedTouches[0], args;
25405
+
25406
+ if (new Date().getTime() - time > 500) {
25407
+ return;
25408
+ }
25409
+
25410
+ if (Math.abs(startTouch.clientX - endTouch.clientX) > 5) {
25411
+ return;
25412
+ }
25413
+
25414
+ if (Math.abs(startTouch.clientY - endTouch.clientY) > 5) {
25415
+ return;
25416
+ }
25417
+
25418
+ args = {
25419
+ target: elm
25420
+ };
25421
+
25422
+ each('pageX pageY clientX clientY screenX screenY'.split(' '), function(key) {
25423
+ args[key] = endTouch[key];
25424
+ });
25425
+
25426
+ args = editor.fire('click', args);
25427
+ });
25428
+ });
25429
+ }
25430
+
25401
25431
  /**
25402
25432
  * WebKit has a bug where it will allow forms to be submitted if they are inside a contentEditable element.
25403
25433
  * For example this: <form><button></form>
@@ -25444,10 +25474,10 @@ define("tinymce/util/Quirks", [
25444
25474
  blockFormSubmitInsideEditor();
25445
25475
  disableBackspaceIntoATable();
25446
25476
  removeAppleInterchangeBrs();
25477
+ touchClickEvent();
25447
25478
 
25448
25479
  // iOS
25449
25480
  if (Env.iOS) {
25450
- selectionChangeNodeChanged();
25451
25481
  restoreFocusOnKeyDown();
25452
25482
  bodyHeight();
25453
25483
  tapLinksAndImages();
@@ -25649,8 +25679,18 @@ define("tinymce/EditorObservable", [
25649
25679
  "tinymce/dom/DOMUtils",
25650
25680
  "tinymce/util/Tools"
25651
25681
  ], function(Observable, DOMUtils, Tools) {
25652
- var DOM = DOMUtils.DOM;
25682
+ var DOM = DOMUtils.DOM, customEventRootDelegates;
25653
25683
 
25684
+ /**
25685
+ * Returns the event target so for the specified event. Some events fire
25686
+ * only on document, some fire on documentElement etc. This also handles the
25687
+ * custom event root setting where it returns that element instead of the body.
25688
+ *
25689
+ * @private
25690
+ * @param {tinymce.Editor} editor Editor instance to get event target from.
25691
+ * @param {String} eventName Name of the event for example "click".
25692
+ * @return {Element/Document} HTML Element or document target to bind on.
25693
+ */
25654
25694
  function getEventTarget(editor, eventName) {
25655
25695
  if (eventName == 'selectionchange') {
25656
25696
  return editor.getDoc();
@@ -25659,62 +25699,96 @@ define("tinymce/EditorObservable", [
25659
25699
  // Need to bind mousedown/mouseup etc to document not body in iframe mode
25660
25700
  // Since the user might click on the HTML element not the BODY
25661
25701
  if (!editor.inline && /^mouse|click|contextmenu|drop|dragover|dragend/.test(eventName)) {
25662
- return editor.getDoc();
25702
+ return editor.getDoc().documentElement;
25703
+ }
25704
+
25705
+ // Bind to event root instead of body if it's defined
25706
+ if (editor.settings.event_root) {
25707
+ if (!editor.eventRoot) {
25708
+ editor.eventRoot = DOM.select(editor.settings.event_root)[0];
25709
+ }
25710
+
25711
+ return editor.eventRoot;
25663
25712
  }
25664
25713
 
25665
25714
  return editor.getBody();
25666
25715
  }
25667
25716
 
25668
- function bindEventDelegate(editor, name) {
25669
- var eventRootSelector = editor.settings.event_root, editorManager = editor.editorManager;
25670
- var eventRootElm = editorManager.eventRootElm || getEventTarget(editor, name);
25717
+ /**
25718
+ * Binds a event delegate for the specified name this delegate will fire
25719
+ * the event to the editor dispatcher.
25720
+ *
25721
+ * @private
25722
+ * @param {tinymce.Editor} editor Editor instance to get event target from.
25723
+ * @param {String} eventName Name of the event for example "click".
25724
+ */
25725
+ function bindEventDelegate(editor, eventName) {
25726
+ var eventRootElm = getEventTarget(editor, eventName), delegate;
25727
+
25728
+ if (!editor.delegates) {
25729
+ editor.delegates = {};
25730
+ }
25671
25731
 
25672
- if (eventRootSelector) {
25673
- if (!editorManager.rootEvents) {
25674
- editorManager.rootEvents = {};
25732
+ if (editor.delegates[eventName]) {
25733
+ return;
25734
+ }
25675
25735
 
25676
- editorManager.on('RemoveEditor', function() {
25677
- if (!editorManager.activeEditor) {
25678
- DOM.unbind(eventRootElm);
25679
- delete editorManager.rootEvents;
25736
+ if (editor.settings.event_root) {
25737
+ if (!customEventRootDelegates) {
25738
+ customEventRootDelegates = {};
25739
+ editor.editorManager.on('removeEditor', function() {
25740
+ var name;
25741
+
25742
+ if (!editor.editorManager.activeEditor) {
25743
+ if (customEventRootDelegates) {
25744
+ for (name in customEventRootDelegates) {
25745
+ editor.dom.unbind(getEventTarget(editor, name));
25746
+ }
25747
+
25748
+ customEventRootDelegates = null;
25749
+ }
25680
25750
  }
25681
25751
  });
25682
25752
  }
25683
25753
 
25684
- if (editorManager.rootEvents[name]) {
25754
+ if (customEventRootDelegates[eventName]) {
25685
25755
  return;
25686
25756
  }
25687
25757
 
25688
- if (eventRootElm == editor.getBody()) {
25689
- eventRootElm = DOM.select(eventRootSelector)[0];
25690
- editorManager.eventRootElm = eventRootElm;
25691
- }
25692
-
25693
- editorManager.rootEvents[name] = true;
25694
-
25695
- DOM.bind(eventRootElm, name, function(e) {
25696
- var target = e.target, editors = editorManager.editors, i = editors.length;
25758
+ delegate = function(e) {
25759
+ var target = e.target, editors = editor.editorManager.editors, i = editors.length;
25697
25760
 
25698
25761
  while (i--) {
25699
25762
  var body = editors[i].getBody();
25700
25763
 
25701
25764
  if (body === target || DOM.isChildOf(target, body)) {
25702
25765
  if (!editors[i].hidden) {
25703
- editors[i].fire(name, e);
25766
+ editors[i].fire(eventName, e);
25704
25767
  }
25705
25768
  }
25706
25769
  }
25707
- });
25770
+ };
25771
+
25772
+ customEventRootDelegates[eventName] = delegate;
25773
+ DOM.bind(eventRootElm, eventName, delegate);
25708
25774
  } else {
25709
- editor.dom.bind(eventRootElm, name, function(e) {
25775
+ delegate = function(e) {
25710
25776
  if (!editor.hidden) {
25711
- editor.fire(name, e);
25777
+ editor.fire(eventName, e);
25712
25778
  }
25713
- });
25779
+ };
25780
+
25781
+ DOM.bind(eventRootElm, eventName, delegate);
25782
+ editor.delegates[eventName] = delegate;
25714
25783
  }
25715
25784
  }
25716
25785
 
25717
25786
  var EditorObservable = {
25787
+ /**
25788
+ * Bind any pending event delegates. This gets executed after the target body/document is created.
25789
+ *
25790
+ * @private
25791
+ */
25718
25792
  bindPendingEventDelegates: function() {
25719
25793
  var self = this;
25720
25794
 
@@ -25723,6 +25797,12 @@ define("tinymce/EditorObservable", [
25723
25797
  });
25724
25798
  },
25725
25799
 
25800
+ /**
25801
+ * Toggles a native event on/off this is called by the EventDispatcher when
25802
+ * the first native event handler is added and when the last native event handler is removed.
25803
+ *
25804
+ * @private
25805
+ */
25726
25806
  toggleNativeEvent: function(name, state) {
25727
25807
  var self = this;
25728
25808
 
@@ -25746,8 +25826,35 @@ define("tinymce/EditorObservable", [
25746
25826
  }
25747
25827
  }
25748
25828
  } else if (self.initialized) {
25749
- self.dom.unbind(getEventTarget(self, name), name);
25829
+ self.dom.unbind(getEventTarget(self, name), name, self.delegates[name]);
25830
+ delete self.delegates[name];
25831
+ }
25832
+ },
25833
+
25834
+ /**
25835
+ * Unbinds all native event handlers that means delegates, custom events bound using the Events API etc.
25836
+ *
25837
+ * @private
25838
+ */
25839
+ unbindAllNativeEvents: function() {
25840
+ var self = this, name;
25841
+
25842
+ if (self.delegates) {
25843
+ for (name in self.delegates) {
25844
+ self.dom.unbind(getEventTarget(self, name), name, self.delegates[name]);
25845
+ }
25846
+
25847
+ delete self.delegates;
25848
+ }
25849
+
25850
+ if (!self.inline) {
25851
+ self.getBody().onload = null;
25852
+ self.dom.unbind(self.getWin());
25853
+ self.dom.unbind(self.getDoc());
25750
25854
  }
25855
+
25856
+ self.dom.unbind(self.getBody());
25857
+ self.dom.unbind(self.getContainer());
25751
25858
  }
25752
25859
  };
25753
25860
 
@@ -26554,6 +26661,9 @@ define("tinymce/Editor", [
26554
26661
 
26555
26662
  DOM.setAttrib("src", url || 'javascript:""');
26556
26663
 
26664
+ self.contentAreaContainer = o.iframeContainer;
26665
+ self.iframeElement = ifr;
26666
+
26557
26667
  n = DOM.add(o.iframeContainer, ifr);
26558
26668
 
26559
26669
  // Try accessing the document this will fail on IE when document.domain is set to the same as location.hostname
@@ -26566,9 +26676,6 @@ define("tinymce/Editor", [
26566
26676
  }
26567
26677
  }
26568
26678
 
26569
- self.contentAreaContainer = o.iframeContainer;
26570
- self.iframeElement = ifr;
26571
-
26572
26679
  if (o.editorContainer) {
26573
26680
  DOM.get(o.editorContainer).style.display = self.orgDisplay;
26574
26681
  self.hidden = DOM.isHidden(o.editorContainer);
@@ -26879,12 +26986,15 @@ define("tinymce/Editor", [
26879
26986
  // Handle auto focus
26880
26987
  if (settings.auto_focus) {
26881
26988
  setTimeout(function() {
26882
- var ed = self.editorManager.get(settings.auto_focus);
26989
+ var editor;
26990
+
26991
+ if (settings.auto_focus === true) {
26992
+ editor = self;
26993
+ } else {
26994
+ editor = self.editorManager.get(settings.auto_focus);
26995
+ }
26883
26996
 
26884
- ed.selection.select(ed.getBody(), 1);
26885
- ed.selection.collapse(1);
26886
- ed.getBody().focus();
26887
- ed.getWin().focus();
26997
+ editor.focus();
26888
26998
  }, 100);
26889
26999
  }
26890
27000
 
@@ -27927,6 +28037,7 @@ define("tinymce/Editor", [
27927
28037
  if (!self.removed) {
27928
28038
  self.save();
27929
28039
  self.removed = 1;
28040
+ self.unbindAllNativeEvents();
27930
28041
 
27931
28042
  // Remove any hidden input
27932
28043
  if (self.hasHiddenInput) {
@@ -27942,21 +28053,12 @@ define("tinymce/Editor", [
27942
28053
 
27943
28054
  DOM.setStyle(self.id, 'display', self.orgDisplay);
27944
28055
  self.getBody().onload = null; // Prevent #6816
27945
-
27946
- // Don't clear the window or document if content editable
27947
- // is enabled since other instances might still be present
27948
- Event.unbind(self.getWin());
27949
- Event.unbind(self.getDoc());
27950
28056
  }
27951
28057
 
27952
- var elm = self.getContainer();
27953
- Event.unbind(self.getBody());
27954
- Event.unbind(elm);
27955
-
27956
28058
  self.fire('remove');
27957
28059
 
27958
28060
  self.editorManager.remove(self);
27959
- DOM.remove(elm);
28061
+ DOM.remove(self.getContainer());
27960
28062
  self.destroy();
27961
28063
  }
27962
28064
  },
@@ -27984,14 +28086,6 @@ define("tinymce/Editor", [
27984
28086
  return;
27985
28087
  }
27986
28088
 
27987
- // We must unbind on Gecko since it would otherwise produce the pesky "attempt
27988
- // to run compile-and-go script on a cleared scope" message
27989
- if (automatic && isGecko) {
27990
- Event.unbind(self.getDoc());
27991
- Event.unbind(self.getWin());
27992
- Event.unbind(self.getBody());
27993
- }
27994
-
27995
28089
  if (!automatic) {
27996
28090
  self.editorManager.off('beforeunload', self._beforeUnload);
27997
28091
 
@@ -28474,6 +28568,7 @@ define("tinymce/EditorManager", [
28474
28568
  // User has manually destroyed the editor lets clean up the mess
28475
28569
  if (editor && !(editor.getContainer() || editor.getBody()).parentNode) {
28476
28570
  removeEditorFromList(editor);
28571
+ editor.unbindAllNativeEvents();
28477
28572
  editor.destroy(true);
28478
28573
  editor = null;
28479
28574
  }
@@ -28504,7 +28599,7 @@ define("tinymce/EditorManager", [
28504
28599
  * @property minorVersion
28505
28600
  * @type String
28506
28601
  */
28507
- minorVersion: '1.2',
28602
+ minorVersion: '1.3',
28508
28603
 
28509
28604
  /**
28510
28605
  * Release date of TinyMCE build.
@@ -28512,7 +28607,7 @@ define("tinymce/EditorManager", [
28512
28607
  * @property releaseDate
28513
28608
  * @type String
28514
28609
  */
28515
- releaseDate: '2014-07-15',
28610
+ releaseDate: '2014-07-29',
28516
28611
 
28517
28612
  /**
28518
28613
  * Collection of editor instances.
@@ -29131,6 +29226,7 @@ define("tinymce/LegacyInput", [
29131
29226
  /**
29132
29227
  * This class enables you to send XMLHTTPRequests cross browser.
29133
29228
  * @class tinymce.util.XHR
29229
+ * @mixes tinymce.util.Observable
29134
29230
  * @static
29135
29231
  * @example
29136
29232
  * // Sends a low level Ajax request
@@ -29140,9 +29236,17 @@ define("tinymce/LegacyInput", [
29140
29236
  * console.debug(text);
29141
29237
  * }
29142
29238
  * });
29239
+ *
29240
+ * // Add custom header to XHR request
29241
+ * tinymce.util.XHR.on('beforeSend', function(e) {
29242
+ * e.xhr.setRequestHeader('X-Requested-With', 'Something');
29243
+ * });
29143
29244
  */
29144
- define("tinymce/util/XHR", [], function() {
29145
- return {
29245
+ define("tinymce/util/XHR", [
29246
+ "tinymce/util/Observable",
29247
+ "tinymce/util/Tools"
29248
+ ], function(Observable, Tools) {
29249
+ var XHR = {
29146
29250
  /**
29147
29251
  * Sends a XMLHTTPRequest.
29148
29252
  * Consult the Wiki for details on what settings this method takes.
@@ -29186,12 +29290,14 @@ define("tinymce/util/XHR", [], function() {
29186
29290
  if (settings.crossDomain) {
29187
29291
  xhr.withCredentials = true;
29188
29292
  }
29293
+
29189
29294
  if (settings.content_type) {
29190
29295
  xhr.setRequestHeader('Content-Type', settings.content_type);
29191
29296
  }
29192
29297
 
29193
29298
  xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
29194
29299
 
29300
+ xhr = XHR.fire('beforeSend', {xhr: xhr, settings: settings}).xhr;
29195
29301
  xhr.send(settings.data);
29196
29302
 
29197
29303
  // Syncronous request
@@ -29204,6 +29310,10 @@ define("tinymce/util/XHR", [], function() {
29204
29310
  }
29205
29311
  }
29206
29312
  };
29313
+
29314
+ Tools.extend(XHR, Observable);
29315
+
29316
+ return XHR;
29207
29317
  });
29208
29318
 
29209
29319
  // Included from: js/tinymce/classes/util/JSON.js
@@ -31070,6 +31180,15 @@ define("tinymce/ui/PanelButton", [
31070
31180
  });
31071
31181
 
31072
31182
  return self._super();
31183
+ },
31184
+
31185
+ remove: function() {
31186
+ if (this.panel) {
31187
+ this.panel.remove();
31188
+ this.panel = null;
31189
+ }
31190
+
31191
+ return this._super();
31073
31192
  }
31074
31193
  });
31075
31194
  });
@@ -32856,7 +32975,6 @@ define("tinymce/ui/FormatControls", [
32856
32975
  paste: ['Paste', 'Paste'],
32857
32976
  help: ['Help', 'mceHelp'],
32858
32977
  selectall: ['Select all', 'SelectAll'],
32859
- hr: ['Insert horizontal rule', 'InsertHorizontalRule'],
32860
32978
  removeformat: ['Clear formatting', 'RemoveFormat'],
32861
32979
  visualaid: ['Visual aids', 'mceToggleVisualAid'],
32862
32980
  newdocument: ['New document', 'mceNewDocument']