wp/wp-includes/js/tinymce/plugins/compat3x/plugin.js
changeset 7 cf61fcea0001
parent 5 5e2f62d02dcd
equal deleted inserted replaced
6:490d5cc509ed 7:cf61fcea0001
     1 /**
     1 /**
     2  * plugin.js
     2  * plugin.js
     3  *
     3  *
     4  * Copyright, Moxiecode Systems AB
       
     5  * Released under LGPL License.
     4  * Released under LGPL License.
       
     5  * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
     6  *
     6  *
     7  * License: http://www.tinymce.com/license
     7  * License: http://www.tinymce.com/license
     8  * Contributing: http://www.tinymce.com/contributing
     8  * Contributing: http://www.tinymce.com/contributing
     9  */
     9  */
    10 
    10 
    17  *
    17  *
    18  * Unsupported things:
    18  * Unsupported things:
    19  *  - No editor.onEvent
    19  *  - No editor.onEvent
    20  *  - Can't cancel execCommands with beforeExecCommand
    20  *  - Can't cancel execCommands with beforeExecCommand
    21  */
    21  */
    22 (function(tinymce) {
    22 (function (tinymce) {
    23 	var reported;
    23   var reported;
    24 
    24 
    25 	function noop() {
    25   function noop() {
    26 	}
    26   }
    27 
    27 
    28 	function log(apiCall) {
    28   function log(apiCall) {
    29 		if (!reported && window && window.console) {
    29     if (!reported && window && window.console) {
    30 			reported = true;
    30       reported = true;
    31 			console.log("Deprecated TinyMCE API call: " + apiCall);
    31       console.log("Deprecated TinyMCE API call: " + apiCall);
    32 		}
    32     }
    33 	}
    33   }
    34 
    34 
    35 	function Dispatcher(target, newEventName, argsMap, defaultScope) {
    35   function Dispatcher(target, newEventName, argsMap, defaultScope) {
    36 		target = target || this;
    36     target = target || this;
    37 
    37     var cbs = [];
    38 		if (!newEventName) {
    38 
    39 			this.add = this.addToTop = this.remove = this.dispatch = noop;
    39     if (!newEventName) {
    40 			return;
    40       this.add = this.addToTop = this.remove = this.dispatch = noop;
    41 		}
    41       return;
    42 
    42     }
    43 		this.add = function(callback, scope, prepend) {
    43 
    44 			log('<target>.on' + newEventName + ".add(..)");
    44     this.add = function (callback, scope, prepend) {
    45 
    45       log('<target>.on' + newEventName + ".add(..)");
    46 			// Convert callback({arg1:x, arg2:x}) -> callback(arg1, arg2)
    46 
    47 			function patchedEventCallback(e) {
    47       // Convert callback({arg1:x, arg2:x}) -> callback(arg1, arg2)
    48 				var callbackArgs = [];
    48       function patchedEventCallback(e) {
    49 
    49         var callbackArgs = [];
    50 				if (typeof argsMap == "string") {
    50 
    51 					argsMap = argsMap.split(" ");
    51         if (typeof argsMap == "string") {
    52 				}
    52           argsMap = argsMap.split(" ");
    53 
    53         }
    54 				if (argsMap && typeof argsMap != "function") {
    54 
    55 					for (var i = 0; i < argsMap.length; i++) {
    55         if (argsMap && typeof argsMap !== "function") {
    56 						callbackArgs.push(e[argsMap[i]]);
    56           for (var i = 0; i < argsMap.length; i++) {
    57 					}
    57             callbackArgs.push(e[argsMap[i]]);
    58 				}
    58           }
    59 
    59         }
    60 				if (typeof argsMap == "function") {
    60 
    61 					callbackArgs = argsMap(newEventName, e, target);
    61         if (typeof argsMap == "function") {
    62 					if (!callbackArgs) {
    62           callbackArgs = argsMap(newEventName, e, target);
    63 						return;
    63           if (!callbackArgs) {
    64 					}
    64             return;
    65 				}
    65           }
    66 
    66         }
    67 				if (!argsMap) {
    67 
    68 					callbackArgs = [e];
    68         if (!argsMap) {
    69 				}
    69           callbackArgs = [e];
    70 
    70         }
    71 				callbackArgs.unshift(defaultScope || target);
    71 
    72 
    72         callbackArgs.unshift(defaultScope || target);
    73 				if (callback.apply(scope || defaultScope || target, callbackArgs) === false) {
    73 
    74 					e.stopImmediatePropagation();
    74         if (callback.apply(scope || defaultScope || target, callbackArgs) === false) {
    75 				}
    75           e.stopImmediatePropagation();
    76 			}
    76         }
    77 
    77       }
    78 			target.on(newEventName, patchedEventCallback, prepend);
    78 
    79 
    79       target.on(newEventName, patchedEventCallback, prepend);
    80 			return patchedEventCallback;
    80 
    81 		};
    81       var handlers = {
    82 
    82         original: callback,
    83 		this.addToTop = function(callback, scope) {
    83         patched: patchedEventCallback
    84 			this.add(callback, scope, true);
    84       };
    85 		};
    85 
    86 
    86       cbs.push(handlers);
    87 		this.remove = function(callback) {
    87       return patchedEventCallback;
    88 			return target.off(newEventName, callback);
    88     };
    89 		};
    89 
    90 
    90     this.addToTop = function (callback, scope) {
    91 		this.dispatch = function() {
    91       this.add(callback, scope, true);
    92 			target.fire(newEventName);
    92     };
    93 
    93 
    94 			return true;
    94     this.remove = function (callback) {
    95 		};
    95       cbs.forEach(function (item, i) {
    96 	}
    96         if (item.original === callback) {
    97 
    97           cbs.splice(i, 1);
    98 	tinymce.util.Dispatcher = Dispatcher;
    98           return target.off(newEventName, item.patched);
    99 	tinymce.onBeforeUnload = new Dispatcher(tinymce, "BeforeUnload");
    99         }
   100 	tinymce.onAddEditor = new Dispatcher(tinymce, "AddEditor", "editor");
   100       });
   101 	tinymce.onRemoveEditor = new Dispatcher(tinymce, "RemoveEditor", "editor");
   101 
   102 
   102       return target.off(newEventName, callback);
   103 	tinymce.util.Cookie = {
   103     };
   104 		get: noop, getHash: noop, remove: noop, set: noop, setHash: noop
   104 
   105 	};
   105     this.dispatch = function () {
   106 
   106       target.fire(newEventName);
   107 	function patchEditor(editor) {
   107       return true;
   108 		function patchEditorEvents(oldEventNames, argsMap) {
   108     };
   109 			tinymce.each(oldEventNames.split(" "), function(oldName) {
   109   }
   110 				editor["on" + oldName] = new Dispatcher(editor, oldName, argsMap);
   110 
   111 			});
   111   tinymce.util.Dispatcher = Dispatcher;
   112 		}
   112   tinymce.onBeforeUnload = new Dispatcher(tinymce, "BeforeUnload");
   113 
   113   tinymce.onAddEditor = new Dispatcher(tinymce, "AddEditor", "editor");
   114 		function convertUndoEventArgs(type, event, target) {
   114   tinymce.onRemoveEditor = new Dispatcher(tinymce, "RemoveEditor", "editor");
   115 			return [
   115 
   116 				event.level,
   116   tinymce.util.Cookie = {
   117 				target
   117     get: noop, getHash: noop, remove: noop, set: noop, setHash: noop
   118 			];
   118   };
   119 		}
   119 
   120 
   120   function patchEditor(editor) {
   121 		function filterSelectionEvents(needsSelection) {
   121 
   122 			return function(type, e) {
   122     function translate(str) {
   123 				if ((!e.selection && !needsSelection) || e.selection == needsSelection) {
   123       var prefix = editor.settings.language || "en";
   124 					return [e];
   124       var prefixedStr = [prefix, str].join('.');
   125 				}
   125       var translatedStr = tinymce.i18n.translate(prefixedStr);
   126 			};
   126 
   127 		}
   127       return prefixedStr !== translatedStr ? translatedStr : tinymce.i18n.translate(str);
   128 
   128     }
   129 		if (editor.controlManager) {
   129 
   130 			return;
   130     function patchEditorEvents(oldEventNames, argsMap) {
   131 		}
   131       tinymce.each(oldEventNames.split(" "), function (oldName) {
   132 
   132         editor["on" + oldName] = new Dispatcher(editor, oldName, argsMap);
   133 		function cmNoop() {
   133       });
   134 			var obj = {}, methods = 'add addMenu addSeparator collapse createMenu destroy displayColor expand focus ' +
   134     }
   135 				'getLength hasMenus hideMenu isActive isCollapsed isDisabled isRendered isSelected mark ' +
   135 
   136 				'postRender remove removeAll renderHTML renderMenu renderNode renderTo select selectByIndex ' +
   136     function convertUndoEventArgs(type, event, target) {
   137 				'setActive setAriaProperty setColor setDisabled setSelected setState showMenu update';
   137       return [
   138 
   138         event.level,
   139 			log('editor.controlManager.*');
   139         target
   140 
   140       ];
   141 			function _noop() {
   141     }
   142 				return cmNoop();
   142 
   143 			}
   143     function filterSelectionEvents(needsSelection) {
   144 
   144       return function (type, e) {
   145 			tinymce.each(methods.split(' '), function(method) {
   145         if ((!e.selection && !needsSelection) || e.selection == needsSelection) {
   146 				obj[method] = _noop;
   146           return [e];
   147 			});
   147         }
   148 
   148       };
   149 			return obj;
   149     }
   150 		}
   150 
   151 
   151     if (editor.controlManager) {
   152 		editor.controlManager = {
   152       return;
   153 			buttons: {},
   153     }
   154 
   154 
   155 			setDisabled: function(name, state) {
   155     function cmNoop() {
   156 				log("controlManager.setDisabled(..)");
   156       var obj = {}, methods = 'add addMenu addSeparator collapse createMenu destroy displayColor expand focus ' +
   157 
   157         'getLength hasMenus hideMenu isActive isCollapsed isDisabled isRendered isSelected mark ' +
   158 				if (this.buttons[name]) {
   158         'postRender remove removeAll renderHTML renderMenu renderNode renderTo select selectByIndex ' +
   159 					this.buttons[name].disabled(state);
   159         'setActive setAriaProperty setColor setDisabled setSelected setState showMenu update';
   160 				}
   160 
   161 			},
   161       log('editor.controlManager.*');
   162 
   162 
   163 			setActive: function(name, state) {
   163       function _noop() {
   164 				log("controlManager.setActive(..)");
   164         return cmNoop();
   165 
   165       }
   166 				if (this.buttons[name]) {
   166 
   167 					this.buttons[name].active(state);
   167       tinymce.each(methods.split(' '), function (method) {
   168 				}
   168         obj[method] = _noop;
   169 			},
   169       });
   170 
   170 
   171 			onAdd: new Dispatcher(),
   171       return obj;
   172 			onPostRender: new Dispatcher(),
   172     }
   173 
   173 
   174 			add: function(obj) {
   174     editor.controlManager = {
   175 				return obj;
   175       buttons: {},
   176 			},
   176 
   177 			createButton: cmNoop,
   177       setDisabled: function (name, state) {
   178 			createColorSplitButton: cmNoop,
   178         log("controlManager.setDisabled(..)");
   179 			createControl: cmNoop,
   179 
   180 			createDropMenu: cmNoop,
   180         if (this.buttons[name]) {
   181 			createListBox: cmNoop,
   181           this.buttons[name].disabled(state);
   182 			createMenuButton: cmNoop,
   182         }
   183 			createSeparator: cmNoop,
   183       },
   184 			createSplitButton: cmNoop,
   184 
   185 			createToolbar: cmNoop,
   185       setActive: function (name, state) {
   186 			createToolbarGroup: cmNoop,
   186         log("controlManager.setActive(..)");
   187 			destroy: noop,
   187 
   188 			get: noop,
   188         if (this.buttons[name]) {
   189 			setControlType: cmNoop
   189           this.buttons[name].active(state);
   190 		};
   190         }
   191 
   191       },
   192 		patchEditorEvents("PreInit BeforeRenderUI PostRender Load Init Remove Activate Deactivate", "editor");
   192 
   193 		patchEditorEvents("Click MouseUp MouseDown DblClick KeyDown KeyUp KeyPress ContextMenu Paste Submit Reset");
   193       onAdd: new Dispatcher(),
   194 		patchEditorEvents("BeforeExecCommand ExecCommand", "command ui value args"); // args.terminate not supported
   194       onPostRender: new Dispatcher(),
   195 		patchEditorEvents("PreProcess PostProcess LoadContent SaveContent Change");
   195 
   196 		patchEditorEvents("BeforeSetContent BeforeGetContent SetContent GetContent", filterSelectionEvents(false));
   196       add: function (obj) {
   197 		patchEditorEvents("SetProgressState", "state time");
   197         return obj;
   198 		patchEditorEvents("VisualAid", "element hasVisual");
   198       },
   199 		patchEditorEvents("Undo Redo", convertUndoEventArgs);
   199       createButton: cmNoop,
   200 
   200       createColorSplitButton: cmNoop,
   201 		patchEditorEvents("NodeChange", function(type, e) {
   201       createControl: cmNoop,
   202 			return [
   202       createDropMenu: cmNoop,
   203 				editor.controlManager,
   203       createListBox: cmNoop,
   204 				e.element,
   204       createMenuButton: cmNoop,
   205 				editor.selection.isCollapsed(),
   205       createSeparator: cmNoop,
   206 				e
   206       createSplitButton: cmNoop,
   207 			];
   207       createToolbar: cmNoop,
   208 		});
   208       createToolbarGroup: cmNoop,
   209 
   209       destroy: noop,
   210 		var originalAddButton = editor.addButton;
   210       get: noop,
   211 		editor.addButton = function(name, settings) {
   211       setControlType: cmNoop
   212 			var originalOnPostRender, string, translated;
   212     };
   213 
   213 
   214 			function patchedPostRender() {
   214     patchEditorEvents("PreInit BeforeRenderUI PostRender Load Init Remove Activate Deactivate", "editor");
   215 				editor.controlManager.buttons[name] = this;
   215     patchEditorEvents("Click MouseUp MouseDown DblClick KeyDown KeyUp KeyPress ContextMenu Paste Submit Reset");
   216 
   216     patchEditorEvents("BeforeExecCommand ExecCommand", "command ui value args"); // args.terminate not supported
   217 				if (originalOnPostRender) {
   217     patchEditorEvents("PreProcess PostProcess LoadContent SaveContent Change");
   218 					return originalOnPostRender.call(this);
   218     patchEditorEvents("BeforeSetContent BeforeGetContent SetContent GetContent", filterSelectionEvents(false));
   219 				}
   219     patchEditorEvents("SetProgressState", "state time");
   220 			}
   220     patchEditorEvents("VisualAid", "element hasVisual");
   221 
   221     patchEditorEvents("Undo Redo", convertUndoEventArgs);
   222 			for (var key in settings) {
   222 
   223 				if (key.toLowerCase() === "onpostrender") {
   223     patchEditorEvents("NodeChange", function (type, e) {
   224 					originalOnPostRender = settings[key];
   224       return [
   225 					settings.onPostRender = patchedPostRender;
   225         editor.controlManager,
   226 				}
   226         e.element,
   227 			}
   227         editor.selection.isCollapsed(),
   228 
   228         e
   229 			if (!originalOnPostRender) {
   229       ];
   230 				settings.onPostRender = patchedPostRender;
   230     });
   231 			}
   231 
   232 
   232     var originalAddButton = editor.addButton;
   233 			if ( settings.title ) {
   233     editor.addButton = function (name, settings) {
   234 				// WP
   234       var originalOnPostRender;
   235 				string = (editor.settings.language || "en") + "." + settings.title;
   235 
   236 				translated = tinymce.i18n.translate(string);
   236       function patchedPostRender() {
   237 
   237         editor.controlManager.buttons[name] = this;
   238 				if ( string !== translated ) {
   238 
   239 					settings.title = translated;
   239         if (originalOnPostRender) {
   240 				}
   240           return originalOnPostRender.apply(this, arguments);
   241 				// WP end
   241         }
   242 			}
   242       }
   243 
   243 
   244 			return originalAddButton.call(this, name, settings);
   244       for (var key in settings) {
   245 		};
   245         if (key.toLowerCase() === "onpostrender") {
   246 
   246           originalOnPostRender = settings[key];
   247 		editor.on('init', function() {
   247           settings.onPostRender = patchedPostRender;
   248 			var undoManager = editor.undoManager, selection = editor.selection;
   248         }
   249 
   249       }
   250 			undoManager.onUndo = new Dispatcher(editor, "Undo", convertUndoEventArgs, null, undoManager);
   250 
   251 			undoManager.onRedo = new Dispatcher(editor, "Redo", convertUndoEventArgs, null, undoManager);
   251       if (!originalOnPostRender) {
   252 			undoManager.onBeforeAdd = new Dispatcher(editor, "BeforeAddUndo", null, undoManager);
   252         settings.onPostRender = patchedPostRender;
   253 			undoManager.onAdd = new Dispatcher(editor, "AddUndo", null, undoManager);
   253       }
   254 
   254 
   255 			selection.onBeforeGetContent = new Dispatcher(editor, "BeforeGetContent", filterSelectionEvents(true), selection);
   255       if (settings.title) {
   256 			selection.onGetContent = new Dispatcher(editor, "GetContent", filterSelectionEvents(true), selection);
   256         settings.title = translate(settings.title);
   257 			selection.onBeforeSetContent = new Dispatcher(editor, "BeforeSetContent", filterSelectionEvents(true), selection);
   257       }
   258 			selection.onSetContent = new Dispatcher(editor, "SetContent", filterSelectionEvents(true), selection);
   258 
   259 		});
   259       return originalAddButton.call(this, name, settings);
   260 
   260     };
   261 		editor.on('BeforeRenderUI', function() {
   261 
   262 			var windowManager = editor.windowManager;
   262     editor.on('init', function () {
   263 
   263       var undoManager = editor.undoManager, selection = editor.selection;
   264 			windowManager.onOpen = new Dispatcher();
   264 
   265 			windowManager.onClose = new Dispatcher();
   265       undoManager.onUndo = new Dispatcher(editor, "Undo", convertUndoEventArgs, null, undoManager);
   266 			windowManager.createInstance = function(className, a, b, c, d, e) {
   266       undoManager.onRedo = new Dispatcher(editor, "Redo", convertUndoEventArgs, null, undoManager);
   267 				log("windowManager.createInstance(..)");
   267       undoManager.onBeforeAdd = new Dispatcher(editor, "BeforeAddUndo", null, undoManager);
   268 
   268       undoManager.onAdd = new Dispatcher(editor, "AddUndo", null, undoManager);
   269 				var constr = tinymce.resolve(className);
   269 
   270 				return new constr(a, b, c, d, e);
   270       selection.onBeforeGetContent = new Dispatcher(editor, "BeforeGetContent", filterSelectionEvents(true), selection);
   271 			};
   271       selection.onGetContent = new Dispatcher(editor, "GetContent", filterSelectionEvents(true), selection);
   272 		});
   272       selection.onBeforeSetContent = new Dispatcher(editor, "BeforeSetContent", filterSelectionEvents(true), selection);
   273 	}
   273       selection.onSetContent = new Dispatcher(editor, "SetContent", filterSelectionEvents(true), selection);
   274 
   274     });
   275 	tinymce.on('SetupEditor', patchEditor);
   275 
   276 	tinymce.PluginManager.add("compat3x", patchEditor);
   276     editor.on('BeforeRenderUI', function () {
   277 
   277       var windowManager = editor.windowManager;
   278 	tinymce.addI18n = function(prefix, o) {
   278 
   279 		var I18n = tinymce.util.I18n, each = tinymce.each;
   279       windowManager.onOpen = new Dispatcher();
   280 
   280       windowManager.onClose = new Dispatcher();
   281 		if (typeof(prefix) == "string" && prefix.indexOf('.') === -1) {
   281       windowManager.createInstance = function (className, a, b, c, d, e) {
   282 			I18n.add(prefix, o);
   282         log("windowManager.createInstance(..)");
   283 			return;
   283 
   284 		}
   284         var constr = tinymce.resolve(className);
   285 
   285         return new constr(a, b, c, d, e);
   286 		if (!tinymce.is(prefix, 'string')) {
   286       };
   287 			each(prefix, function(o, lc) {
   287     });
   288 				each(o, function(o, g) {
   288   }
   289 					each(o, function(o, k) {
   289 
   290 						if (g === 'common') {
   290   tinymce.on('SetupEditor', function (e) {
   291 							I18n.data[lc + '.' + k] = o;
   291     patchEditor(e.editor);
   292 						} else {
   292   });
   293 							I18n.data[lc + '.' + g + '.' + k] = o;
   293 
   294 						}
   294   tinymce.PluginManager.add("compat3x", patchEditor);
   295 					});
   295 
   296 				});
   296   tinymce.addI18n = function (prefix, o) {
   297 			});
   297     var I18n = tinymce.util.I18n, each = tinymce.each;
   298 		} else {
   298 
   299 			each(o, function(o, k) {
   299     if (typeof prefix == "string" && prefix.indexOf('.') === -1) {
   300 				I18n.data[prefix + '.' + k] = o;
   300       I18n.add(prefix, o);
   301 			});
   301       return;
   302 		}
   302     }
   303 	};
   303 
       
   304     if (!tinymce.is(prefix, 'string')) {
       
   305       each(prefix, function (o, lc) {
       
   306         each(o, function (o, g) {
       
   307           each(o, function (o, k) {
       
   308             if (g === 'common') {
       
   309               I18n.data[lc + '.' + k] = o;
       
   310             } else {
       
   311               I18n.data[lc + '.' + g + '.' + k] = o;
       
   312             }
       
   313           });
       
   314         });
       
   315       });
       
   316     } else {
       
   317       each(o, function (o, k) {
       
   318         I18n.data[prefix + '.' + k] = o;
       
   319       });
       
   320     }
       
   321   };
   304 })(tinymce);
   322 })(tinymce);