m.spyratos
m.spyratos

Reputation: 4219

WP - JS - Get Instance of Tinymce Editor

I'm creating a Wordpress plugin, which adds a metabox right under the post editor containing a button. The plugin also loads a Javascript file right below the closing </body> tag.

PURPOSE

At the moment, what I am trying to achieve with the plugin is simple. When a user enters content to the editor and then clicks the button inside the metabox, I want to modify the editor's content.

JS CODE

In its simplest form:

jQuery(document).ready(function($) {
   $('#button').on('click', function(e) {
      e.preventDefault();

      var editor = tinyMCE.get("content");
      editor.setContent(some_content);
   });
});

PROBLEM

The problem is that editor variable returns undefined.

FIREBUG (when trying to set var editor)

wpActiveEditor : "content"
editors : [ ]
activeEditor : null

WHAT HAVE I TRIED

I have tried many, many things (also many small tweaks) found on Tinymce's documentation and here on Stackoverflow but the problem still remains the same.

Any help would be very appreciated.

PS. The content textarea is visible when running my tests.

Upvotes: 3

Views: 6596

Answers (3)

Stephan Samuel
Stephan Samuel

Reputation: 697

Many years later but maybe this will help someone...

In addition to everything said above some consideration needs to be paid to the JS event model. Consider:

  1. TinyMCE may not initialize (and the tinymce global may not be available) until the document is done loading. The OP correctly wrapped calls in jQuery(fn), which will solve this. This is relevant if you're using an added framework that initializes and tries to manipulate the editors (like AngularJS directives).
  2. Parts of initialization seem to be asynchronous so even if you wrap everything in jQuery(fn) the editors may not be available until later. WP loads Underscore as part of Backbone so wrapping initial attempts to locate editors in _.defer(fn) seems to get me lots of mileage. This could be done with the native JS setTimeout as well.
  3. Beyond the fantastic answer by @m.spyratos, it may be helpful to note that you can hook mode change events (Visual/Text) by adding a jQuery click event handler to button.switch-tmce[data-wp-editor="my_editor_id"] and button.switch-html[data-wp-editor="my_editor_id"] for when the user selects Visual or Text, respectively. Your version may vary but I found that the textarea goes away when switching to Visual mode and the tinymce.editor instance goes away when switching to Text mode. Hooking to these events gives a persistent means to re-hook when the user decides to change modes.
  4. As a quick reference, you can attach to the editor object (activeEditor or something in editors[], which is keyed by editor ID) to receive any and all changes in visual editor content with by hooking to the editor with editor.on('NodeChange keyup', fn) and a single event callback. I included blur in my solution as well, for posterity. The text editor content can be hooked with jQuery('textarea#my_editor_id').on('keyup', fn).

I have successfully managed multiple editors on a page that are entirely two-way bound entirely through JS; the editors are created with wp_editor and no initial content then loaded asynchronously (via AJAX in my case) and managed through multiple edit cycles without a server round-trip. This is possible, if not slightly convoluted.

Upvotes: 0

m.spyratos
m.spyratos

Reputation: 4219

When the Editor first loads with the "Text" mode active, tinymce does not get initialized, therefore you cannot use tinyMCE.get(), as opposed to the "Visual" mode.

(I hadn't noticed that it actually works on the "Visual" mode, as I was keep testing it on the "Text" mode)

So, a conditional statement is necessary to determine first which tab is active. I solved my problem with this method:

function setEditorContent(val) {
  var $_editorTextArea = $('#content');
  $_editorTextArea.is(':visible') ? $_editorTextArea.val(val) : tinyMCE.get('content').setContent(val);
}

Hope this answer will prevent some headaches :)

Upvotes: 11

Thariama
Thariama

Reputation: 50832

Well, a live example would help a lot. This way i can only guess: It looks a bit as if you cannot get the editor you want. There are two possible reasons that come into my mind:

  1. The editor id you are using is not the id of your editor To verify this you check the id of your editors soure html element (in most cases a textarea).If there is no id set tinymce will use "content" as default.

  2. There iy no editor initialized at all To verify this you can use console.log(tinymce.editors) in your javascript console. If no editor is initialized then you will get an empty array.

Upvotes: 1

Related Questions