323 líneas
9,2 KiB
JavaScript
323 líneas
9,2 KiB
JavaScript
|
/**
|
||
|
* plugin.js
|
||
|
*
|
||
|
* Released under LGPL License.
|
||
|
* Copyright (c) 1999-2017 Ephox Corp. All rights reserved
|
||
|
*
|
||
|
* License: http://www.tinymce.com/license
|
||
|
* Contributing: http://www.tinymce.com/contributing
|
||
|
*/
|
||
|
|
||
|
/*global tinymce:true, console:true */
|
||
|
/*eslint no-console:0, new-cap:0 */
|
||
|
|
||
|
/**
|
||
|
* This plugin adds missing events form the 4.x API back. Not every event is
|
||
|
* properly supported but most things should work.
|
||
|
*
|
||
|
* Unsupported things:
|
||
|
* - No editor.onEvent
|
||
|
* - Can't cancel execCommands with beforeExecCommand
|
||
|
*/
|
||
|
(function (tinymce) {
|
||
|
var reported;
|
||
|
|
||
|
function noop() {
|
||
|
}
|
||
|
|
||
|
function log(apiCall) {
|
||
|
if (!reported && window && window.console) {
|
||
|
reported = true;
|
||
|
console.log("Deprecated TinyMCE API call: " + apiCall);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function Dispatcher(target, newEventName, argsMap, defaultScope) {
|
||
|
target = target || this;
|
||
|
var cbs = [];
|
||
|
|
||
|
if (!newEventName) {
|
||
|
this.add = this.addToTop = this.remove = this.dispatch = noop;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
this.add = function (callback, scope, prepend) {
|
||
|
log('<target>.on' + newEventName + ".add(..)");
|
||
|
|
||
|
// Convert callback({arg1:x, arg2:x}) -> callback(arg1, arg2)
|
||
|
function patchedEventCallback(e) {
|
||
|
var callbackArgs = [];
|
||
|
|
||
|
if (typeof argsMap == "string") {
|
||
|
argsMap = argsMap.split(" ");
|
||
|
}
|
||
|
|
||
|
if (argsMap && typeof argsMap !== "function") {
|
||
|
for (var i = 0; i < argsMap.length; i++) {
|
||
|
callbackArgs.push(e[argsMap[i]]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (typeof argsMap == "function") {
|
||
|
callbackArgs = argsMap(newEventName, e, target);
|
||
|
if (!callbackArgs) {
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!argsMap) {
|
||
|
callbackArgs = [e];
|
||
|
}
|
||
|
|
||
|
callbackArgs.unshift(defaultScope || target);
|
||
|
|
||
|
if (callback.apply(scope || defaultScope || target, callbackArgs) === false) {
|
||
|
e.stopImmediatePropagation();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
target.on(newEventName, patchedEventCallback, prepend);
|
||
|
|
||
|
var handlers = {
|
||
|
original: callback,
|
||
|
patched: patchedEventCallback
|
||
|
};
|
||
|
|
||
|
cbs.push(handlers);
|
||
|
return patchedEventCallback;
|
||
|
};
|
||
|
|
||
|
this.addToTop = function (callback, scope) {
|
||
|
this.add(callback, scope, true);
|
||
|
};
|
||
|
|
||
|
this.remove = function (callback) {
|
||
|
cbs.forEach(function (item, i) {
|
||
|
if (item.original === callback) {
|
||
|
cbs.splice(i, 1);
|
||
|
return target.off(newEventName, item.patched);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
return target.off(newEventName, callback);
|
||
|
};
|
||
|
|
||
|
this.dispatch = function () {
|
||
|
target.fire(newEventName);
|
||
|
return true;
|
||
|
};
|
||
|
}
|
||
|
|
||
|
tinymce.util.Dispatcher = Dispatcher;
|
||
|
tinymce.onBeforeUnload = new Dispatcher(tinymce, "BeforeUnload");
|
||
|
tinymce.onAddEditor = new Dispatcher(tinymce, "AddEditor", "editor");
|
||
|
tinymce.onRemoveEditor = new Dispatcher(tinymce, "RemoveEditor", "editor");
|
||
|
|
||
|
tinymce.util.Cookie = {
|
||
|
get: noop, getHash: noop, remove: noop, set: noop, setHash: noop
|
||
|
};
|
||
|
|
||
|
function patchEditor(editor) {
|
||
|
|
||
|
function translate(str) {
|
||
|
var prefix = editor.settings.language || "en";
|
||
|
var prefixedStr = [prefix, str].join('.');
|
||
|
var translatedStr = tinymce.i18n.translate(prefixedStr);
|
||
|
|
||
|
return prefixedStr !== translatedStr ? translatedStr : tinymce.i18n.translate(str);
|
||
|
}
|
||
|
|
||
|
function patchEditorEvents(oldEventNames, argsMap) {
|
||
|
tinymce.each(oldEventNames.split(" "), function (oldName) {
|
||
|
editor["on" + oldName] = new Dispatcher(editor, oldName, argsMap);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function convertUndoEventArgs(type, event, target) {
|
||
|
return [
|
||
|
event.level,
|
||
|
target
|
||
|
];
|
||
|
}
|
||
|
|
||
|
function filterSelectionEvents(needsSelection) {
|
||
|
return function (type, e) {
|
||
|
if ((!e.selection && !needsSelection) || e.selection == needsSelection) {
|
||
|
return [e];
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
|
||
|
if (editor.controlManager) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
function cmNoop() {
|
||
|
var obj = {}, methods = 'add addMenu addSeparator collapse createMenu destroy displayColor expand focus ' +
|
||
|
'getLength hasMenus hideMenu isActive isCollapsed isDisabled isRendered isSelected mark ' +
|
||
|
'postRender remove removeAll renderHTML renderMenu renderNode renderTo select selectByIndex ' +
|
||
|
'setActive setAriaProperty setColor setDisabled setSelected setState showMenu update';
|
||
|
|
||
|
log('editor.controlManager.*');
|
||
|
|
||
|
function _noop() {
|
||
|
return cmNoop();
|
||
|
}
|
||
|
|
||
|
tinymce.each(methods.split(' '), function (method) {
|
||
|
obj[method] = _noop;
|
||
|
});
|
||
|
|
||
|
return obj;
|
||
|
}
|
||
|
|
||
|
editor.controlManager = {
|
||
|
buttons: {},
|
||
|
|
||
|
setDisabled: function (name, state) {
|
||
|
log("controlManager.setDisabled(..)");
|
||
|
|
||
|
if (this.buttons[name]) {
|
||
|
this.buttons[name].disabled(state);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
setActive: function (name, state) {
|
||
|
log("controlManager.setActive(..)");
|
||
|
|
||
|
if (this.buttons[name]) {
|
||
|
this.buttons[name].active(state);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
onAdd: new Dispatcher(),
|
||
|
onPostRender: new Dispatcher(),
|
||
|
|
||
|
add: function (obj) {
|
||
|
return obj;
|
||
|
},
|
||
|
createButton: cmNoop,
|
||
|
createColorSplitButton: cmNoop,
|
||
|
createControl: cmNoop,
|
||
|
createDropMenu: cmNoop,
|
||
|
createListBox: cmNoop,
|
||
|
createMenuButton: cmNoop,
|
||
|
createSeparator: cmNoop,
|
||
|
createSplitButton: cmNoop,
|
||
|
createToolbar: cmNoop,
|
||
|
createToolbarGroup: cmNoop,
|
||
|
destroy: noop,
|
||
|
get: noop,
|
||
|
setControlType: cmNoop
|
||
|
};
|
||
|
|
||
|
patchEditorEvents("PreInit BeforeRenderUI PostRender Load Init Remove Activate Deactivate", "editor");
|
||
|
patchEditorEvents("Click MouseUp MouseDown DblClick KeyDown KeyUp KeyPress ContextMenu Paste Submit Reset");
|
||
|
patchEditorEvents("BeforeExecCommand ExecCommand", "command ui value args"); // args.terminate not supported
|
||
|
patchEditorEvents("PreProcess PostProcess LoadContent SaveContent Change");
|
||
|
patchEditorEvents("BeforeSetContent BeforeGetContent SetContent GetContent", filterSelectionEvents(false));
|
||
|
patchEditorEvents("SetProgressState", "state time");
|
||
|
patchEditorEvents("VisualAid", "element hasVisual");
|
||
|
patchEditorEvents("Undo Redo", convertUndoEventArgs);
|
||
|
|
||
|
patchEditorEvents("NodeChange", function (type, e) {
|
||
|
return [
|
||
|
editor.controlManager,
|
||
|
e.element,
|
||
|
editor.selection.isCollapsed(),
|
||
|
e
|
||
|
];
|
||
|
});
|
||
|
|
||
|
var originalAddButton = editor.addButton;
|
||
|
editor.addButton = function (name, settings) {
|
||
|
var originalOnPostRender;
|
||
|
|
||
|
function patchedPostRender() {
|
||
|
editor.controlManager.buttons[name] = this;
|
||
|
|
||
|
if (originalOnPostRender) {
|
||
|
return originalOnPostRender.apply(this, arguments);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for (var key in settings) {
|
||
|
if (key.toLowerCase() === "onpostrender") {
|
||
|
originalOnPostRender = settings[key];
|
||
|
settings.onPostRender = patchedPostRender;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!originalOnPostRender) {
|
||
|
settings.onPostRender = patchedPostRender;
|
||
|
}
|
||
|
|
||
|
if (settings.title) {
|
||
|
settings.title = translate(settings.title);
|
||
|
}
|
||
|
|
||
|
return originalAddButton.call(this, name, settings);
|
||
|
};
|
||
|
|
||
|
editor.on('init', function () {
|
||
|
var undoManager = editor.undoManager, selection = editor.selection;
|
||
|
|
||
|
undoManager.onUndo = new Dispatcher(editor, "Undo", convertUndoEventArgs, null, undoManager);
|
||
|
undoManager.onRedo = new Dispatcher(editor, "Redo", convertUndoEventArgs, null, undoManager);
|
||
|
undoManager.onBeforeAdd = new Dispatcher(editor, "BeforeAddUndo", null, undoManager);
|
||
|
undoManager.onAdd = new Dispatcher(editor, "AddUndo", null, undoManager);
|
||
|
|
||
|
selection.onBeforeGetContent = new Dispatcher(editor, "BeforeGetContent", filterSelectionEvents(true), selection);
|
||
|
selection.onGetContent = new Dispatcher(editor, "GetContent", filterSelectionEvents(true), selection);
|
||
|
selection.onBeforeSetContent = new Dispatcher(editor, "BeforeSetContent", filterSelectionEvents(true), selection);
|
||
|
selection.onSetContent = new Dispatcher(editor, "SetContent", filterSelectionEvents(true), selection);
|
||
|
});
|
||
|
|
||
|
editor.on('BeforeRenderUI', function () {
|
||
|
var windowManager = editor.windowManager;
|
||
|
|
||
|
windowManager.onOpen = new Dispatcher();
|
||
|
windowManager.onClose = new Dispatcher();
|
||
|
windowManager.createInstance = function (className, a, b, c, d, e) {
|
||
|
log("windowManager.createInstance(..)");
|
||
|
|
||
|
var constr = tinymce.resolve(className);
|
||
|
return new constr(a, b, c, d, e);
|
||
|
};
|
||
|
});
|
||
|
}
|
||
|
|
||
|
tinymce.on('SetupEditor', function (e) {
|
||
|
patchEditor(e.editor);
|
||
|
});
|
||
|
|
||
|
tinymce.PluginManager.add("compat3x", patchEditor);
|
||
|
|
||
|
tinymce.addI18n = function (prefix, o) {
|
||
|
var I18n = tinymce.util.I18n, each = tinymce.each;
|
||
|
|
||
|
if (typeof prefix == "string" && prefix.indexOf('.') === -1) {
|
||
|
I18n.add(prefix, o);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (!tinymce.is(prefix, 'string')) {
|
||
|
each(prefix, function (o, lc) {
|
||
|
each(o, function (o, g) {
|
||
|
each(o, function (o, k) {
|
||
|
if (g === 'common') {
|
||
|
I18n.data[lc + '.' + k] = o;
|
||
|
} else {
|
||
|
I18n.data[lc + '.' + g + '.' + k] = o;
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
} else {
|
||
|
each(o, function (o, k) {
|
||
|
I18n.data[prefix + '.' + k] = o;
|
||
|
});
|
||
|
}
|
||
|
};
|
||
|
})(tinymce);
|