tinymce-rails 4.1.2 → 4.1.3

Sign up to get free protection for your applications and to get access to all the features.
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']