app/assets/source/tinymce/tinymce.jquery.js in tinymce-rails-4.0.18 vs app/assets/source/tinymce/tinymce.jquery.js in tinymce-rails-4.0.19
- old
+ new
@@ -1,6 +1,6 @@
-// 4.0.18 (2014-02-27)
+// 4.0.19 (2014-03-11)
/**
* Compiled inline version. (Library mode)
*/
@@ -139,10 +139,11 @@
* @version 3.4
*/
define("tinymce/html/Styles", [], function() {
return function(settings, schema) {
/*jshint maxlen:255 */
+ /*eslint max-len:0 */
var rgbRegExp = /rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)/gi,
urlOrStrRegExp = /(?:url(?:(?:\(\s*\"([^\"]+)\"\s*\))|(?:\(\s*\'([^\']+)\'\s*\))|(?:\(\s*([^)\s]+)\s*\))))|(?:\'([^\']+)\')|(?:\"([^\"]+)\")/gi,
styleRegExp = /\s*([^:]+):\s*([^;]+);?/g,
trimRightRegExp = /\s+$/,
undef, i, encodingLookup = {}, encodingItems, invisibleChar = '\uFEFF';
@@ -445,10 +446,11 @@
* License: http://www.tinymce.com/license
* Contributing: http://www.tinymce.com/contributing
*/
/*jshint loopfunc:true*/
+/*eslint no-loop-func:0 */
define("tinymce/dom/EventUtils", [], function() {
"use strict";
var eventExpandoPrefix = "mce-data-";
@@ -1097,13 +1099,14 @@
* @method trim
* @param {String} s String to remove whitespace from.
* @return {String} New string with removed whitespace.
*/
var whiteSpaceRegExp = /^\s*|\s*$/g;
- var trim = function(str) {
+
+ function trim(str) {
return (str === null || str === undefined) ? '' : ("" + str).replace(whiteSpaceRegExp, '');
- };
+ }
/**
* Returns true/false if the object is an array or not.
*
* @method isArray
@@ -1209,11 +1212,11 @@
s = s || o;
if (o.length !== undefined) {
// Indexed arrays, needed for Safari
- for (n=0, l = o.length; n < l; n++) {
+ for (n = 0, l = o.length; n < l; n++) {
if (cb.call(s, o[n], n, o) === false) {
return 0;
}
}
} else {
@@ -1318,18 +1321,18 @@
* // Some method
* }
* });
*/
function create(s, p, root) {
- var t = this, sp, ns, cn, scn, c, de = 0;
+ var self = this, sp, ns, cn, scn, c, de = 0;
// Parse : <prefix> <class>:<super class>
s = /^((static) )?([\w.]+)(:([\w.]+))?/.exec(s);
cn = s[3].match(/(^|\.)(\w+)$/i)[2]; // Class name
// Create namespace for new class
- ns = t.createNS(s[3].replace(/\.\w+$/, ''), root);
+ ns = self.createNS(s[3].replace(/\.\w+$/, ''), root);
// Class already exists
if (ns[cn]) {
return;
}
@@ -1351,15 +1354,15 @@
de = 1;
}
// Add constructor and methods
ns[cn] = p[cn];
- t.extend(ns[cn].prototype, p);
+ self.extend(ns[cn].prototype, p);
// Extend
if (s[5]) {
- sp = t.resolve(s[5]).prototype;
+ sp = self.resolve(s[5]).prototype;
scn = s[5].match(/\.(\w+)$/i)[1]; // Class name
// Extend constructor
c = ns[cn];
if (de) {
@@ -1375,16 +1378,16 @@
};
}
ns[cn].prototype[cn] = ns[cn];
// Add super methods
- t.each(sp, function(f, n) {
+ self.each(sp, function(f, n) {
ns[cn].prototype[n] = sp[n];
});
// Add overridden methods
- t.each(p, function(f, n) {
+ self.each(p, function(f, n) {
// Extend methods if needed
if (sp[n]) {
ns[cn].prototype[n] = function() {
this.parent = sp[n];
return f.apply(this, arguments);
@@ -1397,11 +1400,11 @@
});
}
// Add static methods
/*jshint sub:true*/
- t.each(p['static'], function(f, n) {
+ self.each(p['static'], function(f, n) {
ns[cn][n] = f;
});
}
/**
@@ -1497,11 +1500,11 @@
var i, v;
o = o || window;
n = n.split('.');
- for (i=0; i<n.length; i++) {
+ for (i = 0; i < n.length; i++) {
v = n[i];
if (!o[v]) {
o[v] = {};
}
@@ -1592,11 +1595,11 @@
define("tinymce/dom/Range", [
"tinymce/util/Tools"
], function(Tools) {
// Range constructor
function Range(dom) {
- var t = this,
+ var self = this,
doc = dom.doc,
EXTRACT = 0,
CLONE = 1,
DELETE = 2,
TRUE = true,
@@ -1636,18 +1639,18 @@
setEnd(n.parentNode, nodeIndex(n) + 1);
}
function collapse(ts) {
if (ts) {
- t[END_CONTAINER] = t[START_CONTAINER];
- t[END_OFFSET] = t[START_OFFSET];
+ self[END_CONTAINER] = self[START_CONTAINER];
+ self[END_OFFSET] = self[START_OFFSET];
} else {
- t[START_CONTAINER] = t[END_CONTAINER];
- t[START_OFFSET] = t[END_OFFSET];
+ self[START_CONTAINER] = self[END_CONTAINER];
+ self[START_OFFSET] = self[END_OFFSET];
}
- t.collapsed = TRUE;
+ self.collapsed = TRUE;
}
function selectNode(n) {
setStartBefore(n);
setEndAfter(n);
@@ -1657,11 +1660,11 @@
setStart(n, 0);
setEnd(n, n.nodeType === 1 ? n.childNodes.length : n.nodeValue.length);
}
function compareBoundaryPoints(h, r) {
- var sc = t[START_CONTAINER], so = t[START_OFFSET], ec = t[END_CONTAINER], eo = t[END_OFFSET],
+ var sc = self[START_CONTAINER], so = self[START_OFFSET], ec = self[END_CONTAINER], eo = self[END_OFFSET],
rsc = r.startContainer, rso = r.startOffset, rec = r.endContainer, reo = r.endOffset;
// Check START_TO_START
if (h === 0) {
return _compareBoundaryPoints(sc, so, rsc, rso);
@@ -1729,25 +1732,25 @@
}
}
}
function surroundContents(n) {
- var f = t.extractContents();
+ var f = self.extractContents();
- t.insertNode(n);
+ self.insertNode(n);
n.appendChild(f);
- t.selectNode(n);
+ self.selectNode(n);
}
function cloneRange() {
return extend(new Range(dom), {
- startContainer: t[START_CONTAINER],
- startOffset: t[START_OFFSET],
- endContainer: t[END_CONTAINER],
- endOffset: t[END_OFFSET],
- collapsed: t.collapsed,
- commonAncestorContainer: t.commonAncestorContainer
+ startContainer: self[START_CONTAINER],
+ startOffset: self[START_OFFSET],
+ endContainer: self[END_CONTAINER],
+ endOffset: self[END_OFFSET],
+ collapsed: self.collapsed,
+ commonAncestorContainer: self.commonAncestorContainer
});
}
// Private methods
@@ -1774,11 +1777,11 @@
return container;
}
function _isCollapsed() {
- return (t[START_CONTAINER] == t[END_CONTAINER] && t[START_OFFSET] == t[END_OFFSET]);
+ return (self[START_CONTAINER] == self[END_CONTAINER] && self[START_OFFSET] == self[END_OFFSET]);
}
function _compareBoundaryPoints(containerA, offsetA, containerB, offsetB) {
var c, offsetC, n, cmnRoot, childA, childB;
@@ -1890,79 +1893,79 @@
function _setEndPoint(st, n, o) {
var ec, sc;
if (st) {
- t[START_CONTAINER] = n;
- t[START_OFFSET] = o;
+ self[START_CONTAINER] = n;
+ self[START_OFFSET] = o;
} else {
- t[END_CONTAINER] = n;
- t[END_OFFSET] = o;
+ self[END_CONTAINER] = n;
+ self[END_OFFSET] = o;
}
// If one boundary-point of a Range is set to have a root container
// other than the current one for the Range, the Range is collapsed to
// the new position. This enforces the restriction that both boundary-
// points of a Range must have the same root container.
- ec = t[END_CONTAINER];
+ ec = self[END_CONTAINER];
while (ec.parentNode) {
ec = ec.parentNode;
}
- sc = t[START_CONTAINER];
+ sc = self[START_CONTAINER];
while (sc.parentNode) {
sc = sc.parentNode;
}
if (sc == ec) {
// The start position of a Range is guaranteed to never be after the
// end position. To enforce this restriction, if the start is set to
// be at a position after the end, the Range is collapsed to that
// position.
- if (_compareBoundaryPoints(t[START_CONTAINER], t[START_OFFSET], t[END_CONTAINER], t[END_OFFSET]) > 0) {
- t.collapse(st);
+ if (_compareBoundaryPoints(self[START_CONTAINER], self[START_OFFSET], self[END_CONTAINER], self[END_OFFSET]) > 0) {
+ self.collapse(st);
}
} else {
- t.collapse(st);
+ self.collapse(st);
}
- t.collapsed = _isCollapsed();
- t.commonAncestorContainer = dom.findCommonAncestor(t[START_CONTAINER], t[END_CONTAINER]);
+ self.collapsed = _isCollapsed();
+ self.commonAncestorContainer = dom.findCommonAncestor(self[START_CONTAINER], self[END_CONTAINER]);
}
function _traverse(how) {
var c, endContainerDepth = 0, startContainerDepth = 0, p, depthDiff, startNode, endNode, sp, ep;
- if (t[START_CONTAINER] == t[END_CONTAINER]) {
+ if (self[START_CONTAINER] == self[END_CONTAINER]) {
return _traverseSameContainer(how);
}
- for (c = t[END_CONTAINER], p = c.parentNode; p; c = p, p = p.parentNode) {
- if (p == t[START_CONTAINER]) {
+ for (c = self[END_CONTAINER], p = c.parentNode; p; c = p, p = p.parentNode) {
+ if (p == self[START_CONTAINER]) {
return _traverseCommonStartContainer(c, how);
}
++endContainerDepth;
}
- for (c = t[START_CONTAINER], p = c.parentNode; p; c = p, p = p.parentNode) {
- if (p == t[END_CONTAINER]) {
+ for (c = self[START_CONTAINER], p = c.parentNode; p; c = p, p = p.parentNode) {
+ if (p == self[END_CONTAINER]) {
return _traverseCommonEndContainer(c, how);
}
++startContainerDepth;
}
depthDiff = startContainerDepth - endContainerDepth;
- startNode = t[START_CONTAINER];
+ startNode = self[START_CONTAINER];
while (depthDiff > 0) {
startNode = startNode.parentNode;
depthDiff--;
}
- endNode = t[END_CONTAINER];
+ endNode = self[END_CONTAINER];
while (depthDiff < 0) {
endNode = endNode.parentNode;
depthDiff++;
}
@@ -1981,34 +1984,34 @@
if (how != DELETE) {
frag = createDocumentFragment();
}
// If selection is empty, just return the fragment
- if (t[START_OFFSET] == t[END_OFFSET]) {
+ if (self[START_OFFSET] == self[END_OFFSET]) {
return frag;
}
// Text node needs special case handling
- if (t[START_CONTAINER].nodeType == 3 /* TEXT_NODE */) {
+ if (self[START_CONTAINER].nodeType == 3 /* TEXT_NODE */) {
// get the substring
- s = t[START_CONTAINER].nodeValue;
- sub = s.substring(t[START_OFFSET], t[END_OFFSET]);
+ s = self[START_CONTAINER].nodeValue;
+ sub = s.substring(self[START_OFFSET], self[END_OFFSET]);
// set the original text node to its new value
if (how != CLONE) {
- n = t[START_CONTAINER];
- start = t[START_OFFSET];
- len = t[END_OFFSET] - t[START_OFFSET];
+ n = self[START_CONTAINER];
+ start = self[START_OFFSET];
+ len = self[END_OFFSET] - self[START_OFFSET];
if (start === 0 && len >= n.nodeValue.length - 1) {
n.parentNode.removeChild(n);
} else {
n.deleteData(start, len);
}
// Nothing is partially selected, so collapse to start point
- t.collapse(TRUE);
+ self.collapse(TRUE);
}
if (how == DELETE) {
return;
}
@@ -2019,12 +2022,12 @@
return frag;
}
// Copy nodes between the start/end offsets.
- n = _getSelectedNode(t[START_CONTAINER], t[START_OFFSET]);
- cnt = t[END_OFFSET] - t[START_OFFSET];
+ n = _getSelectedNode(self[START_CONTAINER], self[START_OFFSET]);
+ cnt = self[END_OFFSET] - self[START_OFFSET];
while (n && cnt > 0) {
sibling = n.nextSibling;
xferNode = _traverseFullySelected(n, how);
@@ -2036,11 +2039,11 @@
n = sibling;
}
// Nothing is partially selected, so collapse to start point
if (how != CLONE) {
- t.collapse(TRUE);
+ self.collapse(TRUE);
}
return frag;
}
@@ -2056,18 +2059,18 @@
if (frag) {
frag.appendChild(n);
}
endIdx = nodeIndex(endAncestor);
- cnt = endIdx - t[START_OFFSET];
+ cnt = endIdx - self[START_OFFSET];
if (cnt <= 0) {
// Collapse to just before the endAncestor, which
// is partially selected.
if (how != CLONE) {
- t.setEndBefore(endAncestor);
- t.collapse(FALSE);
+ self.setEndBefore(endAncestor);
+ self.collapse(FALSE);
}
return frag;
}
@@ -2085,12 +2088,12 @@
}
// Collapse to just before the endAncestor, which
// is partially selected.
if (how != CLONE) {
- t.setEndBefore(endAncestor);
- t.collapse(FALSE);
+ self.setEndBefore(endAncestor);
+ self.collapse(FALSE);
}
return frag;
}
@@ -2107,11 +2110,11 @@
}
startIdx = nodeIndex(startAncestor);
++startIdx; // Because we already traversed it
- cnt = t[END_OFFSET] - startIdx;
+ cnt = self[END_OFFSET] - startIdx;
n = startAncestor.nextSibling;
while (n && cnt > 0) {
sibling = n.nextSibling;
xferNode = _traverseFullySelected(n, how);
@@ -2122,30 +2125,29 @@
--cnt;
n = sibling;
}
if (how != CLONE) {
- t.setStartAfter(startAncestor);
- t.collapse(TRUE);
+ self.setStartAfter(startAncestor);
+ self.collapse(TRUE);
}
return frag;
}
function _traverseCommonAncestors(startAncestor, endAncestor, how) {
- var n, frag, commonParent, startOffset, endOffset, cnt, sibling, nextSibling;
+ var n, frag, startOffset, endOffset, cnt, sibling, nextSibling;
if (how != DELETE) {
frag = createDocumentFragment();
}
n = _traverseLeftBoundary(startAncestor, how);
if (frag) {
frag.appendChild(n);
}
- commonParent = startAncestor.parentNode;
startOffset = nodeIndex(startAncestor);
endOffset = nodeIndex(endAncestor);
++startOffset;
cnt = endOffset - startOffset;
@@ -2168,20 +2170,20 @@
if (frag) {
frag.appendChild(n);
}
if (how != CLONE) {
- t.setStartAfter(startAncestor);
- t.collapse(TRUE);
+ self.setStartAfter(startAncestor);
+ self.collapse(TRUE);
}
return frag;
}
function _traverseRightBoundary(root, how) {
- var next = _getSelectedNode(t[END_CONTAINER], t[END_OFFSET] - 1), parent, clonedParent;
- var prevSibling, clonedChild, clonedGrandParent, isFullySelected = next != t[END_CONTAINER];
+ var next = _getSelectedNode(self[END_CONTAINER], self[END_OFFSET] - 1), parent, clonedParent;
+ var prevSibling, clonedChild, clonedGrandParent, isFullySelected = next != self[END_CONTAINER];
if (next == root) {
return _traverseNode(next, isFullySelected, FALSE, how);
}
@@ -2217,11 +2219,11 @@
clonedParent = clonedGrandParent;
}
}
function _traverseLeftBoundary(root, how) {
- var next = _getSelectedNode(t[START_CONTAINER], t[START_OFFSET]), isFullySelected = next != t[START_CONTAINER];
+ var next = _getSelectedNode(self[START_CONTAINER], self[START_OFFSET]), isFullySelected = next != self[START_CONTAINER];
var parent, clonedParent, nextSibling, clonedChild, clonedGrandParent;
if (next == root) {
return _traverseNode(next, isFullySelected, TRUE, how);
}
@@ -2268,15 +2270,15 @@
if (n.nodeType == 3 /* TEXT_NODE */) {
txtValue = n.nodeValue;
if (isLeft) {
- offset = t[START_OFFSET];
+ offset = self[START_OFFSET];
newNodeValue = txtValue.substring(offset);
oldNodeValue = txtValue.substring(0, offset);
} else {
- offset = t[END_OFFSET];
+ offset = self[END_OFFSET];
newNodeValue = txtValue.substring(0, offset);
oldNodeValue = txtValue.substring(offset);
}
if (how != CLONE) {
@@ -2310,11 +2312,11 @@
function toStringIE() {
return dom.create('body', null, cloneContents()).outerText;
}
- extend(t, {
+ extend(self, {
// Inital states
startContainer: doc,
startOffset: 0,
endContainer: doc,
endOffset: 0,
@@ -2345,11 +2347,11 @@
surroundContents: surroundContents,
cloneRange: cloneRange,
toStringIE: toStringIE
});
- return t;
+ return self;
}
// Older IE versions doesn't let you override toString by it's constructor so we have to stick it in the prototype
Range.prototype.toString = function() {
return this.toStringIE();
@@ -2369,10 +2371,11 @@
* License: http://www.tinymce.com/license
* Contributing: http://www.tinymce.com/contributing
*/
/*jshint bitwise:false */
+/*eslint no-bitwise:0 */
/**
* Entity encoder class.
*
* @class tinymce.html.Entities
@@ -2761,194 +2764,194 @@
};
});
// Included from: js/tinymce/classes/dom/StyleSheetLoader.js
-/**
- * StyleSheetLoader.js
- *
- * Copyright, Moxiecode Systems AB
- * Released under LGPL License.
- *
- * License: http://www.tinymce.com/license
- * Contributing: http://www.tinymce.com/contributing
- */
-
-/**
- * This class handles loading of external stylesheets and fires events when these are loaded.
- *
- * @class tinymce.dom.StyleSheetLoader
- * @private
- */
-define("tinymce/dom/StyleSheetLoader", [], function() {
- "use strict";
-
- return function(document, settings) {
- var idCount = 0, loadedStates = {}, maxLoadTime;
-
- settings = settings || {};
- maxLoadTime = settings.maxLoadTime || 5000;
-
- function appendToHead(node) {
- document.getElementsByTagName('head')[0].appendChild(node);
- }
-
- /**
- * Loads the specified css style sheet file and call the loadedCallback once it's finished loading.
- *
- * @method load
- * @param {String} url Url to be loaded.
- * @param {Function} loadedCallback Callback to be executed when loaded.
- * @param {Function} errorCallback Callback to be executed when failed loading.
- */
- function load(url, loadedCallback, errorCallback) {
- var link, style, startTime, state;
-
- function passed() {
- var callbacks = state.passed, i = callbacks.length;
-
- while (i--) {
- callbacks[i]();
- }
-
- state.status = 2;
- state.passed = [];
- state.failed = [];
- }
-
- function failed() {
- var callbacks = state.failed, i = callbacks.length;
-
- while (i--) {
- callbacks[i]();
- }
-
- state.status = 3;
- state.passed = [];
- state.failed = [];
- }
-
- // Sniffs for older WebKit versions that have the link.onload but a broken one
- function isOldWebKit() {
- var webKitChunks = navigator.userAgent.match(/WebKit\/(\d*)/);
- return !!(webKitChunks && webKitChunks[1] < 536);
- }
-
- // Calls the waitCallback until the test returns true or the timeout occurs
- function wait(testCallback, waitCallback) {
- if (!testCallback()) {
- // Wait for timeout
- if ((new Date().getTime()) - startTime < maxLoadTime) {
- window.setTimeout(waitCallback, 0);
- } else {
- failed();
- }
- }
- }
-
- // Workaround for WebKit that doesn't properly support the onload event for link elements
- // Or WebKit that fires the onload event before the StyleSheet is added to the document
- function waitForWebKitLinkLoaded() {
- wait(function() {
- var styleSheets = document.styleSheets, styleSheet, i = styleSheets.length, owner;
-
- while (i--) {
- styleSheet = styleSheets[i];
- owner = styleSheet.ownerNode ? styleSheet.ownerNode : styleSheet.owningElement;
- if (owner && owner.id === link.id) {
- passed();
- return true;
- }
- }
- }, waitForWebKitLinkLoaded);
- }
-
- // Workaround for older Geckos that doesn't have any onload event for StyleSheets
- function waitForGeckoLinkLoaded() {
- wait(function() {
- try {
- // Accessing the cssRules will throw an exception until the CSS file is loaded
- var cssRules = style.sheet.cssRules;
- passed();
- return !!cssRules;
- } catch (ex) {
- // Ignore
- }
- }, waitForGeckoLinkLoaded);
- }
-
- if (!loadedStates[url]) {
- state = {
- passed: [],
- failed: []
- };
-
- loadedStates[url] = state;
- } else {
- state = loadedStates[url];
- }
-
- if (loadedCallback) {
- state.passed.push(loadedCallback);
- }
-
- if (errorCallback) {
- state.failed.push(errorCallback);
- }
-
- // Is loading wait for it to pass
- if (state.status == 1) {
- return;
- }
-
- // Has finished loading and was success
- if (state.status == 2) {
- passed();
- return;
- }
-
- // Has finished loading and was a failure
- if (state.status == 3) {
- failed();
- return;
- }
-
- // Start loading
- state.status = 1;
- link = document.createElement('link');
- link.rel = 'stylesheet';
- link.type = 'text/css';
- link.id = 'u' + (idCount++);
- link.async = false;
- link.defer = false;
- startTime = new Date().getTime();
-
- // Feature detect onload on link element and sniff older webkits since it has an broken onload event
- if ("onload" in link && !isOldWebKit()) {
- link.onload = waitForWebKitLinkLoaded;
- link.onerror = failed;
- } else {
- // Sniff for old Firefox that doesn't support the onload event on link elements
- // TODO: Remove this in the future when everyone uses modern browsers
- if (navigator.userAgent.indexOf("Firefox") > 0) {
- style = document.createElement('style');
- style.textContent = '@import "' + url + '"';
- waitForGeckoLinkLoaded();
- appendToHead(style);
- return;
- } else {
- // Use the id owner on older webkits
- waitForWebKitLinkLoaded();
- }
- }
-
- appendToHead(link);
- link.href = url;
- }
-
- this.load = load;
- };
+/**
+ * StyleSheetLoader.js
+ *
+ * Copyright, Moxiecode Systems AB
+ * Released under LGPL License.
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
+
+/**
+ * This class handles loading of external stylesheets and fires events when these are loaded.
+ *
+ * @class tinymce.dom.StyleSheetLoader
+ * @private
+ */
+define("tinymce/dom/StyleSheetLoader", [], function() {
+ "use strict";
+
+ return function(document, settings) {
+ var idCount = 0, loadedStates = {}, maxLoadTime;
+
+ settings = settings || {};
+ maxLoadTime = settings.maxLoadTime || 5000;
+
+ function appendToHead(node) {
+ document.getElementsByTagName('head')[0].appendChild(node);
+ }
+
+ /**
+ * Loads the specified css style sheet file and call the loadedCallback once it's finished loading.
+ *
+ * @method load
+ * @param {String} url Url to be loaded.
+ * @param {Function} loadedCallback Callback to be executed when loaded.
+ * @param {Function} errorCallback Callback to be executed when failed loading.
+ */
+ function load(url, loadedCallback, errorCallback) {
+ var link, style, startTime, state;
+
+ function passed() {
+ var callbacks = state.passed, i = callbacks.length;
+
+ while (i--) {
+ callbacks[i]();
+ }
+
+ state.status = 2;
+ state.passed = [];
+ state.failed = [];
+ }
+
+ function failed() {
+ var callbacks = state.failed, i = callbacks.length;
+
+ while (i--) {
+ callbacks[i]();
+ }
+
+ state.status = 3;
+ state.passed = [];
+ state.failed = [];
+ }
+
+ // Sniffs for older WebKit versions that have the link.onload but a broken one
+ function isOldWebKit() {
+ var webKitChunks = navigator.userAgent.match(/WebKit\/(\d*)/);
+ return !!(webKitChunks && webKitChunks[1] < 536);
+ }
+
+ // Calls the waitCallback until the test returns true or the timeout occurs
+ function wait(testCallback, waitCallback) {
+ if (!testCallback()) {
+ // Wait for timeout
+ if ((new Date().getTime()) - startTime < maxLoadTime) {
+ window.setTimeout(waitCallback, 0);
+ } else {
+ failed();
+ }
+ }
+ }
+
+ // Workaround for WebKit that doesn't properly support the onload event for link elements
+ // Or WebKit that fires the onload event before the StyleSheet is added to the document
+ function waitForWebKitLinkLoaded() {
+ wait(function() {
+ var styleSheets = document.styleSheets, styleSheet, i = styleSheets.length, owner;
+
+ while (i--) {
+ styleSheet = styleSheets[i];
+ owner = styleSheet.ownerNode ? styleSheet.ownerNode : styleSheet.owningElement;
+ if (owner && owner.id === link.id) {
+ passed();
+ return true;
+ }
+ }
+ }, waitForWebKitLinkLoaded);
+ }
+
+ // Workaround for older Geckos that doesn't have any onload event for StyleSheets
+ function waitForGeckoLinkLoaded() {
+ wait(function() {
+ try {
+ // Accessing the cssRules will throw an exception until the CSS file is loaded
+ var cssRules = style.sheet.cssRules;
+ passed();
+ return !!cssRules;
+ } catch (ex) {
+ // Ignore
+ }
+ }, waitForGeckoLinkLoaded);
+ }
+
+ if (!loadedStates[url]) {
+ state = {
+ passed: [],
+ failed: []
+ };
+
+ loadedStates[url] = state;
+ } else {
+ state = loadedStates[url];
+ }
+
+ if (loadedCallback) {
+ state.passed.push(loadedCallback);
+ }
+
+ if (errorCallback) {
+ state.failed.push(errorCallback);
+ }
+
+ // Is loading wait for it to pass
+ if (state.status == 1) {
+ return;
+ }
+
+ // Has finished loading and was success
+ if (state.status == 2) {
+ passed();
+ return;
+ }
+
+ // Has finished loading and was a failure
+ if (state.status == 3) {
+ failed();
+ return;
+ }
+
+ // Start loading
+ state.status = 1;
+ link = document.createElement('link');
+ link.rel = 'stylesheet';
+ link.type = 'text/css';
+ link.id = 'u' + (idCount++);
+ link.async = false;
+ link.defer = false;
+ startTime = new Date().getTime();
+
+ // Feature detect onload on link element and sniff older webkits since it has an broken onload event
+ if ("onload" in link && !isOldWebKit()) {
+ link.onload = waitForWebKitLinkLoaded;
+ link.onerror = failed;
+ } else {
+ // Sniff for old Firefox that doesn't support the onload event on link elements
+ // TODO: Remove this in the future when everyone uses modern browsers
+ if (navigator.userAgent.indexOf("Firefox") > 0) {
+ style = document.createElement('style');
+ style.textContent = '@import "' + url + '"';
+ waitForGeckoLinkLoaded();
+ appendToHead(style);
+ return;
+ } else {
+ // Use the id owner on older webkits
+ waitForWebKitLinkLoaded();
+ }
+ }
+
+ appendToHead(link);
+ link.href = url;
+ }
+
+ this.load = load;
+ };
});
// Included from: js/tinymce/classes/dom/DOMUtils.js
/**
@@ -3697,26 +3700,26 @@
*
* // Sets class attribute on a specific element in the current page
* tinymce.dom.setAttrib('mydiv', 'class', 'myclass');
*/
setAttrib: function(e, n, v) {
- var t = this;
+ var self = this;
// What's the point
if (!e || !n) {
return;
}
return this.run(e, function(e) {
- var s = t.settings;
+ var s = self.settings;
var originalValue = e.getAttribute(n);
if (v !== null) {
switch (n) {
case "style":
if (!is(v, 'string')) {
each(v, function(v, n) {
- t.setStyle(e, n, v);
+ self.setStyle(e, n, v);
});
return;
}
@@ -3738,14 +3741,14 @@
case "src":
case "href":
if (s.keep_values) {
if (s.url_converter) {
- v = s.url_converter.call(s.url_converter_scope || t, v, n, e);
+ v = s.url_converter.call(s.url_converter_scope || self, v, n, e);
}
- t.setAttrib(e, 'data-mce-' + n, v, 2);
+ self.setAttrib(e, 'data-mce-' + n, v, 2);
}
break;
case "shape":
@@ -4310,11 +4313,11 @@
// Create new div with HTML contents and a BR in front to keep comments
var newElement = self.create('div');
newElement.innerHTML = '<br />' + html;
// Add all children from div to target
- each (grep(newElement.childNodes), function(node, i) {
+ each(grep(newElement.childNodes), function(node, i) {
// Skip br element
if (i && element.canHaveHTML) {
element.appendChild(node);
}
});
@@ -4722,14 +4725,14 @@
* @param {Node} node Node to look for.
* @param {boolean} normalized Optional true/false state if the index is what it would be after a normalization.
* @return {Number} Index of the specified node.
*/
nodeIndex: function(node, normalized) {
- var idx = 0, lastNodeType, lastNode, nodeType;
+ var idx = 0, lastNodeType, nodeType;
if (node) {
- for (lastNodeType = node.nodeType, node = node.previousSibling, lastNode = node; node; node = node.previousSibling) {
+ for (lastNodeType = node.nodeType, node = node.previousSibling; node; node = node.previousSibling) {
nodeType = node.nodeType;
// Normalize text nodes
if (normalized && nodeType == 3) {
if (nodeType == lastNodeType || !node.nodeValue.length) {
@@ -5107,10 +5110,12 @@
callback();
}
function error() {
+ /*eslint no-console:0 */
+
// Report the error so it's easier for people to spot loading errors
if (typeof(console) !== "undefined" && console.log) {
console.log("Failed to load: " + url);
}
@@ -5419,63 +5424,63 @@
/**
* Loads an add-on from a specific url.
*
* @method load
- * @param {String} n Short name of the add-on that gets loaded.
- * @param {String} u URL to the add-on that will get loaded.
- * @param {function} cb Optional callback to execute ones the add-on is loaded.
- * @param {Object} s Optional scope to execute the callback in.
+ * @param {String} name Short name of the add-on that gets loaded.
+ * @param {String} addOnUrl URL to the add-on that will get loaded.
+ * @param {function} callback Optional callback to execute ones the add-on is loaded.
+ * @param {Object} scope Optional scope to execute the callback in.
* @example
* // Loads a plugin from an external URL
* tinymce.PluginManager.load('myplugin', '/some/dir/someplugin/plugin.js');
*
* // Initialize TinyMCE
* tinymce.init({
* ...
* plugins: '-myplugin' // Don't try to load it again
* });
*/
- load: function(n, u, cb, s) {
- var t = this, url = u;
+ load: function(name, addOnUrl, callback, scope) {
+ var self = this, url = addOnUrl;
function loadDependencies() {
- var dependencies = t.dependencies(n);
+ var dependencies = self.dependencies(name);
each(dependencies, function(dep) {
- var newUrl = t.createUrl(u, dep);
+ var newUrl = self.createUrl(addOnUrl, dep);
- t.load(newUrl.resource, newUrl, undefined, undefined);
+ self.load(newUrl.resource, newUrl, undefined, undefined);
});
- if (cb) {
- if (s) {
- cb.call(s);
+ if (callback) {
+ if (scope) {
+ callback.call(scope);
} else {
- cb.call(ScriptLoader);
+ callback.call(ScriptLoader);
}
}
}
- if (t.urls[n]) {
+ if (self.urls[name]) {
return;
}
- if (typeof u === "object") {
- url = u.prefix + u.resource + u.suffix;
+ if (typeof addOnUrl === "object") {
+ url = addOnUrl.prefix + addOnUrl.resource + addOnUrl.suffix;
}
if (url.indexOf('/') !== 0 && url.indexOf('://') == -1) {
url = AddOnManager.baseURL + '/' + url;
}
- t.urls[n] = url.substring(0, url.lastIndexOf('/'));
+ self.urls[name] = url.substring(0, url.lastIndexOf('/'));
- if (t.lookup[n]) {
+ if (self.lookup[name]) {
loadDependencies();
} else {
- ScriptLoader.ScriptLoader.add(url, loadDependencies, s);
+ ScriptLoader.ScriptLoader.add(url, loadDependencies, scope);
}
}
};
AddOnManager.PluginManager = new AddOnManager();
@@ -6085,11 +6090,11 @@
* @private
* @param {String} type html4, html5 or html5-strict schema type.
* @return {Object} Schema lookup table.
*/
function compileSchema(type) {
- var schema = {}, globalAttributes, eventAttributes, blockContent;
+ var schema = {}, globalAttributes, blockContent;
var phrasingContent, flowContent, html4BlockContent, html4PhrasingContent;
function add(name, attributes, children) {
var ni, i, attributesOrder, args = arguments;
@@ -6153,17 +6158,17 @@
// Attributes present on all elements
globalAttributes = split("id accesskey class dir lang style tabindex title");
// Event attributes can be opt-in/opt-out
- eventAttributes = split("onabort onblur oncancel oncanplay oncanplaythrough onchange onclick onclose oncontextmenu oncuechange " +
+ /*eventAttributes = split("onabort onblur oncancel oncanplay oncanplaythrough onchange onclick onclose oncontextmenu oncuechange " +
"ondblclick ondrag ondragend ondragenter ondragleave ondragover ondragstart ondrop ondurationchange onemptied onended " +
"onerror onfocus oninput oninvalid onkeydown onkeypress onkeyup onload onloadeddata onloadedmetadata onloadstart " +
"onmousedown onmousemove onmouseout onmouseover onmouseup onmousewheel onpause onplay onplaying onprogress onratechange " +
"onreset onscroll onseeked onseeking onseeking onselect onshow onstalled onsubmit onsuspend ontimeupdate onvolumechange " +
"onwaiting"
- );
+ );*/
// Block content elements
blockContent = split(
"address blockquote div dl fieldset form h1 h2 h3 h4 h5 h6 hr menu ol p pre table ul"
);
@@ -6986,10 +6991,12 @@
*
* License: http://www.tinymce.com/license
* Contributing: http://www.tinymce.com/contributing
*/
+/*eslint max-depth:[2, 9] */
+
/**
* This class parses HTML code using pure JavaScript and executes various events for each item it finds. It will
* always execute the events in the right order for tag soup code like <b><p></b></p>. It will also remove elements
* and attributes that doesn't fit the schema if the validate setting is enabled.
*
@@ -7042,12 +7049,14 @@
* @method SaxParser
* @param {Object} settings Name/value collection of settings. comment, cdata, text, start and end are callbacks.
* @param {tinymce.html.Schema} schema HTML Schema class to use when parsing.
*/
return function(settings, schema) {
- var self = this, noop = function() {};
+ var self = this;
+ function noop() {}
+
settings = settings || {};
self.schema = schema = schema || new Schema();
if (settings.fix_self_closing !== false) {
settings.fix_self_closing = true;
@@ -8650,10 +8659,11 @@
htmlParser.addNodeFilter('script,style', function(nodes, name) {
var i = nodes.length, node, value;
function trim(value) {
/*jshint maxlen:255 */
+ /*eslint max-len:0 */
return value.replace(/(<!--\[CDATA\[|\]\]-->)/g, '\n')
.replace(/^[\r\n]*|[\r\n]*$/g, '')
.replace(/^\s*((<!--)?(\s*\/\/)?\s*<!\[CDATA\[|(<!--\s*)?\/\*\s*<!\[CDATA\[\s*\*\/|(\/\/)?\s*<!--|\/\*\s*<!--\s*\*\/)\s*[\r\n]*/gi, '')
.replace(/\s*(\/\*\s*\]\]>\s*\*\/(-->)?|\s*\/\/\s*\]\]>(-->)?|\/\/\s*(-->)?|\]\]>|\/\*\s*-->\s*\*\/|\s*-->\s*)\s*$/g, '');
}
@@ -9521,23 +9531,25 @@
'z-index: 10000' +
'}'
);
function isResizable(elm) {
- if (editor.settings.object_resizing === false) {
+ var selector = editor.settings.object_resizing;
+
+ if (selector === false || Env.iOS) {
return false;
}
- if (!/TABLE|IMG|DIV/.test(elm.nodeName)) {
- return false;
+ if (typeof selector != 'string') {
+ selector = 'table,img,div';
}
if (elm.getAttribute('data-mce-resize') === 'false') {
return false;
}
- return true;
+ return editor.dom.is(elm, selector);
}
function resizeGhostElement(e) {
var deltaX, deltaY;
@@ -9903,10 +9915,18 @@
});
editor.dom.bind(editor.getBody(), 'mscontrolselect', function(e) {
if (/^(TABLE|IMG|HR)$/.test(e.target.nodeName)) {
e.preventDefault();
+
+ // This moves the selection from being a control selection to a text like selection like in WebKit #6753
+ // TODO: Fix this the day IE works like other browsers without this nasty native ugly control selections.
+ if (e.target.tagName == 'IMG') {
+ window.setTimeout(function() {
+ editor.selection.select(e.target);
+ }, 0);
+ }
}
});
}
}
@@ -10768,11 +10788,11 @@
*
* // Restore the selection bookmark
* tinymce.activeEditor.selection.moveToBookmark(bm);
*/
getBookmark: function(type, normalized) {
- var t = this, dom = t.dom, rng, rng2, id, collapsed, name, element, chr = '', styles;
+ var self = this, dom = self.dom, rng, rng2, id, collapsed, name, element, chr = '', styles;
function findIndex(name, element) {
var index = 0;
each(dom.select(name), function(node, i) {
@@ -10806,11 +10826,11 @@
return rng;
}
function getLocation() {
- var rng = t.getRng(true), root = dom.getRoot(), bookmark = {};
+ var rng = self.getRng(true), root = dom.getRoot(), bookmark = {};
function getPoint(rng, start) {
var container = rng[start ? 'startContainer' : 'endContainer'],
offset = rng[start ? 'startOffset' : 'endOffset'], point = [], node, childNodes, after = 0;
@@ -10828,52 +10848,52 @@
if (offset >= childNodes.length && childNodes.length) {
after = 1;
offset = Math.max(0, childNodes.length - 1);
}
- point.push(t.dom.nodeIndex(childNodes[offset], normalized) + after);
+ point.push(self.dom.nodeIndex(childNodes[offset], normalized) + after);
}
for (; container && container != root; container = container.parentNode) {
- point.push(t.dom.nodeIndex(container, normalized));
+ point.push(self.dom.nodeIndex(container, normalized));
}
return point;
}
bookmark.start = getPoint(rng, true);
- if (!t.isCollapsed()) {
+ if (!self.isCollapsed()) {
bookmark.end = getPoint(rng);
}
return bookmark;
}
if (type == 2) {
- element = t.getNode();
+ element = self.getNode();
name = element ? element.nodeName : null;
if (name == 'IMG') {
return {name: name, index: findIndex(name, element)};
}
- if (t.tridentSel) {
- return t.tridentSel.getBookmark(type);
+ if (self.tridentSel) {
+ return self.tridentSel.getBookmark(type);
}
return getLocation();
}
// Handle simple range
if (type) {
- return {rng: t.getRng()};
+ return {rng: self.getRng()};
}
- rng = t.getRng();
+ rng = self.getRng();
id = dom.uniqueId();
- collapsed = t.isCollapsed();
+ collapsed = self.isCollapsed();
styles = 'overflow:hidden;line-height:0px';
// Explorer method
if (rng.duplicate || rng.item) {
// Text selection
@@ -10908,11 +10928,11 @@
name = element.nodeName;
return {name: name, index: findIndex(name, element)};
}
} else {
- element = t.getNode();
+ element = self.getNode();
name = element.nodeName;
if (name == 'IMG') {
return {name: name, index: findIndex(name, element)};
}
@@ -10928,11 +10948,11 @@
rng = normalizeTableCellSelection(rng);
rng.collapse(true);
rng.insertNode(dom.create('span', {'data-mce-type': "bookmark", id: id + '_start', style: styles}, chr));
}
- t.moveToBookmark({id: id, keep: 1});
+ self.moveToBookmark({id: id, keep: 1});
return {id: id};
},
/**
@@ -10949,11 +10969,11 @@
*
* // Restore the selection bookmark
* tinymce.activeEditor.selection.moveToBookmark(bm);
*/
moveToBookmark: function(bookmark) {
- var t = this, dom = t.dom, rng, root, startContainer, endContainer, startOffset, endOffset;
+ var self = this, dom = self.dom, rng, root, startContainer, endContainer, startOffset, endOffset;
function setEndPoint(start) {
var point = bookmark[start ? 'start' : 'end'], i, node, offset, children;
if (point) {
@@ -11069,32 +11089,32 @@
if (bookmark) {
if (bookmark.start) {
rng = dom.createRng();
root = dom.getRoot();
- if (t.tridentSel) {
- return t.tridentSel.moveToBookmark(bookmark);
+ if (self.tridentSel) {
+ return self.tridentSel.moveToBookmark(bookmark);
}
if (setEndPoint(true) && setEndPoint()) {
- t.setRng(rng);
+ self.setRng(rng);
}
} else if (bookmark.id) {
// Restore start/end points
restoreEndPoint('start');
restoreEndPoint('end');
if (startContainer) {
rng = dom.createRng();
rng.setStart(addBogus(startContainer), startOffset);
rng.setEnd(addBogus(endContainer), endOffset);
- t.setRng(rng);
+ self.setRng(rng);
}
} else if (bookmark.name) {
- t.select(dom.select(bookmark.name)[bookmark.index]);
+ self.select(dom.select(bookmark.name)[bookmark.index]);
} else if (bookmark.rng) {
- t.setRng(bookmark.rng);
+ self.setRng(bookmark.rng);
}
}
},
/**
@@ -13061,11 +13081,12 @@
if (start ? startOffset > 0 : endOffset < container.nodeValue.length) {
return container;
}
}
- for (;;) {
+ /*eslint no-constant-condition:0 */
+ while (true) {
// Stop expanding on block elements
if (!format[0].block_expand && isBlock(parent)) {
return parent;
}
@@ -14140,11 +14161,11 @@
'<div[^>]+data-mce-bogus[^>]+><\\/div>', // Trim bogus divs like resize handles
'\\s?data-mce-selected="[^"]+"' // Trim temporaty data-mce prefixed attributes like data-mce-selected
].join('|'), 'gi');
return function(editor) {
- var self, index = 0, data = [], beforeBookmark, isFirstTypedCharacter, lock;
+ var self = this, index = 0, data = [], beforeBookmark, isFirstTypedCharacter, lock;
// Returns a trimmed version of the current editor contents
function getContent() {
return trim(editor.getContent({format: 'raw', no_events: 1}).replace(trimContentRegExp, ''));
}
@@ -16048,10 +16069,11 @@
// Parse URL (Credits goes to Steave, http://blog.stevenlevithan.com/archives/parseuri)
url = url.replace(/@@/g, '(mce_at)'); // Zope 3 workaround, they use @@something
/*jshint maxlen: 255 */
+ /*eslint max-len: 0 */
url = /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@\/]*):?([^:@\/]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(url);
each(["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"], function(v, i) {
var part = url[i];
@@ -16381,20 +16403,18 @@
function Class() {
}
// Provides classical inheritance, based on code made by John Resig
Class.extend = extendClass = function(prop) {
- var Self = this, _super = Self.prototype, prototype, name, member;
+ var self = this, _super = self.prototype, prototype, name, member;
// The dummy class constructor
function Class() {
- var i, mixins, mixin, self;
+ var i, mixins, mixin, self = this;
// All construction is actually done in the init method
if (!initializing) {
- self = this;
-
// Run class constuctor
if (self.init) {
self.init.apply(self, arguments);
}
@@ -16432,11 +16452,11 @@
}
// Instantiate a base class (but only create the instance,
// don't run the init constructor)
initializing = true;
- prototype = new Self();
+ prototype = new self();
initializing = false;
// Add mixins
if (prop.Mixins) {
each(prop.Mixins, function(mixin) {
@@ -16530,10 +16550,12 @@
*
* License: http://www.tinymce.com/license
* Contributing: http://www.tinymce.com/contributing
*/
+/*eslint no-nested-ternary:0 */
+
/**
* Selector engine, enables you to select controls by using CSS like expressions.
* We currently only support basic CSS expressions to reduce the size of the core
* and the ones we support should be enough for most cases.
*
@@ -16594,10 +16616,11 @@
}
var expression = /^([\w\\*]+)?(?:#([\w\\]+))?(?:\.([\w\\\.]+))?(?:\[\@?([\w\\]+)([\^\$\*!~]?=)([\w\\]+)\])?(?:\:(.+))?/i;
/*jshint maxlen:255 */
+ /*eslint max-len:0 */
var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
whiteSpace = /^\s*|\s*$/g,
Collection;
var Selector = Class.extend({
@@ -17430,10 +17453,12 @@
*
* License: http://www.tinymce.com/license
* Contributing: http://www.tinymce.com/contributing
*/
+/*eslint consistent-this:0 */
+
/**
* This is the base class for all controls and containers. All UI control instances inherit
* from this one as it has the base logic needed by all of them.
*
* @class tinymce.ui.Control
@@ -18141,14 +18166,14 @@
* @method parents
* @param {String} selector Optional selector expression to find parents.
* @return {tinymce.ui.Collection} Collection with all parent controls.
*/
parents: function(selector) {
- var ctrl = this, parents = new Collection();
+ var self = this, ctrl, parents = new Collection();
// Add each parent to collection
- for (ctrl = ctrl.parent(); ctrl; ctrl = ctrl.parent()) {
+ for (ctrl = self.parent(); ctrl; ctrl = ctrl.parent()) {
parents.add(ctrl);
}
// Filter away everything that doesn't match the selector
if (selector) {
@@ -18789,14 +18814,14 @@
function fixWheelEvent(e) {
e.preventDefault();
if (e.type == "mousewheel") {
- e.deltaY = - 1/40 * e.wheelDelta;
+ e.deltaY = -1 / 40 * e.wheelDelta;
if (e.wheelDeltaX) {
- e.deltaX = -1/40 * e.wheelDeltaX;
+ e.deltaX = -1 / 40 * e.wheelDeltaX;
}
} else {
e.deltaX = 0;
e.deltaY = e.detail;
}
@@ -19860,11 +19885,11 @@
self.preRender();
layout.preRender(self);
return (
'<div id="' + self._id + '" class="' + self.classes() + '"' + (role ? ' role="' + this.settings.role + '"' : '') + '>' +
- '<div id="' + self._id + '-body" class="' + self.classes('body') + '">'+
+ '<div id="' + self._id + '-body" class="' + self.classes('body') + '">' +
(self.settings.html || '') + layout.renderHtml(self) +
'</div>' +
'</div>'
);
},
@@ -19951,17 +19976,17 @@
*
* @method reflow
* @return {tinymce.ui.Container} Current container instance.
*/
reflow: function() {
- var i, items;
+ var i;
if (this.visible()) {
Control.repaintControls = [];
Control.repaintControls.map = {};
- items = this.recalc();
+ this.recalc();
i = Control.repaintControls.length;
while (i--) {
Control.repaintControls[i].repaint();
}
@@ -21882,11 +21907,11 @@
*
* This code is a ugly hack since writing full custom delete logic for just this bug
* fix seemed like a huge task. I hope we can remove this before the year 2030.
*/
function cleanupStylesWhenDeleting() {
- var doc = editor.getDoc();
+ var doc = editor.getDoc(), urlPrefix = 'data:text/mce-internal,';
if (!window.MutationObserver) {
return;
}
@@ -21997,18 +22022,24 @@
editor.addCommand('ForwardDelete', function() {
customDelete(true);
});
editor.on('dragstart', function(e) {
- e.dataTransfer.setData('mce-internal', editor.selection.getContent());
+ // Safari doesn't support custom dataTransfer items so we can only use URL and Text
+ e.dataTransfer.setData('URL', 'data:text/mce-internal,' + escape(editor.selection.getContent()));
});
editor.on('drop', function(e) {
if (!isDefaultPrevented(e)) {
- var internalContent = e.dataTransfer.getData('mce-internal');
+ var internalContent = e.dataTransfer.getData('URL');
- if (internalContent && doc.caretRangeFromPoint) {
+ if (!internalContent || internalContent.indexOf(urlPrefix) == -1 || !doc.caretRangeFromPoint) {
+ return;
+ }
+
+ internalContent = unescape(internalContent.substr(urlPrefix.length));
+ if (doc.caretRangeFromPoint) {
e.preventDefault();
customDelete();
editor.selection.setRng(doc.caretRangeFromPoint(e.x, e.y));
editor.insertContent(internalContent);
}
@@ -22790,20 +22821,24 @@
setEditorCommandState("AutoUrlDetect", false);
}
/**
* IE 11 has a fantastic bug where it will produce two trailing BR elements to iframe bodies when
- * the iframe is hidden by display: none. This workaround solves this by switching
- * on designMode on the whole document.
+ * the iframe is hidden by display: none on a parent container. The DOM is actually out of sync
+ * with innerHTML in this case. It's like IE adds shadow DOM BR elements that appears on innerHTML
+ * but not as the lastChild of the body. However is we add a BR element to the body then remove it
+ * it doesn't seem to add these BR elements makes sence right?!
*
- * Example this: <body>text</body> becomes <body>text<br><br></body>
+ * Example of what happens: <body>text</body> becomes <body>text<br><br></body>
*/
function doubleTrailingBrElements() {
if (!editor.inline) {
- editor.on('init', function() {
- editor.getDoc().designMode = 'on';
- });
+ editor.on('focus blur', function() {
+ var br = editor.dom.create('br');
+ editor.getBody().appendChild(br);
+ br.parentNode.removeChild(br);
+ }, true);
}
}
// All browsers
disableBackspaceIntoATable();
@@ -22911,10 +22946,14 @@
* instance.fire('event', {...});
*/
fire: function(name, args, bubble) {
var self = this, handlers, i, l, callback, parent;
+ if (self.removed) {
+ return;
+ }
+
name = name.toLowerCase();
args = args || {};
args.type = name;
// Setup target is there isn't one
@@ -22984,17 +23023,18 @@
* Binds an event listener to a specific event by name.
*
* @method on
* @param {String} name Event name or space separated list of events to bind.
* @param {callback} callback Callback to be executed when the event occurs.
+ * @param {Boolean} first Optional flag if the event should be prepended. Use this with care.
* @return {Object} Current class instance.
* @example
* instance.on('event', function(e) {
* // Callback logic
* });
*/
- on: function(name, callback) {
+ on: function(name, callback, prepend) {
var self = this, bindings, handlers, names, i;
if (callback === false) {
callback = function() {
return false;
@@ -23018,11 +23058,15 @@
if (self.bindNative && nativeEvents[name]) {
self.bindNative(name);
}
}
- handlers.push(callback);
+ if (prepend) {
+ handlers.unshift(callback);
+ } else {
+ handlers.push(callback);
+ }
}
}
return self;
},
@@ -23691,11 +23735,11 @@
*
* @method init
*/
init: function() {
var self = this, settings = self.settings, elm = self.getElement();
- var w, h, minHeight, n, o, url, bodyId, bodyClass, re, i, initializedPlugins = [];
+ var w, h, minHeight, n, o, Theme, url, bodyId, bodyClass, re, i, initializedPlugins = [];
self.rtl = this.editorManager.i18n.rtl;
self.editorManager.add(self);
settings.aria_label = settings.aria_label || DOM.getAttrib(elm, 'aria-label', self.getLang('aria.rich_text_area'));
@@ -23710,37 +23754,37 @@
* tinymce.activeEditor.theme.someMethod();
*/
if (settings.theme) {
if (typeof settings.theme != "function") {
settings.theme = settings.theme.replace(/-/, '');
- o = ThemeManager.get(settings.theme);
- self.theme = new o(self, ThemeManager.urls[settings.theme]);
+ Theme = ThemeManager.get(settings.theme);
+ self.theme = new Theme(self, ThemeManager.urls[settings.theme]);
if (self.theme.init) {
self.theme.init(self, ThemeManager.urls[settings.theme] || self.documentBaseUrl.replace(/\/$/, ''));
}
} else {
self.theme = settings.theme;
}
}
function initPlugin(plugin) {
- var constr = PluginManager.get(plugin), url, pluginInstance;
+ var Plugin = PluginManager.get(plugin), pluginUrl, pluginInstance;
- url = PluginManager.urls[plugin] || self.documentBaseUrl.replace(/\/$/, '');
+ pluginUrl = PluginManager.urls[plugin] || self.documentBaseUrl.replace(/\/$/, '');
plugin = trim(plugin);
- if (constr && inArray(initializedPlugins, plugin) === -1) {
+ if (Plugin && inArray(initializedPlugins, plugin) === -1) {
each(PluginManager.dependencies(plugin), function(dep){
initPlugin(dep);
});
- pluginInstance = new constr(self, url);
+ pluginInstance = new Plugin(self, pluginUrl);
self.plugins[plugin] = pluginInstance;
if (pluginInstance.init) {
- pluginInstance.init(self, url);
+ pluginInstance.init(self, pluginUrl);
initializedPlugins.push(plugin);
}
}
}
@@ -23756,15 +23800,15 @@
h = settings.height || elm.style.height || elm.offsetHeight;
minHeight = settings.min_height || 100;
re = /^[0-9\.]+(|px)$/i;
if (re.test('' + w)) {
- w = Math.max(parseInt(w, 10) + (o.deltaWidth || 0), 100);
+ w = Math.max(parseInt(w, 10), 100);
}
if (re.test('' + h)) {
- h = Math.max(parseInt(h, 10) + (o.deltaHeight || 0), minHeight);
+ h = Math.max(parseInt(h, 10), minHeight);
}
// Render UI
o = self.theme.renderUI({
targetNode: elm,
@@ -23860,11 +23904,12 @@
}
self.iframeHTML += '</head><body id="' + bodyId + '" class="mce-content-body ' + bodyClass + '" ' +
'onload="window.parent.tinymce.get(\'' + self.id + '\').fire(\'load\');"><br></body></html>';
- var domainRelaxUrl = 'javascript:(function(){'+
+ /*eslint no-script-url:0 */
+ var domainRelaxUrl = 'javascript:(function(){' +
'document.open();document.domain="' + document.domain + '";' +
'var ed = window.parent.tinymce.get("' + self.id + '");document.write(ed.iframeHTML);' +
'document.close();ed.initContentBody(true);})()';
// Domain relaxing is required since the user has messed around with document.domain
@@ -23938,16 +23983,16 @@
doc.close();
}
if (settings.content_editable) {
self.on('remove', function() {
- var body = this.getBody();
+ var bodyEl = this.getBody();
- DOM.removeClass(body, 'mce-content-body');
- DOM.removeClass(body, 'mce-edit-focus');
- DOM.setAttrib(body, 'tabIndex', null);
- DOM.setAttrib(body, 'contentEditable', null);
+ DOM.removeClass(bodyEl, 'mce-content-body');
+ DOM.removeClass(bodyEl, 'mce-edit-focus');
+ DOM.setAttrib(bodyEl, 'tabIndex', null);
+ DOM.setAttrib(bodyEl, 'contentEditable', null);
});
DOM.addClass(targetElm, 'mce-content-body');
targetElm.tabIndex = -1;
self.contentDocument = doc = settings.content_document || document;
@@ -24403,11 +24448,11 @@
*/
nodeChanged: function() {
var self = this, selection = self.selection, node, parents, root;
// Fix for bug #1896577 it seems that this can not be fired while the editor is loading
- if (self.initialized && !self.settings.disable_nodechange) {
+ if (self.initialized && !self.settings.disable_nodechange && !self.settings.readonly) {
// Get start node
root = self.getBody();
node = selection.getStart() || root;
node = ie && node.ownerDocument != self.getDoc() ? self.getBody() : node; // Fix for IE initial state
@@ -24935,11 +24980,11 @@
// Check if forcedRootBlock is configured and that the block is a valid child of the body
if (forcedRootBlockName && self.schema.isValidChild(body.nodeName.toLowerCase(), forcedRootBlockName.toLowerCase())) {
// Padd with bogus BR elements on modern browsers and IE 7 and 8 since they don't render empty P tags properly
content = ie && ie < 11 ? '' : '<br data-mce-bogus="1">';
content = self.dom.createHTML(forcedRootBlockName, self.settings.forced_root_block_attrs, content);
- } else if (!ie || ie < 11) {
+ } else if (!ie) {
// We need to add a BR when forced_root_block is disabled on non IE browsers to place the caret
content = '<br data-mce-bogus="1">';
}
body.innerHTML = content;
@@ -25234,23 +25279,19 @@
*/
remove: function() {
var self = this;
if (!self.removed) {
+ self.fire('remove');
+ self.off();
self.removed = 1; // Cancels post remove event execution
// Remove any hidden input
if (self.hasHiddenInput) {
DOM.remove(self.getElement().nextSibling);
}
- // Fixed bug where IE has a blinking cursor left from the editor
- var doc = self.getDoc();
- if (ie && doc && !self.inline) {
- doc.execCommand('SelectAll');
- }
-
// We must save before we hide so Safari doesn't crash
self.save();
DOM.setStyle(self.id, 'display', self.orgDisplay);
@@ -25263,12 +25304,10 @@
var elm = self.getContainer();
Event.unbind(self.getBody());
Event.unbind(elm);
- self.fire('remove');
-
self.editorManager.remove(self);
DOM.remove(elm);
self.destroy();
}
},
@@ -25353,11 +25392,11 @@
}
DOM.unbind(form, 'submit reset', self.formEventDelegate);
}
- self.contentAreaContainer = self.formElement = self.container = null;
+ self.contentAreaContainer = self.formElement = self.container = self.editorContainer = null;
self.settings.content_element = self.bodyElement = self.contentDocument = self.contentWindow = null;
if (self.selection) {
self.selection = self.selection.win = self.selection.dom = self.selection.dom.doc = null;
}
@@ -25506,10 +25545,12 @@
*/
define("tinymce/FocusManager", [
"tinymce/dom/DOMUtils",
"tinymce/Env"
], function(DOMUtils, Env) {
+ var selectionChangeHandler, documentFocusInHandler, DOM = DOMUtils.DOM;
+
/**
* Constructs a new focus manager instance.
*
* @constructor FocusManager
* @param {tinymce.EditorManager} editorManager Editor manager instance to handle focus for.
@@ -25553,11 +25594,11 @@
return rng;
}
function isUIElement(elm) {
- return !!DOMUtils.DOM.getParent(elm, FocusManager.isEditorUIElement);
+ return !!DOM.getParent(elm, FocusManager.isEditorUIElement);
}
function isNodeInBodyOfEditor(node, editor) {
var body = editor.getBody();
@@ -25569,11 +25610,11 @@
node = node.parentNode;
}
}
function registerEvents(e) {
- var editor = e.editor, selectionChangeHandler;
+ var editor = e.editor;
editor.on('init', function() {
// On IE take selection snapshot onbeforedeactivate
if ("onbeforedeactivate" in document && Env.ie < 11) {
// Gets fired when the editor is about to be blurred but also when the selection
@@ -25609,29 +25650,26 @@
editor.lastRng = editor.selection.getRng();
}
});
// Handles the issue with WebKit not retaining selection within inline document
- // If the user releases the mouse out side the body while selecting a nodeChange won't
- // fire and there for the selection snapshot won't be stored
- // TODO: Optimize this since we only need to bind these on the active editor
- if (Env.webkit) {
+ // If the user releases the mouse out side the body since a mouse up event wont occur on the body
+ if (Env.webkit && !selectionChangeHandler) {
selectionChangeHandler = function() {
- var rng = editor.selection.getRng();
+ var activeEditor = editorManager.activeEditor;
- // Store when it's non collapsed
- if (!rng.collapsed) {
- editor.lastRng = rng;
+ if (activeEditor && activeEditor.selection) {
+ var rng = activeEditor.selection.getRng();
+
+ // Store when it's non collapsed
+ if (rng && !rng.collapsed) {
+ editor.lastRng = rng;
+ }
}
};
- // Bind selection handler
- DOMUtils.DOM.bind(document, 'selectionchange', selectionChangeHandler);
-
- editor.on('remove', function() {
- DOMUtils.DOM.unbind(document, 'selectionchange', selectionChangeHandler);
- });
+ DOM.bind(document, 'selectionchange', selectionChangeHandler);
}
}
});
editor.on('setcontent', function() {
@@ -25679,32 +25717,45 @@
editor.selection.lastFocusBookmark = null;
}
}
}, 0);
});
- }
- // Check if focus is moved to an element outside the active editor by checking if the target node
- // isn't within the body of the activeEditor nor a UI element such as a dialog child control
- DOMUtils.DOM.bind(document, 'focusin', function(e) {
- var activeEditor = editorManager.activeEditor;
+ if (!documentFocusInHandler) {
+ documentFocusInHandler = function(e) {
+ var activeEditor = editorManager.activeEditor;
- if (activeEditor && e.target.ownerDocument == document) {
- // Check to make sure we have a valid selection
- if (activeEditor.selection) {
- activeEditor.selection.lastFocusBookmark = createBookmark(activeEditor.lastRng);
- }
+ if (activeEditor && e.target.ownerDocument == document) {
+ // Check to make sure we have a valid selection
+ if (activeEditor.selection) {
+ activeEditor.selection.lastFocusBookmark = createBookmark(activeEditor.lastRng);
+ }
- // Fire a blur event if the element isn't a UI element
- if (!isUIElement(e.target) && editorManager.focusedEditor == activeEditor) {
- activeEditor.fire('blur', {focusedEditor: null});
- editorManager.focusedEditor = null;
- }
+ // Fire a blur event if the element isn't a UI element
+ if (!isUIElement(e.target) && editorManager.focusedEditor == activeEditor) {
+ activeEditor.fire('blur', {focusedEditor: null});
+ editorManager.focusedEditor = null;
+ }
+ }
+ };
+
+ // Check if focus is moved to an element outside the active editor by checking if the target node
+ // isn't within the body of the activeEditor nor a UI element such as a dialog child control
+ DOM.bind(document, 'focusin', documentFocusInHandler);
}
- });
+ }
+ function unregisterDocumentEvents() {
+ if (!editorManager.activeEditor) {
+ DOM.unbind(document, 'selectionchange', selectionChangeHandler);
+ DOM.unbind(document, 'focusin', documentFocusInHandler);
+ selectionChangeHandler = documentFocusInHandler = null;
+ }
+ }
+
editorManager.on('AddEditor', registerEvents);
+ editorManager.on('RemoveEditor', unregisterDocumentEvents);
}
/**
* Returns true if the specified element is part of the UI for example an button or text input.
*
@@ -25768,19 +25819,19 @@
* Minor version of TinyMCE build.
*
* @property minorVersion
* @type String
*/
- minorVersion : '0.18',
+ minorVersion : '0.19',
/**
* Release date of TinyMCE build.
*
* @property releaseDate
* @type String
*/
- releaseDate: '2014-02-27',
+ releaseDate: '2014-03-11',
/**
* Collection of editor instances.
*
* @property editors
@@ -26516,11 +26567,11 @@
}) + quote;
}
if (t == 'object') {
if (o.hasOwnProperty && Object.prototype.toString.call(o) === '[object Array]') {
- for (i=0, v = '['; i<o.length; i++) {
+ for (i = 0, v = '['; i < o.length; i++) {
v += (i > 0 ? ',' : '') + serialize(o[i], quote);
}
return v + ']';
}
@@ -26528,11 +26579,11 @@
v = '{';
for (name in o) {
if (o.hasOwnProperty(name)) {
v += typeof o[name] != 'function' ? (v.length > 1 ? ',' + quote : quote) + name +
- quote +':' + serialize(o[name], quote) : '';
+ quote + ':' + serialize(o[name], quote) : '';
}
}
return v + '}';
}
@@ -27656,12 +27707,12 @@
self.addClass('btn-group');
self.preRender();
layout.preRender(self);
return (
- '<div id="' + self._id + '" class="' + self.classes() + '">'+
- '<div id="' + self._id + '-body">'+
+ '<div id="' + self._id + '" class="' + self.classes() + '">' +
+ '<div id="' + self._id + '-body">' +
(self.settings.html || '') + layout.renderHtml(self) +
'</div>' +
'</div>'
);
}
@@ -27781,11 +27832,11 @@
var self = this, id = self._id, prefix = self.classPrefix;
return (
'<div id="' + id + '" class="' + self.classes() + '" unselectable="on" aria-labelledby="' + id + '-al" tabindex="-1">' +
'<i class="' + prefix + 'ico ' + prefix + 'i-checkbox"></i>' +
- '<span id="' + id +'-al" class="' + prefix + 'label">' + self.encode(self._text) + '</span>' +
+ '<span id="' + id + '-al" class="' + prefix + 'label">' + self.encode(self._text) + '</span>' +
'</div>'
);
}
});
});
@@ -28469,13 +28520,13 @@
_getPathHtml: function() {
var self = this, parts = self._data || [], i, l, html = '', prefix = self.classPrefix;
for (i = 0, l = parts.length; i < l; i++) {
html += (
- (i > 0 ? '<div class="'+ prefix + 'divider" aria-hidden="true"> ' + self.settings.delimiter + ' </div>' : '') +
+ (i > 0 ? '<div class="' + prefix + 'divider" aria-hidden="true"> ' + self.settings.delimiter + ' </div>' : '') +
'<div role="button" class="' + prefix + 'path-item' + (i == l - 1 ? ' ' + prefix + 'last' : '') + '" data-index="' +
- i + '" tabindex="-1" id="' + self._id + '-' + i +'" aria-level="' + i + '">' + parts[i].name + '</div>'
+ i + '" tabindex="-1" id="' + self._id + '-' + i + '" aria-level="' + i + '">' + parts[i].name + '</div>'
);
}
if (!html) {
html = '<div class="' + prefix + 'path-item"> </div>';
@@ -28994,12 +29045,12 @@
*/
recalc: function(container) {
// A ton of variables, needs to be in the same scope for performance
var i, l, items, contLayoutRect, contPaddingBox, contSettings, align, pack, spacing, totalFlex, availableSpace, direction;
var ctrl, ctrlLayoutRect, ctrlSettings, flex, maxSizeItems = [], size, maxSize, ratio, rect, pos, maxAlignEndPos;
- var sizeName, minSizeName, posName, maxSizeName, beforeName, innerSizeName, afterName, deltaSizeName, contentSizeName;
- var alignAxisName, alignInnerSizeName, alignSizeName, alignMinSizeName, alignMaxSizeName, alignBeforeName, alignAfterName;
+ var sizeName, minSizeName, posName, maxSizeName, beforeName, innerSizeName, deltaSizeName, contentSizeName;
+ var alignAxisName, alignInnerSizeName, alignSizeName, alignMinSizeName, alignBeforeName, alignAfterName;
var alignDeltaSizeName, alignContentSizeName;
var max = Math.max, min = Math.min;
// Get container items, properties and settings
items = container.items().filter(':visible');
@@ -29022,40 +29073,36 @@
sizeName = "h";
minSizeName = "minH";
maxSizeName = "maxH";
innerSizeName = "innerH";
beforeName = 'top';
- afterName = 'bottom';
deltaSizeName = "deltaH";
contentSizeName = "contentH";
alignBeforeName = "left";
alignSizeName = "w";
alignAxisName = "x";
alignInnerSizeName = "innerW";
alignMinSizeName = "minW";
- alignMaxSizeName = "maxW";
alignAfterName = "right";
alignDeltaSizeName = "deltaW";
alignContentSizeName = "contentW";
} else {
posName = "x";
sizeName = "w";
minSizeName = "minW";
maxSizeName = "maxW";
innerSizeName = "innerW";
beforeName = 'left';
- afterName = 'right';
deltaSizeName = "deltaW";
contentSizeName = "contentW";
alignBeforeName = "top";
alignSizeName = "h";
alignAxisName = "y";
alignInnerSizeName = "innerH";
alignMinSizeName = "minH";
- alignMaxSizeName = "maxH";
alignAfterName = "bottom";
alignDeltaSizeName = "deltaH";
alignContentSizeName = "contentH";
}
@@ -29949,11 +29996,11 @@
* @param {tinymce.ui.Container} container Container instance to recalc.
*/
recalc: function(container) {
var settings = container.settings, rows, cols, items, contLayoutRect, width, height, rect,
ctrlLayoutRect, ctrl, x, y, posX, posY, ctrlSettings, contPaddingBox, align, spacingH, spacingV, alignH, alignV, maxX, maxY,
- colWidths = [], rowHeights = [], ctrlMinWidth, ctrlMinHeight, alignX, alignY, availableWidth, availableHeight;
+ colWidths = [], rowHeights = [], ctrlMinWidth, ctrlMinHeight, availableWidth, availableHeight;
// Get layout settings
settings = container.settings;
items = container.items().filter(':visible');
contLayoutRect = container.layoutRect();
@@ -30099,11 +30146,10 @@
// Get control settings and calculate x, y
ctrlSettings = ctrl.settings;
ctrlLayoutRect = ctrl.layoutRect();
width = Math.max(colWidths[x], ctrlLayoutRect.startMinWidth);
- alignX = alignY = 0;
ctrlLayoutRect.x = posX;
ctrlLayoutRect.y = posY;
// Align control horizontal
align = ctrlSettings.alignH || (alignH ? (alignH[x] || alignH[0]) : null);
@@ -30344,11 +30390,11 @@
*/
renderHtml: function() {
var self = this, forId = self.settings.forId;
return (
- '<label id="' + self._id + '" class="' + self.classes() + '"' + (forId ? ' for="' + forId +'"' : '') + '>' +
+ '<label id="' + self._id + '" class="' + self.classes() + '"' + (forId ? ' for="' + forId + '"' : '') + '>' +
self.encode(self._text) +
'</label>'
);
}
});
@@ -31662,10 +31708,10 @@
ctrl.aria('role', 'tabpanel');
ctrl.aria('labelledby', id);
tabsHtml += (
- '<div id="' + id + '" class="' + prefix + 'tab" '+
+ '<div id="' + id + '" class="' + prefix + 'tab" ' +
'unselectable="on" role="tab" aria-controls="' + ctrl._id + '" aria-selected="false" tabIndex="-1">' +
self.encode(ctrl.settings.title) +
'</div>'
);
});
\ No newline at end of file