You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

305 lines
8.1 KiB

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