简体   繁体   中英

How to run code in TinyMCE plugin after `init_instance_callback` has already been completed?

I'm trying to create a new TinyMCE plugin. Is there a way to get a callback to the plugin code after the init_instance_callback has already been run for the whole editor? I would need to run some code within the plugin when this happens and I'd rather automate this inside the plugin instead of documenting that some plugin specific method must be called from the end user configured init_instance_callback callback.

Are the events from TinyMCE editor to the plugin documented somewhere? I would assume it's something along the lines

tinymce.PluginManager.add('myplugin123', function(editor, url)
{
  ...
  editor.on("some-event-name-for-init_instance_callback-complete", function (x)
  {
     // the code I would like to run goes here
     ...
  });
});

I would like use the latest TinyMCE, right now it appears to be version 5.10.2.

I don't believe that callback fires an event when it is done but you can do so manually with your own custom event:

https://fiddle.tiny.cloud/9Uhaab/2

The key part is:

init_instance_callback : function(editor) {
    console.log('Editor: ' + editor.id + ' is now initialized.');
    //Fire your own event at the end of init_instance_callback
    editor.fire('my_custom_event');
},

The last line fires an event you create. You can then listen for that event and do what you need. In the example Fiddle I also do that in the TinyMCE configuration but you can do that in your plugin as you suggest.

It seems that the TinyMCE runs following code to initialize the editor (actual source code for TinyMCE version 5.10.2):

var initEditor = function (editor) {
  editor.bindPendingEventDelegates();
  editor.initialized = true;
  fireInit(editor);
  editor.focus(true);
  moveSelectionToFirstCaretPosition(editor);
  editor.nodeChanged({ initial: true });
  editor.execCallback('init_instance_callback', editor);
  autoFocus(editor);
};

The method call fireInit(editor); triggers event Init for the editor and all event listeners will be executed immediately (including any plugin that has previously run editor.on("Init", ...) to wait for this event).

If that plugin code then wants to run code after the init_instance_callback has already been executed, it can run

setTimeout(function()
{
  // code to run after init_instance_callback
}, 0);

This works in practice with the current implementation because this will add the function reference to the end of browser native event queue which will be run when JS code returns to the browser native event loop. This obviously happens when TinyMCE code has finished running the code that it's currently executing.

Note that the autoFocus() implementation will trigger the focus event after hardcoded 100 ms delay. And autoFocus() will do nothing if editor.settings.auto_focus is not true.

Note that none of this is documented anywhere. The above source code is part of TinyMCE 5.10.2 but it could change in the future so consider above as a hack instead of proper supported feature.

I would say adding function call via setTimeout() and listening for focus event should be pretty good. Whichever happens first will be probably immediately (or after 100 ms delay) after the init_instance_callback has already been executed.

Note that if TinyMCE changes behavior to trigger init_instance_callback via browser native event loop in the future, the above hack will run code too early. Note that in that case there's no safe delay value (> 0) to wait for the TinyMCE to run first because in theory the JS execution can stall for unlimited time between Init event and setting timeout for init_instance_callback trigger. If 0 is not a safe value (like with current implementation) then any non-zero value is not safe either.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM