323 lines
		
	
	
	
		
			9.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			323 lines
		
	
	
	
		
			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); |