ru-se.com

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

plugin.js (9450B)


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