app/assets/source/tinymce/tinymce.jquery.js in tinymce-rails-4.1.3 vs app/assets/source/tinymce/tinymce.jquery.js in tinymce-rails-4.1.4
- old
+ new
@@ -1,6 +1,6 @@
-// 4.1.3 (2014-07-29)
+// 4.1.4 (2014-08-21)
/**
* Compiled inline version. (Library mode)
*/
@@ -190,15 +190,15 @@
if (originalEvent && mouseEventRe.test(originalEvent.type) && originalEvent.pageX === undef && originalEvent.clientX !== undef) {
var eventDoc = event.target.ownerDocument || document;
var doc = eventDoc.documentElement;
var body = eventDoc.body;
- event.pageX = originalEvent.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0 ) -
- ( doc && doc.clientLeft || body && body.clientLeft || 0);
+ event.pageX = originalEvent.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) -
+ (doc && doc.clientLeft || body && body.clientLeft || 0);
- event.pageY = originalEvent.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0 ) -
- ( doc && doc.clientTop || body && body.clientTop || 0);
+ event.pageY = originalEvent.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) -
+ (doc && doc.clientTop || body && body.clientTop || 0);
}
// Add preventDefault method
event.preventDefault = function() {
event.isDefaultPrevented = returnTrue;
@@ -1919,11 +1919,11 @@
try {
while (i--) {
self[i].innerHTML = value;
}
} catch (ex) {
- // Workaround for "Unkown runtime error" when DIV is added to P on IE
+ // Workaround for "Unknown runtime error" when DIV is added to P on IE
DomQuery(self[i]).empty().append(value);
}
return self;
}
@@ -2510,14 +2510,22 @@
expr: Sizzle.selectors,
unique: Sizzle.uniqueSort,
text: Sizzle.getText,
contains: Sizzle.contains,
filter: function(expr, elems, not) {
+ var i = elems.length;
+
if (not) {
expr = ":not(" + expr + ")";
}
+ while (i--) {
+ if (elems[i].nodeType != 1) {
+ elems.splice(i, 1);
+ }
+ }
+
if (elems.length === 1) {
elems = DomQuery.find.matchesSelector(elems[0], expr) ? [elems[0]] : [];
} else {
elems = DomQuery.find.matches(expr, elems);
}
@@ -7506,12 +7514,12 @@
});
editor.on('SelectionChange', function() {
var startElm = editor.selection.getStart(true);
- // Selection change might fire when focus is lost so check if the start is still within the body
- if (!isSameElementPath(startElm) && editor.dom.isChildOf(startElm, editor.getBody())) {
+ // Fire a nodechange only when the selection isn't collapsed since focusout will collapse and remove the selection
+ if (!editor.selection.isCollapsed() && !isSameElementPath(startElm) && editor.dom.isChildOf(startElm, editor.getBody())) {
editor.nodeChanged({selectionChange: true});
}
});
// Fire an extra nodeChange on mouseup for compatibility reasons
@@ -7794,11 +7802,11 @@
* @method unwrap
*/
unwrap: function() {
var self = this, node, next;
- for (node = self.firstChild; node; ) {
+ for (node = self.firstChild; node;) {
next = node.next;
self.insert(node, self, true);
node = next;
}
@@ -7996,15 +8004,15 @@
// Keep empty elements like <img />
if (elements[node.name]) {
return false;
}
- // Keep elements with data attributes or name attribute like <a name="1"></a>
+ // Keep bookmark nodes and name attribute like <a name="1"></a>
i = node.attributes.length;
while (i--) {
name = node.attributes[i].name;
- if (name === "name" || name.indexOf('data-mce-') === 0) {
+ if (name === "name" || name.indexOf('data-mce-bookmark') === 0) {
return false;
}
}
}
@@ -9639,11 +9647,11 @@
currentNode.append(tempNode);
} else {
tempNode = currentNode;
}
- for (childNode = parents[i].firstChild; childNode && childNode != parents[i + 1]; ) {
+ for (childNode = parents[i].firstChild; childNode && childNode != parents[i + 1];) {
nextNode = childNode.next;
tempNode.append(childNode);
childNode = nextNode;
}
@@ -9888,11 +9896,11 @@
}
function removeWhitespaceBefore(node) {
var textNode, textVal, sibling;
- for (textNode = node.prev; textNode && textNode.type === 3; ) {
+ for (textNode = node.prev; textNode && textNode.type === 3;) {
textVal = textNode.value.replace(endWhiteSpaceRegExp, '');
if (textVal.length > 0) {
textNode.value = textVal;
textNode = textNode.prev;
@@ -11715,12 +11723,12 @@
'opacity: .5;' +
'filter: alpha(opacity=50);' +
'z-index: 10000' +
'}' +
rootClass + ' .mce-resize-helper {' +
- 'background-color: #555;' +
- 'background-color: rgba(0,0,0,0.75);' +
+ 'background: #555;' +
+ 'background: rgba(0,0,0,0.75);' +
'border-radius: 3px;' +
'border: 1px;' +
'color: white;' +
'display: none;' +
'font-family: sans-serif;' +
@@ -12026,10 +12034,15 @@
}
} while ((node = node.parentNode));
}
}
+ // Ignore all events while resizing
+ if (resizeStarted) {
+ return;
+ }
+
// Remove data-mce-selected from all elements since they might have been copied using Ctrl+c/v
each(dom.select('img[data-mce-selected],hr[data-mce-selected]'), function(img) {
img.removeAttribute('data-mce-selected');
});
@@ -13108,11 +13121,11 @@
* @see http://www.dotvoid.com/2001/03/using-the-range-object-in-mozilla/
*/
getRng: function(w3c) {
var self = this, selection, rng, elm, doc = self.win.document, ieRng;
- function tryCompareBounderyPoints(how, sourceRange, destinationRange) {
+ function tryCompareBoundaryPoints(how, sourceRange, destinationRange) {
try {
return sourceRange.compareBoundaryPoints(how, destinationRange);
} catch (ex) {
// Gecko throws wrong document exception if the range points
// to nodes that where removed from the dom #6690
@@ -13188,12 +13201,12 @@
rng.setStart(elm, 0);
rng.setEnd(elm, 0);
}
if (self.selectedRange && self.explicitRange) {
- if (tryCompareBounderyPoints(rng.START_TO_START, rng, self.selectedRange) === 0 &&
- tryCompareBounderyPoints(rng.END_TO_END, rng, self.selectedRange) === 0) {
+ if (tryCompareBoundaryPoints(rng.START_TO_START, rng, self.selectedRange) === 0 &&
+ tryCompareBoundaryPoints(rng.END_TO_END, rng, self.selectedRange) === 0) {
// Safari, Opera and Chrome only ever select text which causes the range to change.
// This lets us use the originally set range if the selection hasn't been changed by the user.
rng = self.explicitRange;
} else {
self.selectedRange = null;
@@ -13530,10 +13543,34 @@
if (y < viewPort.y || y + 25 > viewPortY + viewPortH) {
self.editor.getWin().scrollTo(0, y < viewPortY ? y : y - viewPortH + 25);
}
},
+ placeCaretAt: function(clientX, clientY) {
+ var doc = this.editor.getDoc(), rng, point;
+
+ if (doc.caretPositionFromPoint) {
+ point = doc.caretPositionFromPoint(clientX, clientY);
+ rng = doc.createRange();
+ rng.setStart(point.offsetNode, point.offset);
+ rng.collapse(true);
+ } else if (doc.caretRangeFromPoint) {
+ rng = doc.caretRangeFromPoint(clientX, clientY);
+ } else if (doc.body.createTextRange) {
+ rng = doc.body.createTextRange();
+
+ try {
+ rng.moveToPoint(clientX, clientY);
+ rng.collapse(true);
+ } catch (ex) {
+ rng.collapse(clientY < doc.body.clientHeight);
+ }
+ }
+
+ this.setRng(rng);
+ },
+
_moveEndPoint: function(rng, node, start) {
var root = node, walker = new TreeWalker(node, root);
var nonEmptyElementsMap = this.dom.schema.getNonEmptyElements();
do {
@@ -15246,11 +15283,11 @@
node = node.childNodes[offset];
if (node) {
offset = node.nodeType === 3 ? node.length : node.childNodes.length;
}
}
- return { node: node, offset: offset };
+ return {node: node, offset: offset};
}
// If index based start position then resolve it
if (startContainer.nodeType == 1 && startContainer.hasChildNodes()) {
lastIdx = startContainer.childNodes.length - 1;
@@ -16210,11 +16247,11 @@
*
* @private
* @return {String} HTML contents of the editor excluding some internal bogus elements.
*/
function getContent() {
- var content = trim(editor.getContent({format: 'raw', no_events: 1}));
+ var content = editor.getContent({format: 'raw', no_events: 1});
var bogusAllRegExp = /<(\w+) [^>]*data-mce-bogus="all"[^>]*>/g;
var endTagIndex, index, matchLength, matches, shortEndedElements, schema = editor.schema;
content = content.replace(trimContentRegExp, '');
shortEndedElements = schema.getShortEndedElements();
@@ -16232,11 +16269,11 @@
content = content.substring(0, index - matchLength) + content.substring(endTagIndex);
bogusAllRegExp.lastIndex = index - matchLength;
}
- return content;
+ return trim(content);
}
function addNonTypingUndoLevel(e) {
self.typing = false;
self.add({}, e);
@@ -17167,11 +17204,11 @@
}
dom.setAttrib(newBlock, 'id', ''); // Remove ID since it needs to be document unique
// Allow custom handling of new blocks
- editor.fire('NewBlock', { newBlock: newBlock });
+ editor.fire('NewBlock', {newBlock: newBlock});
undoManager.add();
}
editor.on('keydown', function(evt) {
@@ -17707,11 +17744,11 @@
}
// Setup parser and serializer
parser = editor.parser;
serializer = new Serializer({}, editor.schema);
- bookmarkHtml = '<span id="mce_marker" data-mce-type="bookmark">ÈB;</span>';
+ bookmarkHtml = '<span id="mce_marker" data-mce-type="bookmark">​</span>';
// Run beforeSetContent handlers on the HTML to be inserted
args = {content: value, format: 'html', selection: true};
editor.fire('BeforeSetContent', args);
value = args.content;
@@ -17755,11 +17792,13 @@
if (node.attr('id') == 'mce_marker') {
marker = node;
for (node = node.prev; node; node = node.walk(true)) {
if (node.type == 3 || !dom.isBlock(node.name)) {
- node.parent.insert(marker, node, node.name === 'br');
+ if (editor.schema.isValidChild(node.parent.name, 'span')) {
+ node.parent.insert(marker, node, node.name === 'br');
+ }
break;
}
}
}
@@ -21670,11 +21709,11 @@
}
/**
* Returns the navigation root control for the specified control. The navigation root
* is the control that the keyboard navigation gets scoped to for example a menubar or toolbar group.
- * It will look for parents of the specified target control or the currenty focused control if this option is omitted.
+ * It will look for parents of the specified target control or the currently focused control if this option is omitted.
*
* @private
* @param {tinymce.ui.Control} targetControl Optional target control to find root of.
* @return {tinymce.ui.Control} Navigation root control.
*/
@@ -24122,11 +24161,11 @@
* larger than the popup size specified).
*/
self.open = function(args, params) {
var win;
- editor.editorManager.activeEditor = editor;
+ editor.editorManager.setActive(editor);
args.title = args.title || ' ';
// Handle URL
args.url = args.url || args.file; // Legacy
@@ -24779,21 +24818,23 @@
* WebKit has a bug where it isn't possible to select image, hr or anchor elements
* by clicking on them so we need to fake that.
*/
function selectControlElements() {
editor.on('click', function(e) {
- e = e.target;
+ var target = e.target;
// Workaround for bug, http://bugs.webkit.org/show_bug.cgi?id=12250
// WebKit can't even do simple things like selecting an image
// Needs tobe the setBaseAndExtend or it will fail to select floated images
- if (/^(IMG|HR)$/.test(e.nodeName)) {
- selection.getSel().setBaseAndExtent(e, 0, e, 1);
+ if (/^(IMG|HR)$/.test(target.nodeName)) {
+ e.preventDefault();
+ selection.getSel().setBaseAndExtent(target, 0, target, 1);
}
- if (e.nodeName == 'A' && dom.hasClass(e, 'mce-item-anchor')) {
- selection.select(e);
+ if (target.nodeName == 'A' && dom.hasClass(target, 'mce-item-anchor')) {
+ e.preventDefault();
+ selection.select(target);
}
});
}
/**
@@ -25422,10 +25463,17 @@
each('pageX pageY clientX clientY screenX screenY'.split(' '), function(key) {
args[key] = endTouch[key];
});
args = editor.fire('click', args);
+
+ if (!args.isDefaultPrevented()) {
+ // iOS WebKit can't place the caret properly once
+ // you bind touch events so we need to do this manually
+ // TODO: Expand to the closest word? Touble tap still works.
+ editor.selection.placeCaretAt(endTouch.clientX, endTouch.clientY);
+ }
});
});
}
/**
@@ -26619,10 +26667,14 @@
if (bodyClass.indexOf('=') != -1) {
bodyClass = self.getParam('body_class', '', 'hash');
bodyClass = bodyClass[self.id] || '';
}
+ if (settings.content_security_policy) {
+ self.iframeHTML += '<meta http-equiv="Content-Security-Policy" content="' + settings.content_security_policy + '" />';
+ }
+
self.iframeHTML += '</head><body id="' + bodyId +
'" class="mce-content-body ' + bodyClass +
'" data-id="' + self.id + '"><br></body></html>';
/*eslint no-script-url:0 */
@@ -26657,11 +26709,11 @@
ifr.onload = function() {
ifr.onload = null;
self.fire("load");
};
- DOM.setAttrib("src", url || 'javascript:""');
+ DOM.setAttrib(ifr, "src", url || 'javascript:""');
self.contentAreaContainer = o.iframeContainer;
self.iframeElement = ifr;
n = DOM.add(o.iframeContainer, ifr);
@@ -27008,11 +27060,11 @@
*
* @method focus
* @param {Boolean} skipFocus Skip DOM focus. Just set is as the active editor.
*/
focus: function(skipFocus) {
- var oed, self = this, selection = self.selection, contentEditable = self.settings.content_editable, rng;
+ var self = this, selection = self.selection, contentEditable = self.settings.content_editable, rng;
var controlElm, doc = self.getDoc(), body;
if (!skipFocus) {
// Get selected control element
rng = selection.getRng();
@@ -27062,19 +27114,11 @@
rng.addElement(controlElm);
rng.select();
}
}
- if (self.editorManager.activeEditor != self) {
- if ((oed = self.editorManager.activeEditor)) {
- oed.fire('deactivate', {relatedTarget: self});
- }
-
- self.fire('activate', {relatedTarget: oed});
- }
-
- self.editorManager.activeEditor = self;
+ self.editorManager.setActive(self);
},
/**
* Executes a legacy callback. This method is useful to call old 2.x option callbacks.
* There new event model is a better way to add callback so this method might be removed in the future.
@@ -28326,11 +28370,15 @@
editor.on('init', function() {
// Gecko/WebKit has ghost selections in iframes and IE only has one selection per browser tab
if (editor.inline || Env.ie) {
// Use the onbeforedeactivate event when available since it works better see #7023
if ("onbeforedeactivate" in document && Env.ie < 9) {
- editor.dom.bind(editor.getBody(), 'beforedeactivate', function() {
+ editor.dom.bind(editor.getBody(), 'beforedeactivate', function(e) {
+ if (e.target != editor.getBody()) {
+ return;
+ }
+
try {
editor.lastRng = editor.selection.getRng();
} catch (ex) {
// IE throws "Unexcpected call to method or property access" some times so lets ignore it
}
@@ -28397,11 +28445,11 @@
if (focusedEditor != editor) {
if (focusedEditor) {
focusedEditor.fire('blur', {focusedEditor: editor});
}
- editorManager.activeEditor = editor;
+ editorManager.setActive(editor);
editorManager.focusedEditor = editor;
editor.fire('focus', {blurredEditor: focusedEditor});
editor.focus(true);
}
@@ -28437,11 +28485,11 @@
if (activeEditor.selection && e.target != activeEditor.getBody()) {
activeEditor.selection.lastFocusBookmark = createBookmark(activeEditor.dom, activeEditor.lastRng);
}
// Fire a blur event if the element isn't a UI element
- if (!isUIElement(e.target) && editorManager.focusedEditor == activeEditor) {
+ if (e.target != document.body && !isUIElement(e.target) && editorManager.focusedEditor == activeEditor) {
activeEditor.fire('blur', {focusedEditor: null});
editorManager.focusedEditor = null;
}
}
};
@@ -28597,19 +28645,19 @@
* Minor version of TinyMCE build.
*
* @property minorVersion
* @type String
*/
- minorVersion: '1.3',
+ minorVersion: '1.4',
/**
* Release date of TinyMCE build.
*
* @property releaseDate
* @type String
*/
- releaseDate: '2014-07-29',
+ releaseDate: '2014-08-21',
/**
* Collection of editor instances.
*
* @property editors
@@ -28743,11 +28791,11 @@
* tinyMCE.init({
* some_settings : 'some value'
* });
*/
init: function(settings) {
- var self = this, editors = [], editor;
+ var self = this, editors = [];
function createId(elm) {
var id = elm.id;
// Use element id, or unique name or generate a unique id
@@ -28768,10 +28816,11 @@
}
function createEditor(id, settings, targetElm) {
if (!purgeDestroyedEditor(self.get(id))) {
var editor = new Editor(id, settings, self);
+
editor.targetElm = editor.targetElm || targetElm;
editors.push(editor);
editor.render();
}
}
@@ -28821,22 +28870,22 @@
switch (settings.mode) {
case "exact":
l = settings.elements || '';
if (l.length > 0) {
- each(explode(l), function(v) {
- if (DOM.get(v)) {
- editor = new Editor(v, settings, self);
- editors.push(editor);
- editor.render();
+ each(explode(l), function(id) {
+ var elm;
+
+ if ((elm = DOM.get(id))) {
+ createEditor(id, settings, elm);
} else {
each(document.forms, function(f) {
each(f.elements, function(e) {
- if (e.name === v) {
- v = 'mce_editor_' + instanceCounter++;
- DOM.setAttrib(e, 'id', v);
- createEditor(v, settings, e);
+ if (e.name === id) {
+ id = 'mce_editor_' + instanceCounter++;
+ DOM.setAttrib(e, 'id', id);
+ createEditor(id, settings, e);
}
});
});
}
});
@@ -28928,10 +28977,12 @@
// Add named and index editor instance
editors[editor.id] = editor;
editors.push(editor);
+ // Doesn't call setActive method since we don't want
+ // to fire a bunch of activate/deactivate calls while initializing
self.activeEditor = editor;
/**
* Fires when an editor is added to the EditorManager collection.
*
@@ -29120,10 +29171,30 @@
* @param {String/Array/Object} text String to translate
* @return {String} Translated string.
*/
translate: function(text) {
return I18n.translate(text);
+ },
+
+ /**
+ * Sets the active editor instance and fires the deactivate/activate events.
+ *
+ * @method setActive
+ * @param {tinymce.Editor} editor Editor instance to set as the active instance.
+ */
+ setActive: function(editor) {
+ var activeEditor = this.activeEditor;
+
+ if (this.activeEditor != editor) {
+ if (activeEditor) {
+ activeEditor.fire('deactivate', {relatedTarget: editor});
+ }
+
+ editor.fire('activate', {relatedTarget: activeEditor});
+ }
+
+ this.activeEditor = editor;
}
};
extend(EditorManager, Observable);
@@ -31046,21 +31117,32 @@
*/
init: function(settings) {
var self = this;
settings.spellcheck = false;
- settings.icon = 'none';
+ if (settings.onaction) {
+ settings.icon = 'none';
+ }
+
self._super(settings);
self.addClass('colorbox');
self.on('change keyup postrender', function() {
self.repaintColor(self.value());
});
},
repaintColor: function(value) {
- this.getEl().getElementsByTagName('i')[0].style.background = value;
+ var elm = this.getEl().getElementsByTagName('i')[0];
+
+ if (elm) {
+ try {
+ elm.style.background = value;
+ } catch (ex) {
+ // Ignore
+ }
+ }
},
value: function(value) {
var self = this;
\ No newline at end of file