4
* Copyright, Moxiecode Systems AB
5
* Released under LGPL License.
7
* License: http://www.tinymce.com/license
8
* Contributing: http://www.tinymce.com/contributing
11
/*global tinymce:true, console:true */
12
/*eslint no-console:0, new-cap:0 */
15
* This plugin adds missing events form the 4.x API back. Not every event is
16
* properly supported but most things should work.
20
* - Can't cancel execCommands with beforeExecCommand
28
function log(apiCall) {
29
if (!reported && window && window.console) {
31
console.log("Deprecated TinyMCE API call: " + apiCall);
35
function Dispatcher(target, newEventName, argsMap, defaultScope) {
36
target = target || this;
39
this.add = this.addToTop = this.remove = this.dispatch = noop;
43
this.add = function(callback, scope, prepend) {
44
log('<target>.on' + newEventName + ".add(..)");
46
// Convert callback({arg1:x, arg2:x}) -> callback(arg1, arg2)
47
function patchedEventCallback(e) {
48
var callbackArgs = [];
50
if (typeof argsMap == "string") {
51
argsMap = argsMap.split(" ");
54
if (argsMap && typeof argsMap != "function") {
55
for (var i = 0; i < argsMap.length; i++) {
56
callbackArgs.push(e[argsMap[i]]);
60
if (typeof argsMap == "function") {
61
callbackArgs = argsMap(newEventName, e, target);
71
callbackArgs.unshift(defaultScope || target);
73
if (callback.apply(scope || defaultScope || target, callbackArgs) === false) {
74
e.stopImmediatePropagation();
78
target.on(newEventName, patchedEventCallback, prepend);
80
return patchedEventCallback;
83
this.addToTop = function(callback, scope) {
84
this.add(callback, scope, true);
87
this.remove = function(callback) {
88
return target.off(newEventName, callback);
91
this.dispatch = function() {
92
target.fire(newEventName);
98
tinymce.util.Dispatcher = Dispatcher;
99
tinymce.onBeforeUnload = new Dispatcher(tinymce, "BeforeUnload");
100
tinymce.onAddEditor = new Dispatcher(tinymce, "AddEditor", "editor");
101
tinymce.onRemoveEditor = new Dispatcher(tinymce, "RemoveEditor", "editor");
103
tinymce.util.Cookie = {
104
get: noop, getHash: noop, remove: noop, set: noop, setHash: noop
107
function patchEditor(editor) {
108
function patchEditorEvents(oldEventNames, argsMap) {
109
tinymce.each(oldEventNames.split(" "), function(oldName) {
110
editor["on" + oldName] = new Dispatcher(editor, oldName, argsMap);
114
function convertUndoEventArgs(type, event, target) {
121
function filterSelectionEvents(needsSelection) {
122
return function(type, e) {
123
if ((!e.selection && !needsSelection) || e.selection == needsSelection) {
129
if (editor.controlManager) {
134
var obj = {}, methods = 'add addMenu addSeparator collapse createMenu destroy displayColor expand focus ' +
135
'getLength hasMenus hideMenu isActive isCollapsed isDisabled isRendered isSelected mark ' +
136
'postRender remove removeAll renderHTML renderMenu renderNode renderTo select selectByIndex ' +
137
'setActive setAriaProperty setColor setDisabled setSelected setState showMenu update';
139
log('editor.controlManager.*');
145
tinymce.each(methods.split(' '), function(method) {
152
editor.controlManager = {
155
setDisabled: function(name, state) {
156
log("controlManager.setDisabled(..)");
158
if (this.buttons[name]) {
159
this.buttons[name].disabled(state);
163
setActive: function(name, state) {
164
log("controlManager.setActive(..)");
166
if (this.buttons[name]) {
167
this.buttons[name].active(state);
171
onAdd: new Dispatcher(),
172
onPostRender: new Dispatcher(),
177
createButton: cmNoop,
178
createColorSplitButton: cmNoop,
179
createControl: cmNoop,
180
createDropMenu: cmNoop,
181
createListBox: cmNoop,
182
createMenuButton: cmNoop,
183
createSeparator: cmNoop,
184
createSplitButton: cmNoop,
185
createToolbar: cmNoop,
186
createToolbarGroup: cmNoop,
189
setControlType: cmNoop
192
patchEditorEvents("PreInit BeforeRenderUI PostRender Load Init Remove Activate Deactivate", "editor");
193
patchEditorEvents("Click MouseUp MouseDown DblClick KeyDown KeyUp KeyPress ContextMenu Paste Submit Reset");
194
patchEditorEvents("BeforeExecCommand ExecCommand", "command ui value args"); // args.terminate not supported
195
patchEditorEvents("PreProcess PostProcess LoadContent SaveContent Change");
196
patchEditorEvents("BeforeSetContent BeforeGetContent SetContent GetContent", filterSelectionEvents(false));
197
patchEditorEvents("SetProgressState", "state time");
198
patchEditorEvents("VisualAid", "element hasVisual");
199
patchEditorEvents("Undo Redo", convertUndoEventArgs);
201
patchEditorEvents("NodeChange", function(type, e) {
203
editor.controlManager,
205
editor.selection.isCollapsed(),
210
var originalAddButton = editor.addButton;
211
editor.addButton = function(name, settings) {
212
var originalOnPostRender, string, translated;
214
function patchedPostRender() {
215
editor.controlManager.buttons[name] = this;
217
if (originalOnPostRender) {
218
return originalOnPostRender.call(this);
222
for (var key in settings) {
223
if (key.toLowerCase() === "onpostrender") {
224
originalOnPostRender = settings[key];
225
settings.onPostRender = patchedPostRender;
229
if (!originalOnPostRender) {
230
settings.onPostRender = patchedPostRender;
233
if ( settings.title ) {
235
string = (editor.settings.language || "en") + "." + settings.title;
236
translated = tinymce.i18n.translate(string);
238
if ( string !== translated ) {
239
settings.title = translated;
244
return originalAddButton.call(this, name, settings);
247
editor.on('init', function() {
248
var undoManager = editor.undoManager, selection = editor.selection;
250
undoManager.onUndo = new Dispatcher(editor, "Undo", convertUndoEventArgs, null, undoManager);
251
undoManager.onRedo = new Dispatcher(editor, "Redo", convertUndoEventArgs, null, undoManager);
252
undoManager.onBeforeAdd = new Dispatcher(editor, "BeforeAddUndo", null, undoManager);
253
undoManager.onAdd = new Dispatcher(editor, "AddUndo", null, undoManager);
255
selection.onBeforeGetContent = new Dispatcher(editor, "BeforeGetContent", filterSelectionEvents(true), selection);
256
selection.onGetContent = new Dispatcher(editor, "GetContent", filterSelectionEvents(true), selection);
257
selection.onBeforeSetContent = new Dispatcher(editor, "BeforeSetContent", filterSelectionEvents(true), selection);
258
selection.onSetContent = new Dispatcher(editor, "SetContent", filterSelectionEvents(true), selection);
261
editor.on('BeforeRenderUI', function() {
262
var windowManager = editor.windowManager;
264
windowManager.onOpen = new Dispatcher();
265
windowManager.onClose = new Dispatcher();
266
windowManager.createInstance = function(className, a, b, c, d, e) {
267
log("windowManager.createInstance(..)");
269
var constr = tinymce.resolve(className);
270
return new constr(a, b, c, d, e);
275
tinymce.on('SetupEditor', patchEditor);
276
tinymce.PluginManager.add("compat3x", patchEditor);
278
tinymce.addI18n = function(prefix, o) {
279
var I18n = tinymce.util.I18n, each = tinymce.each;
281
if (typeof(prefix) == "string" && prefix.indexOf('.') === -1) {
286
if (!tinymce.is(prefix, 'string')) {
287
each(prefix, function(o, lc) {
288
each(o, function(o, g) {
289
each(o, function(o, k) {
290
if (g === 'common') {
291
I18n.data[lc + '.' + k] = o;
293
I18n.data[lc + '.' + g + '.' + k] = o;
299
each(o, function(o, k) {
300
I18n.data[prefix + '.' + k] = o;