mirror of
git://develop.git.wordpress.org/
synced 2025-01-17 21:08:44 +01:00
TiinyMCE: update to 4.4.3, changelog: https://www.tinymce.com/docs/changelog/#version443-september12016
Fixes #38081, #38245, #37507, #37808 and #38000. git-svn-id: https://develop.svn.wordpress.org/trunk@38773 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
parent
af80e92ee1
commit
7b3132214e
@ -1257,14 +1257,6 @@ final class _WP_Editors {
|
||||
var init, id, $wrap;
|
||||
|
||||
if ( typeof tinymce !== 'undefined' ) {
|
||||
// Fix RTL
|
||||
tinymce.on( 'addeditor', function( event ) {
|
||||
event.editor.rtl = event.editor.settings.rtl_ui ||
|
||||
( event.editor.editorManager &&
|
||||
event.editor.editorManager.i18n &&
|
||||
event.editor.editorManager.i18n.rtl );
|
||||
}, true );
|
||||
|
||||
for ( id in tinyMCEPreInit.mceInit ) {
|
||||
init = tinyMCEPreInit.mceInit[id];
|
||||
$wrap = tinymce.$( '#wp-' + id + '-wrap' );
|
||||
|
@ -135,7 +135,7 @@ tinymce.PluginManager.add('fullscreen', function(editor) {
|
||||
|
||||
editor.addButton('fullscreen', {
|
||||
tooltip: 'Fullscreen',
|
||||
shortcut: 'Ctrl+Alt+F',
|
||||
shortcut: 'Ctrl+Shift+F',
|
||||
onClick: toggleFullscreen,
|
||||
onPostRender: function() {
|
||||
var self = this;
|
||||
|
@ -1 +1 @@
|
||||
tinymce.PluginManager.add("fullscreen",function(a){function b(){var a,b,c=window,d=document,e=d.body;return e.offsetWidth&&(a=e.offsetWidth,b=e.offsetHeight),c.innerWidth&&c.innerHeight&&(a=c.innerWidth,b=c.innerHeight),{w:a,h:b}}function c(){var a=tinymce.DOM.getViewPort();return{x:a.x,y:a.y}}function d(a){scrollTo(a.x,a.y)}function e(){function e(){m.setStyle(p,"height",b().h-(o.clientHeight-p.clientHeight))}var n,o,p,q,r=document.body,s=document.documentElement;l=!l,o=a.getContainer(),n=o.style,p=a.getContentAreaContainer().firstChild,q=p.style,l?(k=c(),f=q.width,g=q.height,q.width=q.height="100%",i=n.width,j=n.height,n.width=n.height="",m.addClass(r,"mce-fullscreen"),m.addClass(s,"mce-fullscreen"),m.addClass(o,"mce-fullscreen"),m.bind(window,"resize",e),e(),h=e):(q.width=f,q.height=g,i&&(n.width=i),j&&(n.height=j),m.removeClass(r,"mce-fullscreen"),m.removeClass(s,"mce-fullscreen"),m.removeClass(o,"mce-fullscreen"),m.unbind(window,"resize",h),d(k)),a.fire("FullscreenStateChanged",{state:l})}var f,g,h,i,j,k,l=!1,m=tinymce.DOM;return a.settings.inline?void 0:(a.on("init",function(){a.addShortcut("Ctrl+Shift+F","",e)}),a.on("remove",function(){h&&m.unbind(window,"resize",h)}),a.addCommand("mceFullScreen",e),a.addMenuItem("fullscreen",{text:"Fullscreen",shortcut:"Ctrl+Shift+F",selectable:!0,onClick:function(){e(),a.focus()},onPostRender:function(){var b=this;a.on("FullscreenStateChanged",function(a){b.active(a.state)})},context:"view"}),a.addButton("fullscreen",{tooltip:"Fullscreen",shortcut:"Ctrl+Alt+F",onClick:e,onPostRender:function(){var b=this;a.on("FullscreenStateChanged",function(a){b.active(a.state)})}}),{isFullscreen:function(){return l}})});
|
||||
tinymce.PluginManager.add("fullscreen",function(a){function b(){var a,b,c=window,d=document,e=d.body;return e.offsetWidth&&(a=e.offsetWidth,b=e.offsetHeight),c.innerWidth&&c.innerHeight&&(a=c.innerWidth,b=c.innerHeight),{w:a,h:b}}function c(){var a=tinymce.DOM.getViewPort();return{x:a.x,y:a.y}}function d(a){scrollTo(a.x,a.y)}function e(){function e(){m.setStyle(p,"height",b().h-(o.clientHeight-p.clientHeight))}var n,o,p,q,r=document.body,s=document.documentElement;l=!l,o=a.getContainer(),n=o.style,p=a.getContentAreaContainer().firstChild,q=p.style,l?(k=c(),f=q.width,g=q.height,q.width=q.height="100%",i=n.width,j=n.height,n.width=n.height="",m.addClass(r,"mce-fullscreen"),m.addClass(s,"mce-fullscreen"),m.addClass(o,"mce-fullscreen"),m.bind(window,"resize",e),e(),h=e):(q.width=f,q.height=g,i&&(n.width=i),j&&(n.height=j),m.removeClass(r,"mce-fullscreen"),m.removeClass(s,"mce-fullscreen"),m.removeClass(o,"mce-fullscreen"),m.unbind(window,"resize",h),d(k)),a.fire("FullscreenStateChanged",{state:l})}var f,g,h,i,j,k,l=!1,m=tinymce.DOM;return a.settings.inline?void 0:(a.on("init",function(){a.addShortcut("Ctrl+Shift+F","",e)}),a.on("remove",function(){h&&m.unbind(window,"resize",h)}),a.addCommand("mceFullScreen",e),a.addMenuItem("fullscreen",{text:"Fullscreen",shortcut:"Ctrl+Shift+F",selectable:!0,onClick:function(){e(),a.focus()},onPostRender:function(){var b=this;a.on("FullscreenStateChanged",function(a){b.active(a.state)})},context:"view"}),a.addButton("fullscreen",{tooltip:"Fullscreen",shortcut:"Ctrl+Shift+F",onClick:e,onPostRender:function(){var b=this;a.on("FullscreenStateChanged",function(a){b.active(a.state)})}}),{isFullscreen:function(){return l}})});
|
@ -26,6 +26,10 @@ tinymce.PluginManager.add('lists', function(editor) {
|
||||
return node && (/^(OL|UL|DL)$/).test(node.nodeName) && isChildOfBody(node);
|
||||
}
|
||||
|
||||
function isListItemNode(node) {
|
||||
return node && /^(LI|DT|DD)$/.test(node.nodeName);
|
||||
}
|
||||
|
||||
function isFirstChild(node) {
|
||||
return node.parentNode.firstChild == node;
|
||||
}
|
||||
@ -42,6 +46,33 @@ tinymce.PluginManager.add('lists', function(editor) {
|
||||
return elm === editor.getBody();
|
||||
}
|
||||
|
||||
function isTextNode(node) {
|
||||
return node && node.nodeType === 3;
|
||||
}
|
||||
|
||||
function getNormalizedEndPoint(container, offset) {
|
||||
var node = tinymce.dom.RangeUtils.getNode(container, offset);
|
||||
|
||||
if (isListItemNode(container) && isTextNode(node)) {
|
||||
var textNodeOffset = offset >= container.childNodes.length ? node.data.length : 0;
|
||||
return {container: node, offset: textNodeOffset};
|
||||
}
|
||||
|
||||
return {container: container, offset: offset};
|
||||
}
|
||||
|
||||
function normalizeRange(rng) {
|
||||
var outRng = rng.cloneRange();
|
||||
|
||||
var rangeStart = getNormalizedEndPoint(rng.startContainer, rng.startOffset);
|
||||
outRng.setStart(rangeStart.container, rangeStart.offset);
|
||||
|
||||
var rangeEnd = getNormalizedEndPoint(rng.endContainer, rng.endOffset);
|
||||
outRng.setEnd(rangeEnd.container, rangeEnd.offset);
|
||||
|
||||
return outRng;
|
||||
}
|
||||
|
||||
editor.on('init', function() {
|
||||
var dom = editor.dom, selection = editor.selection;
|
||||
|
||||
@ -163,7 +194,7 @@ tinymce.PluginManager.add('lists', function(editor) {
|
||||
rng.setEnd(bookmark.endContainer, bookmark.endOffset);
|
||||
}
|
||||
|
||||
selection.setRng(rng);
|
||||
selection.setRng(normalizeRange(rng));
|
||||
}
|
||||
|
||||
function createNewTextBlock(contentNode, blockName) {
|
||||
@ -224,7 +255,7 @@ tinymce.PluginManager.add('lists', function(editor) {
|
||||
|
||||
function getSelectedListItems() {
|
||||
return tinymce.grep(selection.getSelectedBlocks(), function(block) {
|
||||
return /^(LI|DT|DD)$/.test(block.nodeName);
|
||||
return isListItemNode(block);
|
||||
});
|
||||
}
|
||||
|
||||
@ -298,33 +329,34 @@ tinymce.PluginManager.add('lists', function(editor) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes the all lists in the specified element.
|
||||
*/
|
||||
function normalizeList(element) {
|
||||
tinymce.each(tinymce.grep(dom.select('ol,ul', element)), function(ul) {
|
||||
var sibling, parentNode = ul.parentNode;
|
||||
function normalizeLists(element) {
|
||||
tinymce.each(tinymce.grep(dom.select('ol,ul', element)), normalizeList);
|
||||
}
|
||||
|
||||
// Move UL/OL to previous LI if it's the only child of a LI
|
||||
if (parentNode.nodeName == 'LI' && parentNode.firstChild == ul) {
|
||||
sibling = parentNode.previousSibling;
|
||||
if (sibling && sibling.nodeName == 'LI') {
|
||||
sibling.appendChild(ul);
|
||||
function normalizeList(ul) {
|
||||
var sibling, parentNode = ul.parentNode;
|
||||
|
||||
if (isEmpty(parentNode)) {
|
||||
dom.remove(parentNode);
|
||||
}
|
||||
// Move UL/OL to previous LI if it's the only child of a LI
|
||||
if (parentNode.nodeName == 'LI' && parentNode.firstChild == ul) {
|
||||
sibling = parentNode.previousSibling;
|
||||
if (sibling && sibling.nodeName == 'LI') {
|
||||
sibling.appendChild(ul);
|
||||
|
||||
if (isEmpty(parentNode)) {
|
||||
dom.remove(parentNode);
|
||||
}
|
||||
} else {
|
||||
dom.setStyle(parentNode, 'listStyleType', 'none');
|
||||
}
|
||||
}
|
||||
|
||||
// Append OL/UL to previous LI if it's in a parent OL/UL i.e. old HTML4
|
||||
if (isListNode(parentNode)) {
|
||||
sibling = parentNode.previousSibling;
|
||||
if (sibling && sibling.nodeName == 'LI') {
|
||||
sibling.appendChild(ul);
|
||||
}
|
||||
// Append OL/UL to previous LI if it's in a parent OL/UL i.e. old HTML4
|
||||
if (isListNode(parentNode)) {
|
||||
sibling = parentNode.previousSibling;
|
||||
if (sibling && sibling.nodeName == 'LI') {
|
||||
sibling.appendChild(ul);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function outdent(li) {
|
||||
@ -394,7 +426,7 @@ tinymce.PluginManager.add('lists', function(editor) {
|
||||
}
|
||||
|
||||
splitList(ul, li, newBlock);
|
||||
normalizeList(ul.parentNode);
|
||||
normalizeLists(ul.parentNode);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -664,6 +696,7 @@ tinymce.PluginManager.add('lists', function(editor) {
|
||||
}
|
||||
|
||||
splitList(rootList, li);
|
||||
normalizeLists(rootList.parentNode);
|
||||
});
|
||||
|
||||
moveToBookmark(bookmark);
|
||||
@ -711,118 +744,135 @@ tinymce.PluginManager.add('lists', function(editor) {
|
||||
return false;
|
||||
}
|
||||
|
||||
self.backspaceDelete = function(isForward) {
|
||||
function findNextCaretContainer(rng, isForward) {
|
||||
var node = rng.startContainer, offset = rng.startOffset;
|
||||
var nonEmptyBlocks, walker;
|
||||
function findNextCaretContainer(rng, isForward) {
|
||||
var node = rng.startContainer, offset = rng.startOffset;
|
||||
var nonEmptyBlocks, walker;
|
||||
|
||||
if (node.nodeType == 3 && (isForward ? offset < node.data.length : offset > 0)) {
|
||||
if (node.nodeType == 3 && (isForward ? offset < node.data.length : offset > 0)) {
|
||||
return node;
|
||||
}
|
||||
|
||||
nonEmptyBlocks = editor.schema.getNonEmptyElements();
|
||||
if (node.nodeType == 1) {
|
||||
node = tinymce.dom.RangeUtils.getNode(node, offset);
|
||||
}
|
||||
|
||||
walker = new tinymce.dom.TreeWalker(node, editor.getBody());
|
||||
|
||||
// Delete at <li>|<br></li> then jump over the bogus br
|
||||
if (isForward) {
|
||||
if (isBogusBr(node)) {
|
||||
walker.next();
|
||||
}
|
||||
}
|
||||
|
||||
while ((node = walker[isForward ? 'next' : 'prev2']())) {
|
||||
if (node.nodeName == 'LI' && !node.hasChildNodes()) {
|
||||
return node;
|
||||
}
|
||||
|
||||
nonEmptyBlocks = editor.schema.getNonEmptyElements();
|
||||
if (node.nodeType == 1) {
|
||||
node = tinymce.dom.RangeUtils.getNode(node, offset);
|
||||
if (nonEmptyBlocks[node.nodeName]) {
|
||||
return node;
|
||||
}
|
||||
|
||||
walker = new tinymce.dom.TreeWalker(node, editor.getBody());
|
||||
|
||||
// Delete at <li>|<br></li> then jump over the bogus br
|
||||
if (isForward) {
|
||||
if (isBogusBr(node)) {
|
||||
walker.next();
|
||||
}
|
||||
if (node.nodeType == 3 && node.data.length > 0) {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while ((node = walker[isForward ? 'next' : 'prev2']())) {
|
||||
if (node.nodeName == 'LI' && !node.hasChildNodes()) {
|
||||
return node;
|
||||
}
|
||||
function mergeLiElements(fromElm, toElm) {
|
||||
var node, listNode, ul = fromElm.parentNode;
|
||||
|
||||
if (nonEmptyBlocks[node.nodeName]) {
|
||||
return node;
|
||||
}
|
||||
if (!isChildOfBody(fromElm) || !isChildOfBody(toElm)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (node.nodeType == 3 && node.data.length > 0) {
|
||||
return node;
|
||||
}
|
||||
if (isListNode(toElm.lastChild)) {
|
||||
listNode = toElm.lastChild;
|
||||
}
|
||||
|
||||
if (ul == toElm.lastChild) {
|
||||
if (isBr(ul.previousSibling)) {
|
||||
dom.remove(ul.previousSibling);
|
||||
}
|
||||
}
|
||||
|
||||
function mergeLiElements(fromElm, toElm) {
|
||||
var node, listNode, ul = fromElm.parentNode;
|
||||
node = toElm.lastChild;
|
||||
if (node && isBr(node) && fromElm.hasChildNodes()) {
|
||||
dom.remove(node);
|
||||
}
|
||||
|
||||
if (!isChildOfBody(fromElm) || !isChildOfBody(toElm)) {
|
||||
return;
|
||||
}
|
||||
if (isEmpty(toElm, true)) {
|
||||
dom.$(toElm).empty();
|
||||
}
|
||||
|
||||
if (isListNode(toElm.lastChild)) {
|
||||
listNode = toElm.lastChild;
|
||||
}
|
||||
|
||||
if (ul == toElm.lastChild) {
|
||||
if (isBr(ul.previousSibling)) {
|
||||
dom.remove(ul.previousSibling);
|
||||
}
|
||||
}
|
||||
|
||||
node = toElm.lastChild;
|
||||
if (node && isBr(node) && fromElm.hasChildNodes()) {
|
||||
dom.remove(node);
|
||||
}
|
||||
|
||||
if (isEmpty(toElm, true)) {
|
||||
dom.$(toElm).empty();
|
||||
}
|
||||
|
||||
if (!isEmpty(fromElm, true)) {
|
||||
while ((node = fromElm.firstChild)) {
|
||||
toElm.appendChild(node);
|
||||
}
|
||||
}
|
||||
|
||||
if (listNode) {
|
||||
toElm.appendChild(listNode);
|
||||
}
|
||||
|
||||
dom.remove(fromElm);
|
||||
|
||||
if (isEmpty(ul) && !isEditorBody(ul)) {
|
||||
dom.remove(ul);
|
||||
if (!isEmpty(fromElm, true)) {
|
||||
while ((node = fromElm.firstChild)) {
|
||||
toElm.appendChild(node);
|
||||
}
|
||||
}
|
||||
|
||||
if (selection.isCollapsed()) {
|
||||
var li = dom.getParent(selection.getStart(), 'LI'), ul, rng, otherLi;
|
||||
if (listNode) {
|
||||
toElm.appendChild(listNode);
|
||||
}
|
||||
|
||||
if (li) {
|
||||
ul = li.parentNode;
|
||||
if (isEditorBody(ul) && dom.isEmpty(ul)) {
|
||||
dom.remove(fromElm);
|
||||
|
||||
if (isEmpty(ul) && !isEditorBody(ul)) {
|
||||
dom.remove(ul);
|
||||
}
|
||||
}
|
||||
|
||||
function backspaceDeleteCaret(isForward) {
|
||||
var li = dom.getParent(selection.getStart(), 'LI'), ul, rng, otherLi;
|
||||
|
||||
if (li) {
|
||||
ul = li.parentNode;
|
||||
if (isEditorBody(ul) && dom.isEmpty(ul)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
rng = normalizeRange(selection.getRng(true));
|
||||
otherLi = dom.getParent(findNextCaretContainer(rng, isForward), 'LI');
|
||||
|
||||
if (otherLi && otherLi != li) {
|
||||
var bookmark = createBookmark(rng);
|
||||
|
||||
if (isForward) {
|
||||
mergeLiElements(otherLi, li);
|
||||
} else {
|
||||
mergeLiElements(li, otherLi);
|
||||
}
|
||||
|
||||
moveToBookmark(bookmark);
|
||||
|
||||
return true;
|
||||
} else if (!otherLi) {
|
||||
if (!isForward && removeList(ul.nodeName)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
rng = selection.getRng(true);
|
||||
otherLi = dom.getParent(findNextCaretContainer(rng, isForward), 'LI');
|
||||
|
||||
if (otherLi && otherLi != li) {
|
||||
var bookmark = createBookmark(rng);
|
||||
|
||||
if (isForward) {
|
||||
mergeLiElements(otherLi, li);
|
||||
} else {
|
||||
mergeLiElements(li, otherLi);
|
||||
}
|
||||
|
||||
moveToBookmark(bookmark);
|
||||
|
||||
return true;
|
||||
} else if (!otherLi) {
|
||||
if (!isForward && removeList(ul.nodeName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function backspaceDeleteRange() {
|
||||
var startListParent = editor.dom.getParent(editor.selection.getStart(), 'LI,DT,DD');
|
||||
|
||||
if (startListParent || getSelectedListItems().length > 0) {
|
||||
editor.undoManager.transact(function() {
|
||||
editor.execCommand('Delete');
|
||||
normalizeLists(editor.getBody());
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
self.backspaceDelete = function(isForward) {
|
||||
return selection.isCollapsed() ? backspaceDeleteCaret(isForward) : backspaceDeleteRange();
|
||||
};
|
||||
|
||||
editor.on('BeforeExecCommand', function(e) {
|
||||
|
File diff suppressed because one or more lines are too long
@ -264,7 +264,7 @@ define("tinymce/pasteplugin/SmartPaste", [
|
||||
"tinymce/util/Tools"
|
||||
], function (Tools) {
|
||||
var isAbsoluteUrl = function (url) {
|
||||
return /^https?:\/\/[\w\?\-\/+=.&%]+$/i.test(url);
|
||||
return /^https?:\/\/[\w\?\-\/+=.&%@~#]+$/i.test(url);
|
||||
};
|
||||
|
||||
var isImageUrl = function (url) {
|
||||
@ -1766,6 +1766,15 @@ define("tinymce/pasteplugin/Plugin", [
|
||||
editor.focus();
|
||||
}
|
||||
|
||||
// draw back if power version is requested and registered
|
||||
if (/(^|[ ,])powerpaste([, ]|$)/.test(settings.plugins) && PluginManager.get('powerpaste')) {
|
||||
/*eslint no-console:0 */
|
||||
if (typeof console !== "undefined" && console.log) {
|
||||
console.log("PowerPaste is incompatible with Paste plugin! Remove 'paste' from the 'plugins' option.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
self.clipboard = clipboard = new Clipboard(editor);
|
||||
self.quirks = new Quirks(editor);
|
||||
self.wordFilter = new WordFilter(editor);
|
||||
|
File diff suppressed because one or more lines are too long
@ -124,7 +124,7 @@
|
||||
editor.undoManager.add();
|
||||
|
||||
editor.undoManager.transact( function() {
|
||||
node.insertData( offset, '\u200b' );
|
||||
node.insertData( offset, '\uFEFF' );
|
||||
|
||||
node = node.splitText( startOffset );
|
||||
zero = node.splitText( offset - startOffset );
|
||||
@ -145,7 +145,7 @@
|
||||
var offset;
|
||||
|
||||
if ( zero ) {
|
||||
offset = zero.data.indexOf( '\u200b' );
|
||||
offset = zero.data.indexOf( '\uFEFF' );
|
||||
|
||||
if ( offset !== -1 ) {
|
||||
zero.deleteData( offset, offset + 1 );
|
||||
|
@ -81,13 +81,56 @@ var defineGlobal = function (id, ref) {
|
||||
define(id, [], function () { return ref; });
|
||||
};
|
||||
/*jsc
|
||||
["tinymce/inlite/Theme","global!tinymce.ThemeManager","global!tinymce.util.Delay","tinymce/inlite/ui/Panel","tinymce/inlite/ui/Buttons","tinymce/inlite/core/SkinLoader","tinymce/inlite/core/SelectionMatcher","tinymce/inlite/core/ElementMatcher","tinymce/inlite/core/Matcher","tinymce/inlite/alien/Arr","tinymce/inlite/core/PredicateId","global!tinymce.util.Tools","global!tinymce.ui.Factory","global!tinymce.DOM","tinymce/inlite/ui/Toolbar","tinymce/inlite/ui/Forms","tinymce/inlite/core/Measure","tinymce/inlite/core/Layout","tinymce/inlite/file/Conversions","tinymce/inlite/file/Picker","tinymce/inlite/core/Actions","global!tinymce.EditorManager","global!tinymce.util.Promise","tinymce/inlite/alien/Uuid","tinymce/inlite/alien/Unlink","tinymce/inlite/core/UrlType","global!tinymce.geom.Rect","tinymce/inlite/core/Convert","tinymce/inlite/alien/Bookmark","global!tinymce.dom.TreeWalker","global!tinymce.dom.RangeUtils"]
|
||||
["tinymce/inlite/Theme","global!tinymce.ThemeManager","global!tinymce.util.Delay","tinymce/inlite/ui/Panel","tinymce/inlite/ui/Buttons","tinymce/inlite/core/SkinLoader","tinymce/inlite/core/SelectionMatcher","tinymce/inlite/core/ElementMatcher","tinymce/inlite/core/Matcher","tinymce/inlite/alien/Arr","tinymce/inlite/alien/EditorSettings","tinymce/inlite/core/PredicateId","global!tinymce.util.Tools","global!tinymce.ui.Factory","global!tinymce.DOM","tinymce/inlite/ui/Toolbar","tinymce/inlite/ui/Forms","tinymce/inlite/core/Measure","tinymce/inlite/core/Layout","tinymce/inlite/alien/Type","tinymce/inlite/file/Conversions","tinymce/inlite/file/Picker","tinymce/inlite/core/Actions","global!tinymce.EditorManager","global!tinymce.util.Promise","tinymce/inlite/alien/Uuid","tinymce/inlite/alien/Unlink","tinymce/inlite/core/UrlType","global!tinymce.geom.Rect","tinymce/inlite/core/Convert","tinymce/inlite/alien/Bookmark","global!tinymce.dom.TreeWalker","global!tinymce.dom.RangeUtils"]
|
||||
jsc*/
|
||||
defineGlobal("global!tinymce.ThemeManager", tinymce.ThemeManager);
|
||||
defineGlobal("global!tinymce.util.Delay", tinymce.util.Delay);
|
||||
defineGlobal("global!tinymce.util.Tools", tinymce.util.Tools);
|
||||
defineGlobal("global!tinymce.ui.Factory", tinymce.ui.Factory);
|
||||
defineGlobal("global!tinymce.DOM", tinymce.DOM);
|
||||
/**
|
||||
* Type.js
|
||||
*
|
||||
* Released under LGPL License.
|
||||
* Copyright (c) 1999-2016 Ephox Corp. All rights reserved
|
||||
*
|
||||
* License: http://www.tinymce.com/license
|
||||
* Contributing: http://www.tinymce.com/contributing
|
||||
*/
|
||||
|
||||
define('tinymce/inlite/alien/Type', [
|
||||
], function () {
|
||||
var isType = function (type) {
|
||||
return function (value) {
|
||||
return typeof value === type;
|
||||
};
|
||||
};
|
||||
|
||||
var isArray = function (value) {
|
||||
return Array.isArray(value);
|
||||
};
|
||||
|
||||
var isNull = function (value) {
|
||||
return value === null;
|
||||
};
|
||||
|
||||
var isObject = function (predicate) {
|
||||
return function (value) {
|
||||
return !isNull(value) && !isArray(value) && predicate(value);
|
||||
};
|
||||
};
|
||||
|
||||
return {
|
||||
isString: isType("string"),
|
||||
isNumber: isType("number"),
|
||||
isBoolean: isType("boolean"),
|
||||
isFunction: isType("function"),
|
||||
isObject: isObject(isType("object")),
|
||||
isNull: isNull,
|
||||
isArray: isArray
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* Toolbar.js
|
||||
*
|
||||
@ -100,8 +143,9 @@ defineGlobal("global!tinymce.DOM", tinymce.DOM);
|
||||
|
||||
define('tinymce/inlite/ui/Toolbar', [
|
||||
'global!tinymce.util.Tools',
|
||||
'global!tinymce.ui.Factory'
|
||||
], function (Tools, Factory) {
|
||||
'global!tinymce.ui.Factory',
|
||||
'tinymce/inlite/alien/Type'
|
||||
], function (Tools, Factory, Type) {
|
||||
var setActiveItem = function (item, name) {
|
||||
return function(state, args) {
|
||||
var nodeName, i = args.parents.length;
|
||||
@ -161,6 +205,16 @@ define('tinymce/inlite/ui/Toolbar', [
|
||||
};
|
||||
};
|
||||
|
||||
var itemsToArray = function (items) {
|
||||
if (Type.isArray(items)) {
|
||||
return items;
|
||||
} else if (Type.isString(items)) {
|
||||
return items.split(/[ ,]/);
|
||||
}
|
||||
|
||||
return [];
|
||||
};
|
||||
|
||||
var create = function (editor, name, items) {
|
||||
var toolbarItems = [], buttonGroup;
|
||||
|
||||
@ -168,7 +222,7 @@ define('tinymce/inlite/ui/Toolbar', [
|
||||
return;
|
||||
}
|
||||
|
||||
Tools.each(items.split(/[ ,]/), function(item) {
|
||||
Tools.each(itemsToArray(items), function(item) {
|
||||
var itemName;
|
||||
|
||||
if (item == '|') {
|
||||
@ -179,12 +233,12 @@ define('tinymce/inlite/ui/Toolbar', [
|
||||
toolbarItems.push(item);
|
||||
buttonGroup = null;
|
||||
} else {
|
||||
if (!buttonGroup) {
|
||||
buttonGroup = {type: 'buttongroup', items: []};
|
||||
toolbarItems.push(buttonGroup);
|
||||
}
|
||||
|
||||
if (editor.buttons[item]) {
|
||||
if (!buttonGroup) {
|
||||
buttonGroup = {type: 'buttongroup', items: []};
|
||||
toolbarItems.push(buttonGroup);
|
||||
}
|
||||
|
||||
itemName = item;
|
||||
item = editor.buttons[itemName];
|
||||
|
||||
@ -897,10 +951,88 @@ define('tinymce/inlite/core/Layout', [
|
||||
return panelRect;
|
||||
};
|
||||
|
||||
var defaultHandler = function (rects) {
|
||||
return rects.panelRect;
|
||||
};
|
||||
|
||||
return {
|
||||
calcInsert: calcInsert,
|
||||
calc: calc,
|
||||
userConstrain: userConstrain
|
||||
userConstrain: userConstrain,
|
||||
defaultHandler: defaultHandler
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* EditorSettings.js
|
||||
*
|
||||
* Released under LGPL License.
|
||||
* Copyright (c) 1999-2016 Ephox Corp. All rights reserved
|
||||
*
|
||||
* License: http://www.tinymce.com/license
|
||||
* Contributing: http://www.tinymce.com/contributing
|
||||
*/
|
||||
|
||||
define('tinymce/inlite/alien/EditorSettings', [
|
||||
'tinymce/inlite/alien/Type'
|
||||
], function (Type) {
|
||||
var validDefaultOrDie = function (value, predicate) {
|
||||
if (predicate(value)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
throw new Error('Default value doesn\'t match requested type.');
|
||||
};
|
||||
|
||||
var getByTypeOr = function (predicate) {
|
||||
return function (editor, name, defaultValue) {
|
||||
var settings = editor.settings;
|
||||
validDefaultOrDie(defaultValue, predicate);
|
||||
return name in settings && predicate(settings[name]) ? settings[name] : defaultValue;
|
||||
};
|
||||
};
|
||||
|
||||
var splitNoEmpty = function (str, delim) {
|
||||
return str.split(delim).filter(function (item) {
|
||||
return item.length > 0;
|
||||
});
|
||||
};
|
||||
|
||||
var itemsToArray = function (value, defaultValue) {
|
||||
var stringToItemsArray = function (value) {
|
||||
return typeof value === 'string' ? splitNoEmpty(value, /[ ,]/) : value;
|
||||
};
|
||||
|
||||
var boolToItemsArray = function (value, defaultValue) {
|
||||
return value === false ? [ ] : defaultValue;
|
||||
};
|
||||
|
||||
if (Type.isArray(value)) {
|
||||
return value;
|
||||
} else if (Type.isString(value)) {
|
||||
return stringToItemsArray(value);
|
||||
} else if (Type.isBoolean(value)) {
|
||||
return boolToItemsArray(value, defaultValue);
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
};
|
||||
|
||||
var getToolbarItemsOr = function (predicate) {
|
||||
return function (editor, name, defaultValue) {
|
||||
var value = name in editor.settings ? editor.settings[name] : defaultValue;
|
||||
validDefaultOrDie(defaultValue, predicate);
|
||||
return itemsToArray(value, defaultValue);
|
||||
};
|
||||
};
|
||||
|
||||
return {
|
||||
// TODO: Add Option based getString, getBool if merged with core
|
||||
getStringOr: getByTypeOr(Type.isString),
|
||||
getBoolOr: getByTypeOr(Type.isBoolean),
|
||||
getNumberOr: getByTypeOr(Type.isNumber),
|
||||
getHandlerOr: getByTypeOr(Type.isFunction),
|
||||
getToolbarItemsOr: getToolbarItemsOr(Type.isArray)
|
||||
};
|
||||
});
|
||||
|
||||
@ -921,11 +1053,12 @@ define('tinymce/inlite/ui/Panel', [
|
||||
'tinymce/inlite/ui/Toolbar',
|
||||
'tinymce/inlite/ui/Forms',
|
||||
'tinymce/inlite/core/Measure',
|
||||
'tinymce/inlite/core/Layout'
|
||||
], function (Tools, Factory, DOM, Toolbar, Forms, Measure, Layout) {
|
||||
'tinymce/inlite/core/Layout',
|
||||
'tinymce/inlite/alien/EditorSettings'
|
||||
], function (Tools, Factory, DOM, Toolbar, Forms, Measure, Layout, EditorSettings) {
|
||||
return function () {
|
||||
var DEFAULT_TEXT_SELECTION_ITEMS = 'bold italic | quicklink h2 h3 blockquote';
|
||||
var DEFAULT_INSERT_TOOLBAR_ITEMS = 'quickimage quicktable';
|
||||
var DEFAULT_TEXT_SELECTION_ITEMS = ['bold', 'italic', '|', 'quicklink', 'h2', 'h3', 'blockquote'];
|
||||
var DEFAULT_INSERT_TOOLBAR_ITEMS = ['quickimage', 'quicktable'];
|
||||
var panel, currentRect;
|
||||
|
||||
var createToolbars = function (editor, toolbars) {
|
||||
@ -934,23 +1067,22 @@ define('tinymce/inlite/ui/Panel', [
|
||||
});
|
||||
};
|
||||
|
||||
var getTextSelectionToolbarItems = function (settings) {
|
||||
var value = settings.selection_toolbar;
|
||||
return value ? value : DEFAULT_TEXT_SELECTION_ITEMS;
|
||||
var getTextSelectionToolbarItems = function (editor) {
|
||||
return EditorSettings.getToolbarItemsOr(editor, 'selection_toolbar', DEFAULT_TEXT_SELECTION_ITEMS);
|
||||
};
|
||||
|
||||
var getInsertToolbarItems = function (settings) {
|
||||
var value = settings.insert_toolbar;
|
||||
return value ? value : DEFAULT_INSERT_TOOLBAR_ITEMS;
|
||||
var getInsertToolbarItems = function (editor) {
|
||||
return EditorSettings.getToolbarItemsOr(editor, 'insert_toolbar', DEFAULT_INSERT_TOOLBAR_ITEMS);
|
||||
};
|
||||
|
||||
var hasToolbarItems = function (toolbar) {
|
||||
return toolbar.items().length > 0;
|
||||
};
|
||||
|
||||
var create = function (editor, toolbars) {
|
||||
var items, settings = editor.settings;
|
||||
|
||||
items = createToolbars(editor, toolbars);
|
||||
items = items.concat([
|
||||
Toolbar.create(editor, 'text', getTextSelectionToolbarItems(settings)),
|
||||
Toolbar.create(editor, 'insert', getInsertToolbarItems(settings)),
|
||||
var items = createToolbars(editor, toolbars).concat([
|
||||
Toolbar.create(editor, 'text', getTextSelectionToolbarItems(editor)),
|
||||
Toolbar.create(editor, 'insert', getInsertToolbarItems(editor)),
|
||||
Forms.createQuickLinkForm(editor, hide)
|
||||
]);
|
||||
|
||||
@ -966,7 +1098,7 @@ define('tinymce/inlite/ui/Panel', [
|
||||
autofix: true,
|
||||
fixed: true,
|
||||
border: 1,
|
||||
items: items,
|
||||
items: Tools.grep(items, hasToolbarItems),
|
||||
oncancel: function() {
|
||||
editor.focus();
|
||||
}
|
||||
@ -1016,7 +1148,10 @@ define('tinymce/inlite/ui/Panel', [
|
||||
if (toolbars.length > 0) {
|
||||
toolbars[0].show();
|
||||
panel.reflow();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
var showPanelAt = function (panel, id, editor, targetRect) {
|
||||
@ -1024,9 +1159,13 @@ define('tinymce/inlite/ui/Panel', [
|
||||
|
||||
showPanel(panel);
|
||||
panel.items().hide();
|
||||
showToolbar(panel, id);
|
||||
|
||||
userConstainHandler = editor.settings.inline_toolbar_position_handler;
|
||||
if (!showToolbar(panel, id)) {
|
||||
hide(panel);
|
||||
return;
|
||||
}
|
||||
|
||||
userConstainHandler = EditorSettings.getHandlerOr(editor, 'inline_toolbar_position_handler', Layout.defaultHandler);
|
||||
contentAreaRect = Measure.getContentAreaRect(editor);
|
||||
panelRect = DOM.getRect(panel.getEl());
|
||||
|
||||
@ -1040,7 +1179,6 @@ define('tinymce/inlite/ui/Panel', [
|
||||
panelRect = result.rect;
|
||||
currentRect = targetRect;
|
||||
movePanelTo(panel, Layout.userConstrain(userConstainHandler, targetRect, contentAreaRect, panelRect));
|
||||
|
||||
togglePositionClass(panel, result.position);
|
||||
} else {
|
||||
hide(panel);
|
||||
@ -1054,7 +1192,11 @@ define('tinymce/inlite/ui/Panel', [
|
||||
var showForm = function (editor, id) {
|
||||
if (panel) {
|
||||
panel.items().hide();
|
||||
showToolbar(panel, id);
|
||||
|
||||
if (!showToolbar(panel, id)) {
|
||||
hide(panel);
|
||||
return;
|
||||
}
|
||||
|
||||
var contentAreaRect, panelRect, result, userConstainHandler;
|
||||
|
||||
@ -1062,7 +1204,7 @@ define('tinymce/inlite/ui/Panel', [
|
||||
panel.items().hide();
|
||||
showToolbar(panel, id);
|
||||
|
||||
userConstainHandler = editor.settings.inline_toolbar_position_handler;
|
||||
userConstainHandler = EditorSettings.getHandlerOr(editor, 'inline_toolbar_position_handler', Layout.defaultHandler);
|
||||
contentAreaRect = Measure.getContentAreaRect(editor);
|
||||
panelRect = DOM.getRect(panel.getEl());
|
||||
|
||||
@ -1071,7 +1213,6 @@ define('tinymce/inlite/ui/Panel', [
|
||||
if (result) {
|
||||
panelRect = result.rect;
|
||||
movePanelTo(panel, Layout.userConstrain(userConstainHandler, currentRect, contentAreaRect, panelRect));
|
||||
|
||||
togglePositionClass(panel, result.position);
|
||||
}
|
||||
}
|
||||
@ -1305,9 +1446,18 @@ define('tinymce/inlite/core/SkinLoader', [
|
||||
}
|
||||
};
|
||||
|
||||
var load = function (editor, skin, callback) {
|
||||
var baseUrl = EditorManager.baseURL;
|
||||
var skinUrl = baseUrl + '/skins/' + skin;
|
||||
var urlFromName = function (name) {
|
||||
var prefix = EditorManager.baseURL + '/skins/';
|
||||
return name ? prefix + name : prefix + 'lightgray';
|
||||
};
|
||||
|
||||
var toAbsoluteUrl = function (editor, url) {
|
||||
return editor.documentBaseURI.toAbsolute(url);
|
||||
};
|
||||
|
||||
var load = function (editor, callback) {
|
||||
var settings = editor.settings;
|
||||
var skinUrl = settings.skin_url ? toAbsoluteUrl(editor, settings.skin_url) : urlFromName(settings.skin);
|
||||
|
||||
var done = function () {
|
||||
fireSkinLoaded(editor, callback);
|
||||
@ -1544,8 +1694,9 @@ define('tinymce/inlite/Theme', [
|
||||
'tinymce/inlite/core/ElementMatcher',
|
||||
'tinymce/inlite/core/Matcher',
|
||||
'tinymce/inlite/alien/Arr',
|
||||
'tinymce/inlite/alien/EditorSettings',
|
||||
'tinymce/inlite/core/PredicateId'
|
||||
], function(ThemeManager, Delay, Panel, Buttons, SkinLoader, SelectionMatcher, ElementMatcher, Matcher, Arr, PredicateId) {
|
||||
], function(ThemeManager, Delay, Panel, Buttons, SkinLoader, SelectionMatcher, ElementMatcher, Matcher, Arr, EditorSettings, PredicateId) {
|
||||
var getSelectionElements = function (editor) {
|
||||
var node = editor.selection.getNode();
|
||||
var elms = editor.dom.getParents(node);
|
||||
@ -1644,9 +1795,7 @@ define('tinymce/inlite/Theme', [
|
||||
};
|
||||
|
||||
var renderInlineUI = function (editor, panel) {
|
||||
var skinName = editor.settings.skin || 'lightgray';
|
||||
|
||||
SkinLoader.load(editor, skinName, function () {
|
||||
SkinLoader.load(editor, function () {
|
||||
bindContextualToolbarsEvents(editor, panel);
|
||||
overrideLinkShortcut(editor, panel);
|
||||
});
|
||||
|
File diff suppressed because one or more lines are too long
@ -1,4 +1,4 @@
|
||||
// 4.4.1 (2016-07-26)
|
||||
// 4.4.3 (2016-09-01)
|
||||
|
||||
/**
|
||||
* Compiled inline version. (Library mode)
|
||||
@ -888,6 +888,11 @@ define("tinymce/Env", [], function() {
|
||||
*/
|
||||
ceFalse: (ie === false || ie > 8),
|
||||
|
||||
/**
|
||||
* Constant if CSP mode is possible or not. Meaning we can't use script urls for the iframe.
|
||||
*/
|
||||
canHaveCSP: (ie === false || ie > 11),
|
||||
|
||||
desktop: !phone && !tablet,
|
||||
windowsPhone: windowsPhone
|
||||
};
|
||||
@ -10001,16 +10006,17 @@ define("tinymce/dom/NodeType", [], function() {
|
||||
*/
|
||||
|
||||
/**
|
||||
* ....
|
||||
* Utility functions for working with zero width space
|
||||
* characters used as character containers etc.
|
||||
*
|
||||
* @private
|
||||
* @class tinymce.text.Zwsp
|
||||
* @example
|
||||
* var isZwsp = Zwsp.isZwsp('\u200b');
|
||||
* var abc = Zwsp.trim('a\u200bc');
|
||||
* var isZwsp = Zwsp.isZwsp('\uFEFF');
|
||||
* var abc = Zwsp.trim('a\uFEFFc');
|
||||
*/
|
||||
define("tinymce/text/Zwsp", [], function() {
|
||||
var ZWSP = '\u200b';
|
||||
var ZWSP = '\uFEFF';
|
||||
|
||||
function isZwsp(chr) {
|
||||
return chr == ZWSP;
|
||||
@ -10069,6 +10075,30 @@ define("tinymce/caret/CaretContainer", [
|
||||
return isCaretContainerBlock(node) || isCaretContainerInline(node);
|
||||
}
|
||||
|
||||
function removeNode(node) {
|
||||
var parentNode = node.parentNode;
|
||||
if (parentNode) {
|
||||
parentNode.removeChild(node);
|
||||
}
|
||||
}
|
||||
|
||||
function getNodeValue(node) {
|
||||
try {
|
||||
return node.nodeValue;
|
||||
} catch (ex) {
|
||||
// IE sometimes produces "Invalid argument" on nodes
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
function setNodeValue(node, text) {
|
||||
if (text.length === 0) {
|
||||
removeNode(node);
|
||||
} else {
|
||||
node.nodeValue = text;
|
||||
}
|
||||
}
|
||||
|
||||
function insertInline(node, before) {
|
||||
var doc, sibling, textNode, parentNode;
|
||||
|
||||
@ -10136,28 +10166,17 @@ define("tinymce/caret/CaretContainer", [
|
||||
}
|
||||
|
||||
function remove(caretContainerNode) {
|
||||
var text;
|
||||
|
||||
if (isElement(caretContainerNode) && isCaretContainer(caretContainerNode)) {
|
||||
if (caretContainerNode.innerHTML != ' ') {
|
||||
caretContainerNode.removeAttribute('data-mce-caret');
|
||||
} else {
|
||||
if (caretContainerNode.parentNode) {
|
||||
caretContainerNode.parentNode.removeChild(caretContainerNode);
|
||||
}
|
||||
removeNode(caretContainerNode);
|
||||
}
|
||||
}
|
||||
|
||||
if (isText(caretContainerNode)) {
|
||||
text = Zwsp.trim(caretContainerNode.data);
|
||||
|
||||
if (text.length === 0) {
|
||||
if (caretContainerNode.parentNode) {
|
||||
caretContainerNode.parentNode.removeChild(caretContainerNode);
|
||||
}
|
||||
}
|
||||
|
||||
caretContainerNode.nodeValue = text;
|
||||
var text = Zwsp.trim(getNodeValue(caretContainerNode));
|
||||
setNodeValue(caretContainerNode, text);
|
||||
}
|
||||
}
|
||||
|
||||
@ -14542,7 +14561,7 @@ define("tinymce/dom/Serializer", [
|
||||
|
||||
// Nodes needs to be attached to something in WebKit/Opera
|
||||
// This fix will make DOM ranges and make Sizzle happy!
|
||||
impl = node.ownerDocument.implementation;
|
||||
impl = document.implementation;
|
||||
if (impl.createHTMLDocument) {
|
||||
// Create an empty HTML document
|
||||
doc = impl.createHTMLDocument("");
|
||||
@ -18429,7 +18448,7 @@ define("tinymce/dom/ElementUtils", [
|
||||
var name = attr.nodeName.toLowerCase();
|
||||
|
||||
// Don't compare internal attributes or style
|
||||
if (name.indexOf('_') !== 0 && name !== 'style' && name !== 'data-mce-style' && name != 'data-mce-fragment') {
|
||||
if (name.indexOf('_') !== 0 && name !== 'style' && name.indexOf('data-') !== 0) {
|
||||
attribs[name] = dom.getAttrib(node, name);
|
||||
}
|
||||
});
|
||||
@ -20615,7 +20634,8 @@ define("tinymce/Formatter", [
|
||||
// Check for non internal attributes
|
||||
attrs = dom.getAttribs(node);
|
||||
for (i = 0; i < attrs.length; i++) {
|
||||
if (attrs[i].nodeName.indexOf('_') !== 0) {
|
||||
var attrName = attrs[i].nodeName;
|
||||
if (attrName.indexOf('_') !== 0 && attrName.indexOf('data-') !== 0) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
@ -26366,14 +26386,15 @@ define("tinymce/ui/Collection", [
|
||||
* @class tinymce.ui.DomUtils
|
||||
*/
|
||||
define("tinymce/ui/DomUtils", [
|
||||
"tinymce/Env",
|
||||
"tinymce/util/Tools",
|
||||
"tinymce/dom/DOMUtils"
|
||||
], function(Tools, DOMUtils) {
|
||||
], function(Env, Tools, DOMUtils) {
|
||||
"use strict";
|
||||
|
||||
var count = 0;
|
||||
|
||||
return {
|
||||
var funcs = {
|
||||
id: function() {
|
||||
return 'mceu_' + (count++);
|
||||
},
|
||||
@ -26421,7 +26442,11 @@ define("tinymce/ui/DomUtils", [
|
||||
},
|
||||
|
||||
getPos: function(elm, root) {
|
||||
return DOMUtils.DOM.getPos(elm, root);
|
||||
return DOMUtils.DOM.getPos(elm, root || funcs.getContainer());
|
||||
},
|
||||
|
||||
getContainer: function () {
|
||||
return Env.container ? Env.container : document.body;
|
||||
},
|
||||
|
||||
getViewPort: function(win) {
|
||||
@ -26473,6 +26498,8 @@ define("tinymce/ui/DomUtils", [
|
||||
DOMUtils.DOM.setHTML(elm, html);
|
||||
}
|
||||
};
|
||||
|
||||
return funcs;
|
||||
});
|
||||
|
||||
// Included from: js/tinymce/classes/ui/BoxUtils.js
|
||||
@ -26971,7 +26998,7 @@ define("tinymce/ui/Control", [
|
||||
* @return {Element} HTML DOM element to render into.
|
||||
*/
|
||||
getContainerElm: function() {
|
||||
return document.body;
|
||||
return DomUtils.getContainer();
|
||||
},
|
||||
|
||||
/**
|
||||
@ -35594,6 +35621,90 @@ define("tinymce/caret/LineUtils", [
|
||||
};
|
||||
});
|
||||
|
||||
// Included from: js/tinymce/classes/dom/MousePosition.js
|
||||
|
||||
/**
|
||||
* MousePosition.js
|
||||
*
|
||||
* Released under LGPL License.
|
||||
* Copyright (c) 1999-2016 Ephox Corp. All rights reserved
|
||||
*
|
||||
* License: http://www.tinymce.com/license
|
||||
* Contributing: http://www.tinymce.com/contributing
|
||||
*/
|
||||
|
||||
/**
|
||||
* This module calculates an absolute coordinate inside the editor body for both local and global mouse events.
|
||||
*
|
||||
* @private
|
||||
* @class tinymce.dom.MousePosition
|
||||
*/
|
||||
define("tinymce/dom/MousePosition", [
|
||||
], function() {
|
||||
var getAbsolutePosition = function (elm) {
|
||||
var doc, docElem, win, clientRect;
|
||||
|
||||
clientRect = elm.getBoundingClientRect();
|
||||
doc = elm.ownerDocument;
|
||||
docElem = doc.documentElement;
|
||||
win = doc.defaultView;
|
||||
|
||||
return {
|
||||
top: clientRect.top + win.pageYOffset - docElem.clientTop,
|
||||
left: clientRect.left + win.pageXOffset - docElem.clientLeft
|
||||
};
|
||||
};
|
||||
|
||||
var getBodyPosition = function (editor) {
|
||||
return editor.inline ? getAbsolutePosition(editor.getBody()) : {left: 0, top: 0};
|
||||
};
|
||||
|
||||
var getScrollPosition = function (editor) {
|
||||
var body = editor.getBody();
|
||||
return editor.inline ? {left: body.scrollLeft, top: body.scrollTop} : {left: 0, top: 0};
|
||||
};
|
||||
|
||||
var getBodyScroll = function (editor) {
|
||||
var body = editor.getBody(), docElm = editor.getDoc().documentElement;
|
||||
var inlineScroll = {left: body.scrollLeft, top: body.scrollTop};
|
||||
var iframeScroll = {left: body.scrollLeft || docElm.scrollLeft, top: body.scrollTop || docElm.scrollTop};
|
||||
|
||||
return editor.inline ? inlineScroll : iframeScroll;
|
||||
};
|
||||
|
||||
var getMousePosition = function (editor, event) {
|
||||
if (event.target.ownerDocument !== editor.getDoc()) {
|
||||
var iframePosition = getAbsolutePosition(editor.getContentAreaContainer());
|
||||
var scrollPosition = getBodyScroll(editor);
|
||||
|
||||
return {
|
||||
left: event.pageX - iframePosition.left + scrollPosition.left,
|
||||
top: event.pageY - iframePosition.top + scrollPosition.top
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
left: event.pageX,
|
||||
top: event.pageY
|
||||
};
|
||||
};
|
||||
|
||||
var calculatePosition = function (bodyPosition, scrollPosition, mousePosition) {
|
||||
return {
|
||||
pageX: (mousePosition.left - bodyPosition.left) + scrollPosition.left,
|
||||
pageY: (mousePosition.top - bodyPosition.top) + scrollPosition.top
|
||||
};
|
||||
};
|
||||
|
||||
var calc = function (editor, event) {
|
||||
return calculatePosition(getBodyPosition(editor), getScrollPosition(editor), getMousePosition(editor, event));
|
||||
};
|
||||
|
||||
return {
|
||||
calc: calc
|
||||
};
|
||||
});
|
||||
|
||||
// Included from: js/tinymce/classes/DragDropOverrides.js
|
||||
|
||||
/**
|
||||
@ -35615,205 +35726,240 @@ define("tinymce/caret/LineUtils", [
|
||||
define("tinymce/DragDropOverrides", [
|
||||
"tinymce/dom/NodeType",
|
||||
"tinymce/util/Arr",
|
||||
"tinymce/util/Fun"
|
||||
"tinymce/util/Fun",
|
||||
"tinymce/util/Delay",
|
||||
"tinymce/dom/DOMUtils",
|
||||
"tinymce/dom/MousePosition"
|
||||
], function(
|
||||
NodeType,
|
||||
Arr,
|
||||
Fun
|
||||
NodeType, Arr, Fun, Delay, DOMUtils, MousePosition
|
||||
) {
|
||||
var isContentEditableFalse = NodeType.isContentEditableFalse,
|
||||
isContentEditableTrue = NodeType.isContentEditableTrue;
|
||||
|
||||
function init(editor) {
|
||||
var $ = editor.$, rootDocument = document,
|
||||
editableDoc = editor.getDoc(),
|
||||
dom = editor.dom, state = {};
|
||||
var isDraggable = function (elm) {
|
||||
return isContentEditableFalse(elm);
|
||||
};
|
||||
|
||||
function isDraggable(elm) {
|
||||
return isContentEditableFalse(elm);
|
||||
var isValidDropTarget = function (editor, targetElement, dragElement) {
|
||||
if (targetElement === dragElement || editor.dom.isChildOf(targetElement, dragElement)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
function setBodyCursor(cursor) {
|
||||
$(editor.getBody()).css('cursor', cursor);
|
||||
if (isContentEditableFalse(targetElement)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
function isValidDropTarget(elm) {
|
||||
if (elm == state.element || editor.dom.isChildOf(elm, state.element)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
if (isContentEditableFalse(elm)) {
|
||||
return false;
|
||||
}
|
||||
var cloneElement = function (elm) {
|
||||
var cloneElm = elm.cloneNode(true);
|
||||
cloneElm.removeAttribute('data-mce-selected');
|
||||
return cloneElm;
|
||||
};
|
||||
|
||||
return true;
|
||||
var createGhost = function (editor, elm, width, height) {
|
||||
var clonedElm = elm.cloneNode(true);
|
||||
|
||||
editor.dom.setStyles(clonedElm, {width: width, height: height});
|
||||
editor.dom.setAttrib(clonedElm, 'data-mce-selected', null);
|
||||
|
||||
var ghostElm = editor.dom.create('div', {
|
||||
'class': 'mce-drag-container',
|
||||
'data-mce-bogus': 'all',
|
||||
unselectable: 'on',
|
||||
contenteditable: 'false'
|
||||
});
|
||||
|
||||
editor.dom.setStyles(ghostElm, {
|
||||
position: 'absolute',
|
||||
opacity: 0.5,
|
||||
overflow: 'hidden',
|
||||
border: 0,
|
||||
padding: 0,
|
||||
margin: 0,
|
||||
width: width,
|
||||
height: height
|
||||
});
|
||||
|
||||
editor.dom.setStyles(clonedElm, {
|
||||
margin: 0,
|
||||
boxSizing: 'border-box'
|
||||
});
|
||||
|
||||
ghostElm.appendChild(clonedElm);
|
||||
|
||||
return ghostElm;
|
||||
};
|
||||
|
||||
var appendGhostToBody = function (ghostElm, bodyElm) {
|
||||
if (ghostElm.parentNode !== bodyElm) {
|
||||
bodyElm.appendChild(ghostElm);
|
||||
}
|
||||
};
|
||||
|
||||
var moveGhost = function (ghostElm, position, width, height, maxX, maxY) {
|
||||
var overflowX = 0, overflowY = 0;
|
||||
|
||||
ghostElm.style.left = position.pageX + 'px';
|
||||
ghostElm.style.top = position.pageY + 'px';
|
||||
|
||||
if (position.pageX + width > maxX) {
|
||||
overflowX = (position.pageX + width) - maxX;
|
||||
}
|
||||
|
||||
function move(e) {
|
||||
var deltaX, deltaY, pos, viewPort,
|
||||
overflowX = 0, overflowY = 0, movement,
|
||||
clientX, clientY, rootClientRect;
|
||||
|
||||
if (e.button !== 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
deltaX = e.screenX - state.screenX;
|
||||
deltaY = e.screenY - state.screenY;
|
||||
movement = Math.max(Math.abs(deltaX), Math.abs(deltaY));
|
||||
|
||||
if (!state.dragging && movement > 10) {
|
||||
state.dragging = true;
|
||||
setBodyCursor('default');
|
||||
|
||||
state.clone = state.element.cloneNode(true);
|
||||
|
||||
pos = dom.getPos(state.element);
|
||||
state.relX = state.clientX - pos.x;
|
||||
state.relY = state.clientY - pos.y;
|
||||
state.width = state.element.offsetWidth;
|
||||
state.height = state.element.offsetHeight;
|
||||
|
||||
$(state.clone).css({
|
||||
width: state.width,
|
||||
height: state.height
|
||||
}).removeAttr('data-mce-selected');
|
||||
|
||||
state.ghost = $('<div>').css({
|
||||
position: 'absolute',
|
||||
opacity: 0.5,
|
||||
overflow: 'hidden',
|
||||
width: state.width,
|
||||
height: state.height
|
||||
}).attr({
|
||||
'data-mce-bogus': 'all',
|
||||
unselectable: 'on',
|
||||
contenteditable: 'false'
|
||||
}).addClass('mce-drag-container mce-reset').
|
||||
append(state.clone).
|
||||
appendTo(editor.getBody())[0];
|
||||
|
||||
viewPort = editor.dom.getViewPort(editor.getWin());
|
||||
state.maxX = viewPort.w;
|
||||
state.maxY = viewPort.h;
|
||||
}
|
||||
|
||||
if (state.dragging) {
|
||||
editor._selectionOverrides.hideFakeCaret();
|
||||
editor.selection.placeCaretAt(e.clientX, e.clientY);
|
||||
|
||||
clientX = state.clientX + deltaX - state.relX;
|
||||
clientY = state.clientY + deltaY + 5;
|
||||
|
||||
if (clientX + state.width > state.maxX) {
|
||||
overflowX = (clientX + state.width) - state.maxX;
|
||||
}
|
||||
|
||||
if (clientY + state.height > state.maxY) {
|
||||
overflowY = (clientY + state.height) - state.maxY;
|
||||
}
|
||||
|
||||
if (editor.getBody().nodeName != 'BODY') {
|
||||
rootClientRect = editor.getBody().getBoundingClientRect();
|
||||
} else {
|
||||
rootClientRect = {left: 0, top: 0};
|
||||
}
|
||||
|
||||
$(state.ghost).css({
|
||||
left: clientX - rootClientRect.left,
|
||||
top: clientY - rootClientRect.top,
|
||||
width: state.width - overflowX,
|
||||
height: state.height - overflowY
|
||||
});
|
||||
}
|
||||
if (position.pageY + height > maxY) {
|
||||
overflowY = (position.pageY + height) - maxY;
|
||||
}
|
||||
|
||||
function drop(evt) {
|
||||
var dropEvt;
|
||||
ghostElm.style.width = (width - overflowX) + 'px';
|
||||
ghostElm.style.height = (height - overflowY) + 'px';
|
||||
};
|
||||
|
||||
if (state.dragging) {
|
||||
// Hack for IE since it doesn't sync W3C Range with IE Specific range
|
||||
editor.selection.setRng(editor.selection.getSel().getRangeAt(0));
|
||||
var removeElement = function (elm) {
|
||||
if (elm && elm.parentNode) {
|
||||
elm.parentNode.removeChild(elm);
|
||||
}
|
||||
};
|
||||
|
||||
if (isValidDropTarget(editor.selection.getNode())) {
|
||||
var targetClone = state.element;
|
||||
var isLeftMouseButtonPressed = function (e) {
|
||||
return e.button === 0;
|
||||
};
|
||||
|
||||
// Pass along clientX, clientY if we have them
|
||||
dropEvt = editor.fire('drop', {
|
||||
targetClone: targetClone,
|
||||
clientX: evt.clientX,
|
||||
clientY: evt.clientY
|
||||
});
|
||||
var hasDraggableElement = function (state) {
|
||||
return state.element;
|
||||
};
|
||||
|
||||
if (dropEvt.isDefaultPrevented()) {
|
||||
return;
|
||||
}
|
||||
var applyRelPos = function (state, position) {
|
||||
return {
|
||||
pageX: position.pageX - state.relX,
|
||||
pageY: position.pageY + 5
|
||||
};
|
||||
};
|
||||
|
||||
targetClone = dropEvt.targetClone;
|
||||
var start = function (state, editor) {
|
||||
return function (e) {
|
||||
if (isLeftMouseButtonPressed(e)) {
|
||||
var ceElm = Arr.find(editor.dom.getParents(e.target), Fun.or(isContentEditableFalse, isContentEditableTrue));
|
||||
|
||||
editor.undoManager.transact(function() {
|
||||
editor.insertContent(dom.getOuterHTML(targetClone));
|
||||
$(state.element).remove();
|
||||
});
|
||||
if (isDraggable(ceElm)) {
|
||||
var elmPos = editor.dom.getPos(ceElm);
|
||||
var bodyElm = editor.getBody();
|
||||
var docElm = editor.getDoc().documentElement;
|
||||
|
||||
state.element = ceElm;
|
||||
state.screenX = e.screenX;
|
||||
state.screenY = e.screenY;
|
||||
state.maxX = (editor.inline ? bodyElm.scrollWidth : docElm.offsetWidth) - 2;
|
||||
state.maxY = (editor.inline ? bodyElm.scrollHeight : docElm.offsetHeight) - 2;
|
||||
state.relX = e.pageX - elmPos.x;
|
||||
state.relY = e.pageY - elmPos.y;
|
||||
state.width = ceElm.offsetWidth;
|
||||
state.height = ceElm.offsetHeight;
|
||||
state.ghost = createGhost(editor, ceElm, state.width, state.height);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
stop();
|
||||
}
|
||||
var move = function (state, editor) {
|
||||
// Reduces laggy drag behavior on Gecko
|
||||
var throttledPlaceCaretAt = Delay.throttle(function (clientX, clientY) {
|
||||
editor._selectionOverrides.hideFakeCaret();
|
||||
editor.selection.placeCaretAt(clientX, clientY);
|
||||
}, 0);
|
||||
|
||||
function start(e) {
|
||||
var ceElm, evt;
|
||||
return function (e) {
|
||||
var movement = Math.max(Math.abs(e.screenX - state.screenX), Math.abs(e.screenY - state.screenY));
|
||||
|
||||
stop();
|
||||
|
||||
if (e.button !== 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
ceElm = Arr.find(editor.dom.getParents(e.target), Fun.or(isContentEditableFalse, isContentEditableTrue));
|
||||
|
||||
if (isDraggable(ceElm)) {
|
||||
evt = editor.fire('dragstart', {target: ceElm});
|
||||
if (evt.isDefaultPrevented()) {
|
||||
if (hasDraggableElement(state) && !state.dragging && movement > 10) {
|
||||
var args = editor.fire('dragstart', {target: state.element});
|
||||
if (args.isDefaultPrevented()) {
|
||||
return;
|
||||
}
|
||||
|
||||
editor.on('mousemove', move);
|
||||
editor.on('mouseup', drop);
|
||||
state.dragging = true;
|
||||
editor.focus();
|
||||
}
|
||||
|
||||
if (rootDocument != editableDoc) {
|
||||
dom.bind(rootDocument, 'mousemove', move);
|
||||
dom.bind(rootDocument, 'mouseup', drop);
|
||||
if (state.dragging) {
|
||||
var targetPos = applyRelPos(state, MousePosition.calc(editor, e));
|
||||
|
||||
appendGhostToBody(state.ghost, editor.getBody());
|
||||
moveGhost(state.ghost, targetPos, state.width, state.height, state.maxX, state.maxY);
|
||||
|
||||
throttledPlaceCaretAt(e.clientX, e.clientY);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
var drop = function (state, editor) {
|
||||
return function (e) {
|
||||
if (state.dragging) {
|
||||
if (isValidDropTarget(editor, editor.selection.getNode(), state.element)) {
|
||||
var targetClone = cloneElement(state.element);
|
||||
|
||||
var args = editor.fire('drop', {
|
||||
targetClone: targetClone,
|
||||
clientX: e.clientX,
|
||||
clientY: e.clientY
|
||||
});
|
||||
|
||||
if (!args.isDefaultPrevented()) {
|
||||
targetClone = args.targetClone;
|
||||
|
||||
editor.undoManager.transact(function() {
|
||||
removeElement(state.element);
|
||||
editor.insertContent(editor.dom.getOuterHTML(targetClone));
|
||||
editor._selectionOverrides.hideFakeCaret();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
state = {
|
||||
screenX: e.screenX,
|
||||
screenY: e.screenY,
|
||||
clientX: e.clientX,
|
||||
clientY: e.clientY,
|
||||
element: ceElm
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function stop() {
|
||||
$(state.ghost).remove();
|
||||
setBodyCursor(null);
|
||||
|
||||
editor.off('mousemove', move);
|
||||
editor.off('mouseup', stop);
|
||||
|
||||
if (rootDocument != editableDoc) {
|
||||
dom.unbind(rootDocument, 'mousemove', move);
|
||||
dom.unbind(rootDocument, 'mouseup', stop);
|
||||
}
|
||||
|
||||
state = {};
|
||||
}
|
||||
removeDragState(state);
|
||||
};
|
||||
};
|
||||
|
||||
editor.on('mousedown', start);
|
||||
var stop = function (state, editor) {
|
||||
return function () {
|
||||
removeDragState(state);
|
||||
if (state.dragging) {
|
||||
editor.fire('dragend');
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// Blocks drop inside cE=false on IE
|
||||
var removeDragState = function (state) {
|
||||
state.dragging = false;
|
||||
state.element = null;
|
||||
removeElement(state.ghost);
|
||||
};
|
||||
|
||||
var bindFakeDragEvents = function (editor) {
|
||||
var state = {}, pageDom, dragStartHandler, dragHandler, dropHandler, dragEndHandler, rootDocument;
|
||||
|
||||
pageDom = DOMUtils.DOM;
|
||||
rootDocument = document;
|
||||
dragStartHandler = start(state, editor);
|
||||
dragHandler = move(state, editor);
|
||||
dropHandler = drop(state, editor);
|
||||
dragEndHandler = stop(state, editor);
|
||||
|
||||
editor.on('mousedown', dragStartHandler);
|
||||
editor.on('mousemove', dragHandler);
|
||||
editor.on('mouseup', dropHandler);
|
||||
|
||||
pageDom.bind(rootDocument, 'mousemove', dragHandler);
|
||||
pageDom.bind(rootDocument, 'mouseup', dragEndHandler);
|
||||
|
||||
editor.on('remove', function () {
|
||||
pageDom.unbind(rootDocument, 'mousemove', dragHandler);
|
||||
pageDom.unbind(rootDocument, 'mouseup', dragEndHandler);
|
||||
});
|
||||
};
|
||||
|
||||
var blockIeDrop = function (editor) {
|
||||
editor.on('drop', function(e) {
|
||||
// FF doesn't pass out clientX/clientY for drop since this is for IE we just use null instead
|
||||
var realTarget = typeof e.clientX !== 'undefined' ? editor.getDoc().elementFromPoint(e.clientX, e.clientY) : null;
|
||||
@ -35822,7 +35968,12 @@ define("tinymce/DragDropOverrides", [
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var init = function (editor) {
|
||||
bindFakeDragEvents(editor);
|
||||
blockIeDrop(editor);
|
||||
};
|
||||
|
||||
return {
|
||||
init: init
|
||||
@ -35902,6 +36053,11 @@ define("tinymce/SelectionOverrides", [
|
||||
realSelectionId = 'sel-' + editor.dom.uniqueId(),
|
||||
selectedContentEditableNode, $ = editor.$;
|
||||
|
||||
function getRealSelectionElement() {
|
||||
var container = editor.dom.get(realSelectionId);
|
||||
return container ? container.getElementsByTagName('*')[0] : container;
|
||||
}
|
||||
|
||||
function isBlock(node) {
|
||||
return editor.dom.isBlock(node);
|
||||
}
|
||||
@ -36261,25 +36417,51 @@ define("tinymce/SelectionOverrides", [
|
||||
return null;
|
||||
}
|
||||
|
||||
function isTextBlock(node) {
|
||||
var textBlocks = editor.schema.getTextBlockElements();
|
||||
return node.nodeName in textBlocks;
|
||||
}
|
||||
|
||||
function isEmpty(elm) {
|
||||
return editor.dom.isEmpty(elm);
|
||||
}
|
||||
|
||||
function mergeTextBlocks(direction, fromCaretPosition, toCaretPosition) {
|
||||
var dom = editor.dom, fromBlock, toBlock, node, textBlocks;
|
||||
var dom = editor.dom, fromBlock, toBlock, node, ceTarget;
|
||||
|
||||
fromBlock = dom.getParent(fromCaretPosition.getNode(), dom.isBlock);
|
||||
toBlock = dom.getParent(toCaretPosition.getNode(), dom.isBlock);
|
||||
|
||||
if (direction === -1) {
|
||||
if (isAfterContentEditableFalse(toCaretPosition) && isBlock(toCaretPosition.getNode(true))) {
|
||||
ceTarget = toCaretPosition.getNode(true);
|
||||
if (isAfterContentEditableFalse(toCaretPosition) && isBlock(ceTarget)) {
|
||||
if (isTextBlock(fromBlock)) {
|
||||
if (isEmpty(fromBlock)) {
|
||||
dom.remove(fromBlock);
|
||||
}
|
||||
|
||||
return CaretPosition.after(ceTarget).toRange();
|
||||
}
|
||||
|
||||
return deleteContentEditableNode(toCaretPosition.getNode(true));
|
||||
}
|
||||
} else {
|
||||
if (isBeforeContentEditableFalse(fromCaretPosition) && isBlock(fromCaretPosition.getNode())) {
|
||||
ceTarget = fromCaretPosition.getNode();
|
||||
if (isBeforeContentEditableFalse(fromCaretPosition) && isBlock(ceTarget)) {
|
||||
if (isTextBlock(toBlock)) {
|
||||
if (isEmpty(toBlock)) {
|
||||
dom.remove(toBlock);
|
||||
}
|
||||
|
||||
return CaretPosition.before(ceTarget).toRange();
|
||||
}
|
||||
|
||||
return deleteContentEditableNode(fromCaretPosition.getNode());
|
||||
}
|
||||
}
|
||||
|
||||
textBlocks = editor.schema.getTextBlockElements();
|
||||
fromBlock = dom.getParent(fromCaretPosition.getNode(), dom.isBlock);
|
||||
toBlock = dom.getParent(toCaretPosition.getNode(), dom.isBlock);
|
||||
|
||||
// Verify that both blocks are text blocks
|
||||
if (fromBlock === toBlock || !textBlocks[fromBlock.nodeName] || !textBlocks[toBlock.nodeName]) {
|
||||
if (fromBlock === toBlock || !isTextBlock(fromBlock) || !isTextBlock(toBlock)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -36382,6 +36564,7 @@ define("tinymce/SelectionOverrides", [
|
||||
if (contentEditableRoot) {
|
||||
if (isContentEditableFalse(contentEditableRoot)) {
|
||||
e.preventDefault();
|
||||
editor.focus();
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -36604,6 +36787,22 @@ define("tinymce/SelectionOverrides", [
|
||||
}, 0);
|
||||
});
|
||||
|
||||
editor.on('copy', function (e) {
|
||||
var clipboardData = e.clipboardData;
|
||||
|
||||
// Make sure we get proper html/text for the fake cE=false selection
|
||||
// Doesn't work at all on Edge since it doesn't have proper clipboardData support
|
||||
if (!e.isDefaultPrevented() && e.clipboardData && !Env.ie) {
|
||||
var realSelectionElement = getRealSelectionElement();
|
||||
if (realSelectionElement) {
|
||||
e.preventDefault();
|
||||
clipboardData.clearData();
|
||||
clipboardData.setData('text/html', realSelectionElement.outerHTML);
|
||||
clipboardData.setData('text/plain', realSelectionElement.outerText);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
DragDropOverrides.init(editor);
|
||||
}
|
||||
|
||||
@ -36615,8 +36814,6 @@ define("tinymce/SelectionOverrides", [
|
||||
rootClass + ' .mce-offscreen-selection {' +
|
||||
'position: absolute;' +
|
||||
'left: -9999999999px;' +
|
||||
'width: 100px;' +
|
||||
'height: 100px;' +
|
||||
'}' +
|
||||
rootClass + ' *[contentEditable=false] {' +
|
||||
'cursor: default;' +
|
||||
@ -37303,11 +37500,12 @@ define("tinymce/Editor", [
|
||||
var self = this, settings = self.settings, elm = self.getElement();
|
||||
var w, h, minHeight, n, o, Theme, url, bodyId, bodyClass, re, i, initializedPlugins = [];
|
||||
|
||||
this.editorManager.i18n.setCode(settings.language);
|
||||
self.rtl = settings.rtl_ui || this.editorManager.i18n.rtl;
|
||||
|
||||
self.rtl = settings.rtl_ui || self.editorManager.i18n.rtl;
|
||||
self.editorManager.i18n.setCode(settings.language);
|
||||
settings.aria_label = settings.aria_label || DOM.getAttrib(elm, 'aria-label', self.getLang('aria.rich_text_area'));
|
||||
|
||||
self.fire('ScriptsLoaded');
|
||||
|
||||
/**
|
||||
* Reference to the theme instance that was used to generate the UI.
|
||||
*
|
||||
@ -38801,7 +38999,8 @@ define("tinymce/Editor", [
|
||||
* @return {Element} The root element of the editable area.
|
||||
*/
|
||||
getBody: function() {
|
||||
return this.bodyElement || this.getDoc().body;
|
||||
var doc = this.getDoc();
|
||||
return this.bodyElement || (doc ? doc.body : null);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -39520,7 +39719,7 @@ define("tinymce/EditorManager", [
|
||||
* @property minorVersion
|
||||
* @type String
|
||||
*/
|
||||
minorVersion: '4.1',
|
||||
minorVersion: '4.3',
|
||||
|
||||
/**
|
||||
* Release date of TinyMCE build.
|
||||
@ -39528,7 +39727,7 @@ define("tinymce/EditorManager", [
|
||||
* @property releaseDate
|
||||
* @type String
|
||||
*/
|
||||
releaseDate: '2016-07-26',
|
||||
releaseDate: '2016-09-01',
|
||||
|
||||
/**
|
||||
* Collection of editor instances.
|
||||
@ -43570,17 +43769,18 @@ define("tinymce/ui/FormatControls", [
|
||||
"tinymce/ui/Widget",
|
||||
"tinymce/ui/FloatPanel",
|
||||
"tinymce/util/Tools",
|
||||
"tinymce/dom/DOMUtils",
|
||||
"tinymce/EditorManager",
|
||||
"tinymce/Env"
|
||||
], function(Control, Widget, FloatPanel, Tools, EditorManager, Env) {
|
||||
], function(Control, Widget, FloatPanel, Tools, DOMUtils, EditorManager, Env) {
|
||||
var each = Tools.each;
|
||||
|
||||
EditorManager.on('AddEditor', function(e) {
|
||||
if (e.editor.rtl) {
|
||||
Control.rtl = true;
|
||||
}
|
||||
var editor = e.editor;
|
||||
|
||||
registerControls(e.editor);
|
||||
setupRtlMode(editor);
|
||||
registerControls(editor);
|
||||
setupContainer(editor);
|
||||
});
|
||||
|
||||
Control.translate = function(text) {
|
||||
@ -43589,6 +43789,20 @@ define("tinymce/ui/FormatControls", [
|
||||
|
||||
Widget.tooltips = !Env.iOS;
|
||||
|
||||
function setupContainer(editor) {
|
||||
if (editor.settings.ui_container) {
|
||||
Env.container = DOMUtils.DOM.select(editor.settings.ui_container)[0];
|
||||
}
|
||||
}
|
||||
|
||||
function setupRtlMode(editor) {
|
||||
editor.on('ScriptsLoaded', function () {
|
||||
if (editor.rtl) {
|
||||
Control.rtl = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function registerControls(editor) {
|
||||
var formatMenu;
|
||||
|
||||
|
27
src/wp-includes/js/tinymce/tinymce.min.js
vendored
27
src/wp-includes/js/tinymce/tinymce.min.js
vendored
File diff suppressed because one or more lines are too long
@ -18,7 +18,7 @@ $wp_db_version = 38590;
|
||||
*
|
||||
* @global string $tinymce_version
|
||||
*/
|
||||
$tinymce_version = '4401-20160726';
|
||||
$tinymce_version = '4403-20160901';
|
||||
|
||||
/**
|
||||
* Holds the required PHP version
|
||||
|
@ -116,6 +116,7 @@
|
||||
<!-- tinymce.* -->
|
||||
<script src="tinymce/AddOnManager.js"></script>
|
||||
<script src="tinymce/Editor.js"></script>
|
||||
<script src="tinymce/Editor_rtl.js"></script>
|
||||
<script src="tinymce/EditorUpload.js"></script>
|
||||
<script src="tinymce/EditorCommands.js"></script>
|
||||
<script src="tinymce/EditorManager.js"></script>
|
||||
|
@ -29,6 +29,8 @@
|
||||
delete editor.settings.importcss_append;
|
||||
delete editor.settings.importcss_selector_filter;
|
||||
delete editor.settings.importcss_groups;
|
||||
delete editor.settings.importcss_exclusive;
|
||||
delete editor.settings.importcss_selector_converter;
|
||||
}
|
||||
});
|
||||
|
||||
@ -220,4 +222,129 @@
|
||||
equal(evt.control.items().length, 1);
|
||||
equal(evt.control.items()[0].text(), 'b');
|
||||
});
|
||||
|
||||
test("Import custom importcss_selector_converter", function() {
|
||||
editor.settings.importcss_groups = [
|
||||
{title: 'g1', filter: /\.a/, custom: 'A'},
|
||||
{title: 'g2', filter: /\.b/, custom: 'B'},
|
||||
{title: 'g3', custom: 'C'}
|
||||
];
|
||||
|
||||
editor.contentCSS.push("test1.css");
|
||||
editor.settings.importcss_selector_converter = function (selector, group) {
|
||||
return {
|
||||
title: selector + group.custom,
|
||||
inline: 'span'
|
||||
};
|
||||
};
|
||||
|
||||
var evt = fireFormatsMenuEvent([
|
||||
{href: 'test1.css', cssRules: [
|
||||
{selectorText: '.a'},
|
||||
{selectorText: '.b'},
|
||||
{selectorText: '.c'}
|
||||
]}
|
||||
]);
|
||||
|
||||
var items = evt.control.items();
|
||||
equal(items.length, 3);
|
||||
equal(items[0].text(), 'g1');
|
||||
equal(items[0].settings.menu[0].text, '.aA');
|
||||
equal(items[1].text(), 'g2');
|
||||
equal(items[1].settings.menu[0].text, '.bB');
|
||||
equal(items[2].text(), 'g3');
|
||||
equal(items[2].settings.menu[0].text, '.cC');
|
||||
});
|
||||
|
||||
test("Import custom group selector_converter", function() {
|
||||
var constant = function (format) {
|
||||
return function () {
|
||||
return format;
|
||||
};
|
||||
};
|
||||
|
||||
var formatA = {
|
||||
title: 'my format a',
|
||||
selector: 'p'
|
||||
};
|
||||
|
||||
var formatB = {
|
||||
title: 'my format b',
|
||||
selector: 'h1'
|
||||
};
|
||||
|
||||
editor.settings.importcss_groups = [
|
||||
{title: 'g1', filter: /\.a/, selector_converter: constant(formatA)},
|
||||
{title: 'g2', filter: /\.b/, selector_converter: constant(formatB)},
|
||||
{title: 'g3', custom: 'C'}
|
||||
];
|
||||
|
||||
editor.contentCSS.push("test1.css");
|
||||
|
||||
var evt = fireFormatsMenuEvent([
|
||||
{href: 'test1.css', cssRules: [
|
||||
{selectorText: '.a'},
|
||||
{selectorText: '.b'},
|
||||
{selectorText: '.c'}
|
||||
]}
|
||||
]);
|
||||
|
||||
var items = evt.control.items();
|
||||
equal(items.length, 3);
|
||||
equal(items[0].text(), 'g1');
|
||||
equal(items[0].settings.menu[0].text, 'my format a');
|
||||
equal(items[1].text(), 'g2');
|
||||
equal(items[1].settings.menu[0].text, 'my format b');
|
||||
equal(items[2].text(), 'g3');
|
||||
equal(items[2].settings.menu[0].text, 'c');
|
||||
});
|
||||
|
||||
test("Import custom importcss_exclusive: true", function() {
|
||||
editor.settings.importcss_exclusive = true;
|
||||
editor.settings.importcss_groups = [
|
||||
{title: 'g1'},
|
||||
{title: 'g2'}
|
||||
];
|
||||
|
||||
editor.contentCSS.push("test1.css");
|
||||
var evt = fireFormatsMenuEvent([
|
||||
{href: 'test1.css', cssRules: [
|
||||
{selectorText: '.a'},
|
||||
{selectorText: '.b'},
|
||||
{selectorText: '.c'}
|
||||
]}
|
||||
]);
|
||||
|
||||
var items = evt.control.items();
|
||||
equal(items.length, 1);
|
||||
equal(items[0].text(), 'g1');
|
||||
equal(items[0].settings.menu[0].text, 'a');
|
||||
equal(items[0].settings.menu[1].text, 'b');
|
||||
});
|
||||
|
||||
test("Import custom importcss_exclusive: false", function() {
|
||||
editor.settings.importcss_exclusive = false;
|
||||
editor.settings.importcss_groups = [
|
||||
{title: 'g1'},
|
||||
{title: 'g2'}
|
||||
];
|
||||
|
||||
editor.contentCSS.push("test1.css");
|
||||
var evt = fireFormatsMenuEvent([
|
||||
{href: 'test1.css', cssRules: [
|
||||
{selectorText: '.a'},
|
||||
{selectorText: '.b'},
|
||||
{selectorText: '.c'}
|
||||
]}
|
||||
]);
|
||||
|
||||
var items = evt.control.items();
|
||||
equal(items.length, 2);
|
||||
equal(items[0].text(), 'g1');
|
||||
equal(items[0].settings.menu[0].text, 'a');
|
||||
equal(items[0].settings.menu[1].text, 'b');
|
||||
equal(items[1].text(), 'g2');
|
||||
equal(items[1].settings.menu[0].text, 'a');
|
||||
equal(items[1].settings.menu[1].text, 'b');
|
||||
});
|
||||
})();
|
||||
|
@ -35,7 +35,7 @@ ModuleLoader.require([
|
||||
indent: false,
|
||||
schema: 'html5',
|
||||
entities: 'raw',
|
||||
valid_elements: 'li,ol[style],ul[style],dl,dt,dd,em,strong,span,#p,div,br',
|
||||
valid_elements: 'li[style],ol[style],ul[style],dl,dt,dd,em,strong,span,#p,div,br',
|
||||
valid_styles: {
|
||||
'*': 'color,font-size,font-family,background-color,font-weight,font-style,text-decoration,float,margin,margin-top,margin-right,margin-bottom,margin-left,display,position,top,left,list-style-type'
|
||||
},
|
||||
@ -59,7 +59,7 @@ ModuleLoader.require([
|
||||
},
|
||||
valid_styles: {
|
||||
'*': 'color,font-size,font-family,background-color,font-weight,font-style,text-decoration,float,margin,margin-top,margin-right,margin-bottom,margin-left,display,position,top,left,list-style-type'
|
||||
},
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
@ -76,7 +76,7 @@ ModuleLoader.require([
|
||||
},
|
||||
valid_styles: {
|
||||
'*': 'color,font-size,font-family,background-color,font-weight,font-style,text-decoration,float,margin,margin-top,margin-right,margin-bottom,margin-left,display,position,top,left,list-style-type'
|
||||
},
|
||||
}
|
||||
|
||||
});
|
||||
},
|
||||
@ -400,7 +400,7 @@ ModuleLoader.require([
|
||||
|
||||
editor.focus();
|
||||
Utils.setSelection('ul li', 1);
|
||||
execCommand('InsertOrderedList', null, { 'list-style-type': 'lower-alpha' });
|
||||
execCommand('InsertOrderedList', null, {'list-style-type': 'lower-alpha'});
|
||||
|
||||
equal(editor.getContent(),
|
||||
'<ol>' +
|
||||
@ -427,7 +427,7 @@ ModuleLoader.require([
|
||||
|
||||
editor.focus();
|
||||
Utils.setSelection('p', 1);
|
||||
execCommand('InsertOrderedList', null, { 'list-style-type': 'lower-alpha' });
|
||||
execCommand('InsertOrderedList', null, {'list-style-type': 'lower-alpha'});
|
||||
|
||||
equal(editor.getContent(),
|
||||
'<ol>' +
|
||||
@ -481,7 +481,7 @@ ModuleLoader.require([
|
||||
|
||||
editor.focus();
|
||||
Utils.setSelection('ul li', 1);
|
||||
execCommand('InsertOrderedList', false, { 'list-style-type': 'upper-roman' });
|
||||
execCommand('InsertOrderedList', false, {'list-style-type': 'upper-roman'});
|
||||
|
||||
equal(editor.getContent(),
|
||||
'<ol style="list-style-type: upper-roman;">' +
|
||||
@ -506,7 +506,7 @@ ModuleLoader.require([
|
||||
|
||||
editor.focus();
|
||||
Utils.setSelection('ul li', 1);
|
||||
execCommand('InsertOrderedList', false, { 'list-style-type': 'lower-roman' });
|
||||
execCommand('InsertOrderedList', false, {'list-style-type': 'lower-roman'});
|
||||
|
||||
equal(editor.getContent(),
|
||||
'<ol style="list-style-type: lower-roman;">' +
|
||||
@ -533,7 +533,7 @@ ModuleLoader.require([
|
||||
|
||||
editor.focus();
|
||||
Utils.setSelection('ul li', 1);
|
||||
execCommand('InsertOrderedList', false, { 'list-style-type': 'lower-roman' });
|
||||
execCommand('InsertOrderedList', false, {'list-style-type': 'lower-roman'});
|
||||
|
||||
equal(editor.getContent(),
|
||||
'<ol style="list-style-type: upper-roman;">' +
|
||||
@ -968,7 +968,7 @@ ModuleLoader.require([
|
||||
'</ol>' +
|
||||
'<p>c</p>' +
|
||||
'<ol>' +
|
||||
'<li>' +
|
||||
'<li style="list-style-type: none;">' +
|
||||
'<ul>' +
|
||||
'<li>d</li>' +
|
||||
'</ul>' +
|
||||
@ -979,6 +979,64 @@ ModuleLoader.require([
|
||||
equal(editor.selection.getStart().nodeName, 'P');
|
||||
});
|
||||
|
||||
test('Remove OL on a deep nested LI', function() {
|
||||
editor.getBody().innerHTML = trimBrs(
|
||||
'<ol>' +
|
||||
'<li>a' +
|
||||
'<ol>' +
|
||||
'<li>b</li>' +
|
||||
'<li>c' +
|
||||
'<ol>' +
|
||||
'<li>d</li>' +
|
||||
'<li>e</li>' +
|
||||
'<li>f</li>' +
|
||||
'</ol>' +
|
||||
'</li>' +
|
||||
'<li>g</li>' +
|
||||
'<li>h</li>' +
|
||||
'</ol>' +
|
||||
'</li>' +
|
||||
'<li>i</li>' +
|
||||
'</ol>'
|
||||
);
|
||||
|
||||
editor.focus();
|
||||
Utils.setSelection('ol ol ol li:nth-child(2)', 1);
|
||||
execCommand('InsertOrderedList');
|
||||
|
||||
equal(editor.getContent(),
|
||||
'<ol>' +
|
||||
'<li>a' +
|
||||
'<ol>' +
|
||||
'<li>b</li>' +
|
||||
'<li>c' +
|
||||
'<ol>' +
|
||||
'<li>d</li>' +
|
||||
'</ol>' +
|
||||
'</li>' +
|
||||
'</ol>' +
|
||||
'</li>' +
|
||||
'</ol>' +
|
||||
'<p>e</p>' +
|
||||
'<ol>' +
|
||||
'<li style="list-style-type: none;">' +
|
||||
'<ol>' +
|
||||
'<li style="list-style-type: none;">' +
|
||||
'<ol>' +
|
||||
'<li>f</li>' +
|
||||
'</ol>' +
|
||||
'</li>' +
|
||||
'<li>g</li>' +
|
||||
'<li>h</li>' +
|
||||
'</ol>' +
|
||||
'</li>' +
|
||||
'<li>i</li>' +
|
||||
'</ol>'
|
||||
);
|
||||
|
||||
equal(editor.selection.getStart().nodeName, 'P');
|
||||
});
|
||||
|
||||
test('Remove UL with single LI in BR mode', function() {
|
||||
editor.settings.forced_root_block = false;
|
||||
|
||||
@ -2071,6 +2129,70 @@ ModuleLoader.require([
|
||||
equal(editor.selection.getNode().nodeName, 'LI');
|
||||
});
|
||||
|
||||
test('Backspace at LI selected with triple-click in UL', function() {
|
||||
editor.getBody().innerHTML = trimBrs(
|
||||
'<ul>' +
|
||||
'<li>a</li>' +
|
||||
'<li>b' +
|
||||
'<ul>' +
|
||||
'<li>c</li>' +
|
||||
'<li>d</li>' +
|
||||
'</ul>' +
|
||||
'</li>' +
|
||||
'</ul>'
|
||||
);
|
||||
|
||||
editor.focus();
|
||||
Utils.setSelection('li:nth-child(1)', 0, 'li:nth-child(2)', 0);
|
||||
editor.plugins.lists.backspaceDelete();
|
||||
|
||||
equal(trimBrs(editor.getContent()),
|
||||
'<ul>' +
|
||||
'<li>b' +
|
||||
'<ul>' +
|
||||
'<li>c</li>' +
|
||||
'<li>d</li>' +
|
||||
'</ul>' +
|
||||
'</li>' +
|
||||
'</ul>'
|
||||
);
|
||||
|
||||
equal(editor.selection.getNode().nodeName, 'LI');
|
||||
});
|
||||
|
||||
test('Backspace at partially selected list', function() {
|
||||
editor.getBody().innerHTML = trimBrs(
|
||||
'<p>abc</p>' +
|
||||
'<ul>' +
|
||||
'<li>a</li>' +
|
||||
'<li>b' +
|
||||
'<ul>' +
|
||||
'<li>c</li>' +
|
||||
'<li>d</li>' +
|
||||
'</ul>' +
|
||||
'</li>' +
|
||||
'</ul>'
|
||||
);
|
||||
|
||||
editor.focus();
|
||||
Utils.setSelection('p', 1, 'li:nth-child(2)', 0);
|
||||
editor.plugins.lists.backspaceDelete();
|
||||
|
||||
equal(trimBrs(editor.getContent()),
|
||||
'<p>ab</p>' +
|
||||
'<ul>' +
|
||||
'<li style="list-style-type: none;">' +
|
||||
'<ul>' +
|
||||
'<li>c</li>' +
|
||||
'<li>d</li>' +
|
||||
'</ul>' +
|
||||
'</li>' +
|
||||
'</ul>'
|
||||
);
|
||||
|
||||
equal(editor.selection.getNode().nodeName, 'P');
|
||||
});
|
||||
|
||||
// Delete
|
||||
|
||||
test('Delete at end of single LI in UL', function() {
|
||||
@ -2457,4 +2579,30 @@ ModuleLoader.require([
|
||||
|
||||
equal(editor.getContent(), '<ul><li>a</li><li>b</li><li>c</li></ul>');
|
||||
});
|
||||
|
||||
if (tinymce.Env.ie === 11) {
|
||||
test('Backspace merge li elements on IE 11', function() {
|
||||
// IE allows you to place the caret inside a LI without children
|
||||
editor.getBody().innerHTML = trimBrs(
|
||||
'<ul>' +
|
||||
'<li>a</li>' +
|
||||
'<li></li>' +
|
||||
'</ul>'
|
||||
);
|
||||
|
||||
editor.focus();
|
||||
Utils.setSelection('li:nth-child(2)', 0);
|
||||
|
||||
editor.plugins.lists.backspaceDelete();
|
||||
|
||||
equal(editor.getContent(),
|
||||
'<ul>' +
|
||||
'<li>a</li>' +
|
||||
'</ul>'
|
||||
);
|
||||
|
||||
equal(editor.selection.getNode().nodeName, 'LI');
|
||||
equal(editor.selection.getRng(true).startContainer.nodeType, 3, 'Should be a text node');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -28,6 +28,8 @@ ModuleLoader.require([
|
||||
equal(SmartPaste.isAbsoluteUrl('https://www.site.com'), true);
|
||||
equal(SmartPaste.isAbsoluteUrl('http://www.site.com/dir-name/file.gif?query=%42'), true);
|
||||
equal(SmartPaste.isAbsoluteUrl('https://www.site.com/dir-name/file.gif?query=%42'), true);
|
||||
equal(SmartPaste.isAbsoluteUrl('https://www.site.com/dir-name/file.gif?query=%42#a'), true);
|
||||
equal(SmartPaste.isAbsoluteUrl('https://www.site.com/~abc'), true);
|
||||
equal(SmartPaste.isAbsoluteUrl('file.gif'), false);
|
||||
equal(SmartPaste.isAbsoluteUrl(''), false);
|
||||
});
|
||||
@ -40,6 +42,7 @@ ModuleLoader.require([
|
||||
equal(SmartPaste.isImageUrl('http://www.site.com/dir-name/file.png'), true);
|
||||
equal(SmartPaste.isImageUrl('http://www.site.com/dir-name/file.gif'), true);
|
||||
equal(SmartPaste.isImageUrl('https://www.site.com/dir-name/file.gif'), true);
|
||||
equal(SmartPaste.isImageUrl('https://www.site.com/~dir-name/file.gif'), true);
|
||||
equal(SmartPaste.isImageUrl('https://www.site.com/dir-name/file.gif?query=%42'), false);
|
||||
equal(SmartPaste.isImageUrl('https://www.site.com/dir-name/file.html?query=%42'), false);
|
||||
equal(SmartPaste.isImageUrl('file.gif'), false);
|
||||
|
@ -44,6 +44,16 @@
|
||||
win.close();
|
||||
}
|
||||
|
||||
function testCommand(command, tests) {
|
||||
tinymce.util.Tools.each(tests, function (test) {
|
||||
editor.getBody().innerHTML = test.before;
|
||||
editor.selection.select(editor.dom.select('td[data-mce-selected]')[0], true);
|
||||
editor.selection.collapse(true);
|
||||
editor.execCommand(command);
|
||||
equal(cleanTableHtml(editor.getContent()), test.after, test.message);
|
||||
});
|
||||
}
|
||||
|
||||
function cleanTableHtml(html) {
|
||||
return Utils.cleanHtml(html).replace(/<p>( |<br[^>]+>)<\/p>$/, '');
|
||||
}
|
||||
@ -615,6 +625,140 @@
|
||||
);
|
||||
});
|
||||
|
||||
test("mceTablePasteRowAfter from merged row source", function() {
|
||||
editor.setContent(
|
||||
'<table>' +
|
||||
'<tbody>' +
|
||||
'<tr><td colspan="2">1 2</td><td rowspan="2">3</td></tr>' +
|
||||
'<tr><td>1</td><td>2</td></tr>' +
|
||||
'</tbody>' +
|
||||
'</table>'
|
||||
);
|
||||
|
||||
Utils.setSelection('tr:nth-child(1) td', 0);
|
||||
editor.execCommand('mceTableCopyRow');
|
||||
Utils.setSelection('tr:nth-child(2) td:nth-child(2)', 0);
|
||||
editor.execCommand('mceTablePasteRowAfter');
|
||||
|
||||
equal(
|
||||
cleanTableHtml(editor.getContent()),
|
||||
|
||||
'<table>' +
|
||||
'<tbody>' +
|
||||
'<tr><td colspan="2">1 2</td><td rowspan="2">3</td></tr>' +
|
||||
'<tr><td>1</td><td>2</td></tr>' +
|
||||
'<tr><td>1 2</td><td>3</td><td> </td></tr>' +
|
||||
'</tbody>' +
|
||||
'</table>'
|
||||
);
|
||||
});
|
||||
|
||||
test("mceTablePasteRowAfter from merged row source to merged row target", function() {
|
||||
editor.setContent(
|
||||
'<table>' +
|
||||
'<tbody>' +
|
||||
'<tr><td colspan="2">1 2</td><td rowspan="2">3</td></tr>' +
|
||||
'<tr><td>1</td><td>2</td></tr>' +
|
||||
'</tbody>' +
|
||||
'</table>'
|
||||
);
|
||||
|
||||
Utils.setSelection('tr:nth-child(1) td', 0);
|
||||
editor.execCommand('mceTableCopyRow');
|
||||
Utils.setSelection('tr:nth-child(1) td', 0);
|
||||
editor.execCommand('mceTablePasteRowAfter');
|
||||
|
||||
equal(
|
||||
cleanTableHtml(editor.getContent()),
|
||||
|
||||
'<table>' +
|
||||
'<tbody>' +
|
||||
'<tr><td colspan="2">1 2</td><td>3</td></tr>' +
|
||||
'<tr><td>1 2</td><td>3</td><td> </td></tr>' +
|
||||
'<tr><td>1</td><td>2</td><td> </td></tr>' +
|
||||
'</tbody>' +
|
||||
'</table>'
|
||||
);
|
||||
});
|
||||
|
||||
test("mceTablePasteRowAfter to wider table", function() {
|
||||
editor.setContent(
|
||||
'<table>' +
|
||||
'<tbody>' +
|
||||
'<tr><td>1a</td><td>2a</td><td>3a</td></tr>' +
|
||||
'</tbody>' +
|
||||
'</table>' +
|
||||
|
||||
'<table>' +
|
||||
'<tbody>' +
|
||||
'<tr><td>1b</td><td>2b</td><td>3b</td><td>4b</td></tr>' +
|
||||
'</tbody>' +
|
||||
'</table>'
|
||||
);
|
||||
|
||||
Utils.setSelection('table:nth-child(1) tr:nth-child(1) td', 0);
|
||||
editor.execCommand('mceTableCopyRow');
|
||||
|
||||
Utils.setSelection('table:nth-child(2) td', 0);
|
||||
editor.execCommand('mceTablePasteRowAfter');
|
||||
|
||||
equal(
|
||||
cleanTableHtml(editor.getContent()),
|
||||
|
||||
'<table>' +
|
||||
'<tbody>' +
|
||||
'<tr><td>1a</td><td>2a</td><td>3a</td></tr>' +
|
||||
'</tbody>' +
|
||||
'</table>' +
|
||||
|
||||
'<table>' +
|
||||
'<tbody>' +
|
||||
'<tr><td>1b</td><td>2b</td><td>3b</td><td>4b</td></tr>' +
|
||||
'<tr><td>1a</td><td>2a</td><td>3a</td><td> </td></tr>' +
|
||||
'</tbody>' +
|
||||
'</table>'
|
||||
);
|
||||
});
|
||||
|
||||
test("mceTablePasteRowAfter to narrower table", function() {
|
||||
editor.setContent(
|
||||
'<table>' +
|
||||
'<tbody>' +
|
||||
'<tr><td>1a</td><td>2a</td><td>3a</td></tr>' +
|
||||
'</tbody>' +
|
||||
'</table>' +
|
||||
|
||||
'<table>' +
|
||||
'<tbody>' +
|
||||
'<tr><td>1b</td><td>2b</td></tr>' +
|
||||
'</tbody>' +
|
||||
'</table>'
|
||||
);
|
||||
|
||||
Utils.setSelection('table:nth-child(1) tr:nth-child(1) td', 0);
|
||||
editor.execCommand('mceTableCopyRow');
|
||||
|
||||
Utils.setSelection('table:nth-child(2) td', 0);
|
||||
editor.execCommand('mceTablePasteRowAfter');
|
||||
|
||||
equal(
|
||||
cleanTableHtml(editor.getContent()),
|
||||
|
||||
'<table>' +
|
||||
'<tbody>' +
|
||||
'<tr><td>1a</td><td>2a</td><td>3a</td></tr>' +
|
||||
'</tbody>' +
|
||||
'</table>' +
|
||||
|
||||
'<table>' +
|
||||
'<tbody>' +
|
||||
'<tr><td>1b</td><td>2b</td></tr>' +
|
||||
'<tr><td>1a</td><td>2a</td></tr>' +
|
||||
'</tbody>' +
|
||||
'</table>'
|
||||
);
|
||||
});
|
||||
|
||||
test("row clipboard api", function() {
|
||||
var clipboardRows;
|
||||
|
||||
@ -666,6 +810,186 @@
|
||||
);
|
||||
});
|
||||
|
||||
test("mceSplitColsBefore", function() {
|
||||
testCommand('mceSplitColsBefore', [
|
||||
{
|
||||
message: 'Should not change anything these is no table cell selection',
|
||||
before: '<p>a</p>',
|
||||
after: '<p>a</p>'
|
||||
},
|
||||
|
||||
{
|
||||
message: 'Should not change anything since there is nothing to split (1 row)',
|
||||
before: (
|
||||
'<table>' +
|
||||
'<tbody>' +
|
||||
'<tr><td data-mce-selected="1">1a</td><td>2a</td><td>3a</td></tr>' +
|
||||
'</tbody>' +
|
||||
'</table>'
|
||||
),
|
||||
after: (
|
||||
'<table>' +
|
||||
'<tbody>' +
|
||||
'<tr><td>1a</td><td>2a</td><td>3a</td></tr>' +
|
||||
'</tbody>' +
|
||||
'</table>'
|
||||
)
|
||||
},
|
||||
|
||||
{
|
||||
message: 'Should not change anything since there is nothing to split (2 rows)',
|
||||
before: (
|
||||
'<table>' +
|
||||
'<tbody>' +
|
||||
'<tr><td>1a</td><td>2a</td><td>3a</td></tr>' +
|
||||
'<tr><td data-mce-selected="1">1b</td><td>2b</td><td>3b</td></tr>' +
|
||||
'</tbody>' +
|
||||
'</table>'
|
||||
),
|
||||
after: (
|
||||
'<table>' +
|
||||
'<tbody>' +
|
||||
'<tr><td>1a</td><td>2a</td><td>3a</td></tr>' +
|
||||
'<tr><td>1b</td><td>2b</td><td>3b</td></tr>' +
|
||||
'</tbody>' +
|
||||
'</table>'
|
||||
)
|
||||
},
|
||||
|
||||
{
|
||||
message: 'Should split at second row and remove rowspan',
|
||||
before: (
|
||||
'<table>' +
|
||||
'<tbody>' +
|
||||
'<tr><td rowspan="2">1a</td><td>2a</td><td rowspan="2">3a</td></tr>' +
|
||||
'<tr><td data-mce-selected="1">2b</td></tr>' +
|
||||
'</tbody>' +
|
||||
'</table>'
|
||||
),
|
||||
after: (
|
||||
'<table>' +
|
||||
'<tbody>' +
|
||||
'<tr><td>1a</td><td>2a</td><td>3a</td></tr>' +
|
||||
'<tr><td> </td><td>2b</td><td> </td></tr>' +
|
||||
'</tbody>' +
|
||||
'</table>'
|
||||
)
|
||||
},
|
||||
|
||||
{
|
||||
message: 'Should split at third row and decrease rowspan',
|
||||
before: (
|
||||
'<table>' +
|
||||
'<tbody>' +
|
||||
'<tr><td rowspan="3">1a</td><td>2a</td><td rowspan="3">3a</td></tr>' +
|
||||
'<tr><td>2b</td></tr>' +
|
||||
'<tr><td data-mce-selected="1">2c</td></tr>' +
|
||||
'</tbody>' +
|
||||
'</table>'
|
||||
),
|
||||
after: (
|
||||
'<table>' +
|
||||
'<tbody>' +
|
||||
'<tr><td rowspan="2">1a</td><td>2a</td><td rowspan="2">3a</td></tr>' +
|
||||
'<tr><td>2b</td></tr>' +
|
||||
'<tr><td> </td><td>2c</td><td> </td></tr>' +
|
||||
'</tbody>' +
|
||||
'</table>'
|
||||
)
|
||||
}
|
||||
]);
|
||||
});
|
||||
|
||||
test("mceSplitColsAfter", function() {
|
||||
testCommand('mceSplitColsAfter', [
|
||||
{
|
||||
message: 'Should not change anything these is no table cell selection',
|
||||
before: '<p>a</p>',
|
||||
after: '<p>a</p>'
|
||||
},
|
||||
|
||||
{
|
||||
message: 'Should not change anything since there is nothing to split (1 row)',
|
||||
before: (
|
||||
'<table>' +
|
||||
'<tbody>' +
|
||||
'<tr><td data-mce-selected="1">1a</td><td>2a</td><td>3a</td></tr>' +
|
||||
'</tbody>' +
|
||||
'</table>'
|
||||
),
|
||||
after: (
|
||||
'<table>' +
|
||||
'<tbody>' +
|
||||
'<tr><td>1a</td><td>2a</td><td>3a</td></tr>' +
|
||||
'</tbody>' +
|
||||
'</table>'
|
||||
)
|
||||
},
|
||||
|
||||
{
|
||||
message: 'Should not change anything since there is nothing to split (2 rows)',
|
||||
before: (
|
||||
'<table>' +
|
||||
'<tbody>' +
|
||||
'<tr><td data-mce-selected="1">1a</td><td>2a</td><td>3a</td></tr>' +
|
||||
'<tr><td>1b</td><td>2b</td><td>3b</td></tr>' +
|
||||
'</tbody>' +
|
||||
'</table>'
|
||||
),
|
||||
after: (
|
||||
'<table>' +
|
||||
'<tbody>' +
|
||||
'<tr><td>1a</td><td>2a</td><td>3a</td></tr>' +
|
||||
'<tr><td>1b</td><td>2b</td><td>3b</td></tr>' +
|
||||
'</tbody>' +
|
||||
'</table>'
|
||||
)
|
||||
},
|
||||
|
||||
{
|
||||
message: 'Should split at second row and remove rowspan',
|
||||
before: (
|
||||
'<table>' +
|
||||
'<tbody>' +
|
||||
'<tr><td rowspan="2" data-mce-selected="1">1a</td><td>2a</td><td rowspan="2">3a</td></tr>' +
|
||||
'<tr><td>2b</td></tr>' +
|
||||
'</tbody>' +
|
||||
'</table>'
|
||||
),
|
||||
after: (
|
||||
'<table>' +
|
||||
'<tbody>' +
|
||||
'<tr><td>1a</td><td>2a</td><td>3a</td></tr>' +
|
||||
'<tr><td> </td><td>2b</td><td> </td></tr>' +
|
||||
'</tbody>' +
|
||||
'</table>'
|
||||
)
|
||||
},
|
||||
|
||||
{
|
||||
message: 'Should split at first row and produce td:s with decreased rowspans below',
|
||||
before: (
|
||||
'<table>' +
|
||||
'<tbody>' +
|
||||
'<tr><td rowspan="3" data-mce-selected="1">1a</td><td>2a</td><td rowspan="3">3a</td></tr>' +
|
||||
'<tr><td>2b</td></tr>' +
|
||||
'<tr><td>2c</td></tr>' +
|
||||
'</tbody>' +
|
||||
'</table>'
|
||||
),
|
||||
after: (
|
||||
'<table>' +
|
||||
'<tbody>' +
|
||||
'<tr><td>1a</td><td>2a</td><td>3a</td></tr>' +
|
||||
'<tr><td rowspan="2"> </td><td>2b</td><td rowspan="2"> </td></tr>' +
|
||||
'<tr><td>2c</td></tr>' +
|
||||
'</tbody>' +
|
||||
'</table>'
|
||||
)
|
||||
}
|
||||
]);
|
||||
});
|
||||
|
||||
test("mceTableInsertRowBefore command", function() {
|
||||
editor.setContent('<table><tr><td>1</td><td>2</td></tr></table>');
|
||||
Utils.setSelection('td', 0);
|
||||
@ -673,59 +997,176 @@
|
||||
equal(cleanTableHtml(editor.getContent()), '<table><tbody><tr><td> </td><td> </td></tr><tr><td>1</td><td>2</td></tr></tbody></table>');
|
||||
});
|
||||
|
||||
test("mceTableMergeCells command with cell selection", function() {
|
||||
editor.getBody().innerHTML = '<table><tr><td data-mce-selected="1">1</td><td data-mce-selected="1">2</td></tr></table>';
|
||||
Utils.setSelection('td', 0);
|
||||
editor.execCommand('mceTableMergeCells');
|
||||
equal(cleanTableHtml(editor.getContent()), '<table><tbody><tr><td>12</td></tr></tbody></table>');
|
||||
});
|
||||
test("mceTableMergeCells", function() {
|
||||
testCommand('mceTableMergeCells', [
|
||||
{
|
||||
message: 'Should merge all cells into one',
|
||||
before: (
|
||||
'<table>' +
|
||||
'<tbody>' +
|
||||
'<tr><td data-mce-selected="1">a1</td><td data-mce-selected="1">b1</td></tr>' +
|
||||
'<tr><td data-mce-selected="1">a2</td><td data-mce-selected="1">b2</td></tr>' +
|
||||
'</tbody>' +
|
||||
'</table>'
|
||||
),
|
||||
|
||||
test("mceTableMergeCells command with all cells selected", function() {
|
||||
editor.getBody().innerHTML = (
|
||||
'<table>' +
|
||||
'<tbody>' +
|
||||
'<tr><td data-mce-selected="1">1</td><td data-mce-selected="1">2</td></tr>' +
|
||||
'<tr><td data-mce-selected="1">3</td><td data-mce-selected="1">4</td></tr>' +
|
||||
'</tbody>' +
|
||||
'</table>'
|
||||
);
|
||||
after: (
|
||||
'<table>' +
|
||||
'<tbody>' +
|
||||
'<tr><td>a1b1a2b2</td></tr>' +
|
||||
'</tbody>' +
|
||||
'</table>'
|
||||
)
|
||||
},
|
||||
|
||||
Utils.setSelection('td', 0);
|
||||
editor.execCommand('mceTableMergeCells');
|
||||
{
|
||||
message: 'Should merge cells in two cols/rows into one cell with colspan',
|
||||
before: (
|
||||
'<table>' +
|
||||
'<tbody>' +
|
||||
'<tr><td data-mce-selected="1">a1</td><td data-mce-selected="1">b1</td></tr>' +
|
||||
'<tr><td data-mce-selected="1">a2</td><td data-mce-selected="1">b2</td></tr>' +
|
||||
'<tr><td>a3</td><td>b3</td></tr>' +
|
||||
'</tbody>' +
|
||||
'</table>'
|
||||
),
|
||||
|
||||
equal(
|
||||
cleanTableHtml(editor.getContent()),
|
||||
'<table>' +
|
||||
'<tbody>' +
|
||||
'<tr><td>1234</td></tr>' +
|
||||
'</tbody>' +
|
||||
'</table>'
|
||||
);
|
||||
});
|
||||
after: (
|
||||
'<table>' +
|
||||
'<tbody>' +
|
||||
'<tr><td colspan="2">a1b1a2b2</td></tr>' +
|
||||
'<tr><td>a3</td><td>b3</td></tr>' +
|
||||
'</tbody>' +
|
||||
'</table>'
|
||||
)
|
||||
},
|
||||
|
||||
test("mceTableMergeCells command with whole rows selected", function() {
|
||||
editor.getBody().innerHTML = (
|
||||
'<table>' +
|
||||
'<tbody>' +
|
||||
'<tr><td data-mce-selected="1">1</td><td data-mce-selected="1">2</td></tr>' +
|
||||
'<tr><td data-mce-selected="1">3</td><td data-mce-selected="1">4</td></tr>' +
|
||||
'<tr><td>5</td><td>6</td></tr>' +
|
||||
'</tbody>' +
|
||||
'</table>'
|
||||
);
|
||||
{
|
||||
message: 'Should remove all rowspans since the table is fully merged',
|
||||
before: (
|
||||
'<table>' +
|
||||
'<tbody>' +
|
||||
'<tr><td rowspan="2">a1</td><td data-mce-selected="1">b1</td></tr>' +
|
||||
'<tr><td data-mce-selected="1">b2</td></tr>' +
|
||||
'</tbody>' +
|
||||
'</table>'
|
||||
),
|
||||
after: (
|
||||
'<table>' +
|
||||
'<tbody>' +
|
||||
'<tr><td>a1</td><td>b1b2</td></tr>' +
|
||||
'</tbody>' +
|
||||
'</table>'
|
||||
)
|
||||
},
|
||||
|
||||
Utils.setSelection('td', 0);
|
||||
editor.execCommand('mceTableMergeCells');
|
||||
{
|
||||
message: 'Should remove all colspans since the table is fully merged',
|
||||
before: (
|
||||
'<table>' +
|
||||
'<tbody>' +
|
||||
'<tr><td colspan="2">a1</td></tr>' +
|
||||
'<tr><td data-mce-selected="1">a2</td><td data-mce-selected="1">b2</td></tr>' +
|
||||
'</tbody>' +
|
||||
'</table>'
|
||||
),
|
||||
after: (
|
||||
'<table>' +
|
||||
'<tbody>' +
|
||||
'<tr><td>a1</td></tr>' +
|
||||
'<tr><td>a2b2</td></tr>' +
|
||||
'</tbody>' +
|
||||
'</table>'
|
||||
)
|
||||
},
|
||||
|
||||
equal(
|
||||
cleanTableHtml(editor.getContent()),
|
||||
'<table>' +
|
||||
'<tbody>' +
|
||||
'<tr><td colspan="2">1234</td></tr>' +
|
||||
'<tr><td>5</td><td>6</td></tr>' +
|
||||
'</tbody>' +
|
||||
'</table>'
|
||||
);
|
||||
{
|
||||
message: 'Should remove rowspans since the table is fully merged',
|
||||
before: (
|
||||
'<table>' +
|
||||
'<tbody>' +
|
||||
'<tr><td rowspan="3">a1</td><td rowspan="3">b1</td><td data-mce-selected="1">c1</td></tr>' +
|
||||
'<tr><td data-mce-selected="1">c2</td></tr>' +
|
||||
'<tr><td data-mce-selected="1">c3</td></tr>' +
|
||||
'</tbody>' +
|
||||
'</table>'
|
||||
),
|
||||
after: (
|
||||
'<table>' +
|
||||
'<tbody>' +
|
||||
'<tr><td>a1</td><td>b1</td><td>c1c2c3</td></tr>' +
|
||||
'</tbody>' +
|
||||
'</table>'
|
||||
)
|
||||
},
|
||||
|
||||
{
|
||||
message: 'Should remove colspans since the table is fully merged',
|
||||
before: (
|
||||
'<table>' +
|
||||
'<tbody>' +
|
||||
'<tr><td data-mce-selected="1">a1</td><td data-mce-selected="1">b1</td><td data-mce-selected="1">c1</td></tr>' +
|
||||
'<tr><td colspan="3">a2</td></tr>' +
|
||||
'<tr><td colspan="3">a3</td></tr>' +
|
||||
'</tbody>' +
|
||||
'</table>'
|
||||
),
|
||||
after: (
|
||||
'<table>' +
|
||||
'<tbody>' +
|
||||
'<tr><td>a1b1c1</td></tr>' +
|
||||
'<tr><td>a2</td></tr>' +
|
||||
'<tr><td>a3</td></tr>' +
|
||||
'</tbody>' +
|
||||
'</table>'
|
||||
)
|
||||
},
|
||||
|
||||
{
|
||||
message: 'Should reduce rowspans to 2 keep the colspan and remove one tr',
|
||||
before: (
|
||||
'<table>' +
|
||||
'<tbody>' +
|
||||
'<tr><td colspan="2" rowspan="2">a1</td><td rowspan="3">b1</td><td data-mce-selected="1">c1</td></tr>' +
|
||||
'<tr><td data-mce-selected="1">c2</td></tr>' +
|
||||
'<tr><td>a3</td><td>b3</td><td data-mce-selected="1">c3</td></tr>' +
|
||||
'</tbody>' +
|
||||
'</table>'
|
||||
),
|
||||
after: (
|
||||
'<table>' +
|
||||
'<tbody>' +
|
||||
'<tr><td colspan="2">a1</td><td rowspan="2">b1</td><td rowspan="2">c1c2c3</td></tr>' +
|
||||
'<tr><td>a3</td><td>b3</td></tr>' +
|
||||
'</tbody>' +
|
||||
'</table>'
|
||||
)
|
||||
},
|
||||
|
||||
{
|
||||
message: 'Should reduce colspans to 2 keep the rowspan',
|
||||
before: (
|
||||
'<table>' +
|
||||
'<tbody>' +
|
||||
'<tr><td data-mce-selected="1">a1</td><td data-mce-selected="1">b1</td><td data-mce-selected="1">c1</td></tr>' +
|
||||
'<tr><td colspan="3">a2</td></tr>' +
|
||||
'<tr><td colspan="2" rowspan="2">a3</td><td>c3</td></tr>' +
|
||||
'<tr><td>c4</td></tr>' +
|
||||
'</tbody>' +
|
||||
'</table>'
|
||||
),
|
||||
after: (
|
||||
'<table>' +
|
||||
'<tbody>' +
|
||||
'<tr><td colspan="2">a1b1c1</td></tr>' +
|
||||
'<tr><td colspan="2">a2</td></tr>' +
|
||||
'<tr><td rowspan="2">a3</td><td>c3</td></tr>' +
|
||||
'<tr><td>c4</td></tr>' +
|
||||
'</tbody>' +
|
||||
'</table>'
|
||||
)
|
||||
}
|
||||
]);
|
||||
});
|
||||
|
||||
test("mceTableSplitCells command", function() {
|
||||
|
@ -490,4 +490,9 @@ test('translate', function() {
|
||||
});
|
||||
|
||||
equal(editor.translate('input i18n'), 'output i18n');
|
||||
});
|
||||
|
||||
test('kamer word bounderies', function() {
|
||||
editor.setContent('<p>!\u200b!\u200b!</p>');
|
||||
equal(editor.getContent(), '<p>!\u200b!\u200b!</p>');
|
||||
});
|
55
tests/qunit/editor/tinymce/Editor_rtl.js
Normal file
55
tests/qunit/editor/tinymce/Editor_rtl.js
Normal file
@ -0,0 +1,55 @@
|
||||
ModuleLoader.require([
|
||||
"tinymce/util/I18n",
|
||||
"tinymce/ui/Control"
|
||||
], function(I18n, Control) {
|
||||
var scriptLoadedRtlState = {};
|
||||
|
||||
module("tinymce.Editor_rtl", {
|
||||
setupModule: function() {
|
||||
QUnit.stop();
|
||||
|
||||
tinymce.addI18n('ar', {
|
||||
"Bold": "Bold test",
|
||||
"_dir": "rtl"
|
||||
});
|
||||
|
||||
tinymce.init({
|
||||
selector: "textarea",
|
||||
toolbar: 'bold italic underline',
|
||||
setup: function (editor) {
|
||||
var beforeEventRtl = editor.rtl;
|
||||
|
||||
editor.on('ScriptsLoaded', function () {
|
||||
// We will know the rtl mode and code after all scripts have been loaded
|
||||
scriptLoadedRtlState = {
|
||||
beforeRtl: beforeEventRtl,
|
||||
afterRtl: editor.rtl,
|
||||
code: I18n.getCode()
|
||||
};
|
||||
});
|
||||
},
|
||||
init_instance_callback: function(ed) {
|
||||
window.editor = ed;
|
||||
QUnit.start();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
teardown: function() {
|
||||
I18n.rtl = false;
|
||||
I18n.setCode('en');
|
||||
Control.rtl = false;
|
||||
}
|
||||
});
|
||||
|
||||
test('UI rendered in RTL mode', function() {
|
||||
QUnit.equal(tinymce.activeEditor.getContainer().className.indexOf('mce-rtl') !== -1, true, 'Should have a mce-rtl class');
|
||||
QUnit.equal(tinymce.activeEditor.rtl, true, 'Should have the rtl property set');
|
||||
});
|
||||
|
||||
test('Rtl mode property set on editor instance and I18n global', function() {
|
||||
QUnit.equal(scriptLoadedRtlState.beforeRtl, undefined, 'Should be undefined since we dont know the rtl mode yet');
|
||||
QUnit.equal(scriptLoadedRtlState.afterRtl, true, 'Should be true since we now know the rtl mode');
|
||||
QUnit.equal(scriptLoadedRtlState.code, 'ar', 'Should be "ar" since the code hass been changed during loading');
|
||||
});
|
||||
});
|
@ -112,6 +112,17 @@ test('Toggle OFF - Inline element on partially selected text in start/end elemen
|
||||
equal(getContent(), '<p>1<b>234</b></p><p><b>123</b>4</p>');
|
||||
});
|
||||
|
||||
test('Toggle OFF - Inline element with data attribute', function() {
|
||||
editor.formatter.register('format', {inline: 'b'});
|
||||
editor.getBody().innerHTML = '<p><b data-x="1">1</b></p>';
|
||||
var rng = editor.dom.createRng();
|
||||
rng.setStart(editor.dom.select('b')[0].firstChild, 0);
|
||||
rng.setEnd(editor.dom.select('b')[0].firstChild, 1);
|
||||
editor.selection.setRng(rng);
|
||||
editor.formatter.toggle('format');
|
||||
equal(getContent(), '<p>1</p>');
|
||||
});
|
||||
|
||||
test('Toggle ON - NO inline element on selected text', function() {
|
||||
// Inline element on selected text
|
||||
editor.formatter.register('format', {
|
||||
@ -577,6 +588,19 @@ test('Inline element merged with left and right siblings', function() {
|
||||
equal(getContent(), '<p><b>123456</b></p>', 'Inline element merged with left and right siblings');
|
||||
});
|
||||
|
||||
test('Inline element merged with data attributed left sibling', function() {
|
||||
editor.formatter.register('format', {
|
||||
inline: 'b'
|
||||
});
|
||||
editor.getBody().innerHTML = '<p><b data-x="1">1234</b>5678</p>';
|
||||
var rng = editor.dom.createRng();
|
||||
rng.setStart(editor.dom.select('p')[0].lastChild, 0);
|
||||
rng.setEnd(editor.dom.select('p')[0].lastChild, 4);
|
||||
editor.selection.setRng(rng);
|
||||
editor.formatter.apply('format');
|
||||
equal(getContent(), '<p><b data-x="1">12345678</b></p>', 'Inline element merged with left sibling');
|
||||
});
|
||||
|
||||
test('Don\'t merge siblings with whitespace between 1', function() {
|
||||
editor.formatter.register('format', {
|
||||
inline: 'b'
|
||||
|
@ -276,6 +276,24 @@ ModuleLoader.require([
|
||||
equal(editor.selection.getRng().startContainer.nextSibling.nodeName, 'SPAN');
|
||||
});
|
||||
|
||||
test('backspace from empty block to after cE=false', function() {
|
||||
editor.getBody().innerHTML = '<p contenteditable="false">1</p><p><br></p>';
|
||||
Utils.setSelection('p:nth-child(2)', 0);
|
||||
|
||||
backspace();
|
||||
equal(editor.getContent(), '<p contenteditable="false">1</p>');
|
||||
assertCaretInCaretBlockContainer();
|
||||
});
|
||||
|
||||
test('delete from empty block to before cE=false', function() {
|
||||
editor.getBody().innerHTML = '<p><br></p><p contenteditable="false">2</p>';
|
||||
Utils.setSelection('p:nth-child(1)', 0);
|
||||
|
||||
forwardDelete();
|
||||
equal(editor.getContent(), '<p contenteditable="false">2</p>');
|
||||
assertCaretInCaretBlockContainer();
|
||||
});
|
||||
|
||||
test('exit pre block (up)', exitPreTest(upArrow, 0, '<p>\u00a0</p><pre>abc</pre>'));
|
||||
test('exit pre block (left)', exitPreTest(leftArrow, 0, '<p>\u00a0</p><pre>abc</pre>'));
|
||||
test('exit pre block (down)', exitPreTest(downArrow, 3, '<pre>abc</pre><p>\u00a0</p>'));
|
||||
|
@ -278,6 +278,7 @@ test('Extra with changes', function() {
|
||||
|
||||
editor.undoManager.clear();
|
||||
editor.setContent('<p>abc</p>');
|
||||
Utils.setSelection('p', 0);
|
||||
editor.undoManager.add();
|
||||
|
||||
editor.undoManager.extra(function() {
|
||||
@ -291,8 +292,8 @@ test('Extra with changes', function() {
|
||||
data = editor.undoManager.data;
|
||||
equal(data.length, 3);
|
||||
equal(data[0].content, '<p>abc</p>');
|
||||
deepEqual(data[0].bookmark, {start: [0]});
|
||||
deepEqual(data[0].beforeBookmark, {start: [0]});
|
||||
deepEqual(data[0].bookmark, {start: [0, 0, 0]});
|
||||
deepEqual(data[0].beforeBookmark, {start: [0, 0, 0]});
|
||||
equal(data[1].content, '<p>a1c</p>');
|
||||
deepEqual(data[1].bookmark, {start: [2, 0, 0]});
|
||||
deepEqual(data[1].beforeBookmark, {start: [2, 0, 0]});
|
||||
@ -337,6 +338,7 @@ test('Exclude internal elements', function() {
|
||||
'<img src="about:blank" data-mce-bogus="all">' +
|
||||
'<br data-mce-bogus="1">' +
|
||||
'test' +
|
||||
'\u200B' +
|
||||
'<img src="about:blank" />' +
|
||||
'<table><tr><td>x</td></tr></table>'
|
||||
);
|
||||
@ -346,6 +348,7 @@ test('Exclude internal elements', function() {
|
||||
equal(Utils.cleanHtml(lastLevel.content),
|
||||
'<br data-mce-bogus="1">' +
|
||||
'test' +
|
||||
'\u200B' +
|
||||
'<img src="about:blank">' +
|
||||
'<table><tbody><tr><td>x</td></tr></tbody></table>'
|
||||
);
|
||||
|
@ -11,7 +11,14 @@ ModuleLoader.require([
|
||||
}
|
||||
|
||||
function setViewHtml(html) {
|
||||
getRoot().innerHTML = html;
|
||||
var child, rootElm = getRoot();
|
||||
|
||||
// IE leaves zwsp in the dom on innerHTML
|
||||
while ((child = rootElm.firstChild)) {
|
||||
rootElm.removeChild(child);
|
||||
}
|
||||
|
||||
rootElm.innerHTML = html;
|
||||
}
|
||||
|
||||
function getRoot() {
|
||||
|
@ -18,8 +18,29 @@ ModuleLoader.require([
|
||||
return document.getElementById('view');
|
||||
}
|
||||
|
||||
function replaceWithZwsp(node) {
|
||||
for (var i = 0; i < node.childNodes.length; i++) {
|
||||
var childNode = node.childNodes[i];
|
||||
|
||||
if (childNode.nodeType === 3) {
|
||||
childNode.nodeValue = childNode.nodeValue.replace(/__ZWSP__/, ZWSP);
|
||||
} else {
|
||||
replaceWithZwsp(childNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setupHtml(html) {
|
||||
getRoot().innerHTML = html;
|
||||
var child, rootElm = getRoot();
|
||||
|
||||
// IE leaves zwsp in the dom on innerHTML
|
||||
while ((child = rootElm.firstChild)) {
|
||||
rootElm.removeChild(child);
|
||||
}
|
||||
|
||||
// IE messes zwsp up on innerHTML so we need to first set markers then replace then using dom operations
|
||||
rootElm.innerHTML = html.replace(new RegExp(ZWSP, 'g'), '__ZWSP__');
|
||||
replaceWithZwsp(rootElm);
|
||||
}
|
||||
|
||||
function findElm(selector) {
|
||||
|
@ -2,7 +2,7 @@ ModuleLoader.require(["tinymce/text/Zwsp"], function(Zwsp) {
|
||||
module("tinymce.text.Zwsp");
|
||||
|
||||
test('ZWSP', function() {
|
||||
strictEqual(Zwsp.ZWSP, '\u200b');
|
||||
strictEqual(Zwsp.ZWSP, '\uFEFF');
|
||||
});
|
||||
|
||||
test('isZwsp', function() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user