Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

Once a page has loaded, how do I create a TinyMCE editor?

Putting a wp_editor call in an AJAX request then displaying it gives this:

enter image description here

Visual and text tabs are nonfunctional, no toolbar, no active TinyMCE instance, just the html markup. I need to instantiate the JS component of TinyMCE, but how?

I've also tried making a call in my AJAX response PHP to _WP_Editors::editor_js();, and I can see the response in the console using console.log and I see the JS script there, but it is not inserted into the DOM and it is never executed

share|improve this question
1  
Get it per Ajax … where you can use wp_editor()? –  toscho Jul 26 '12 at 18:25
    
wp_editor returns all the html needed but it doesn't return the JS needed to instantiate the TinyMCE instance –  Tom J Nowell Mar 27 '13 at 13:57
1  
Sure you got the right files included? –  kaiser Mar 27 '13 at 14:04
    
yes, I can instantiate a wp_editor on the same page, and I get improvements but the problem is not solved. I create 2 editors in my first AJAX and they sort of work, one has a full working editor, the second is a bit weird and shows no buttons on the text view. Second AJAX request however gives 2 nonfuncitoning editors, plain markup, and JS errors "Uncaught TypeError: Cannot read property 'click' of undefined" –  Tom J Nowell Mar 27 '13 at 14:31
    
See How to load wp_editor via AJAX –  toscho Jan 31 at 15:59

1 Answer 1

up vote 2 down vote accepted

I've made some progress

Load a wp_editor in the initial page load in a hidden div, then do the AJAX call to grab the editor markup.

While in PHP, you will need to retrieve the IDs of the editors created via wp_editor calls. Unfortunately, the variables on the _WP_Editors class are private, but wecan get around this by using filters. To do this we start by calling the editor_js hook inside an output buffer. It will attempt to generate the needed settings and output the required JS, although this JS will not work when sent back via AJAX and inserted.

At the end of this call, the _WP_Editors class pases the mcesettings array through a filter, which we will use to make a copy that we can pull the editor IDs out of:

add_action( 'after_wp_tiny_mce', array( $this, 'steal_away_mcesettings' ) );

function steal_away_mcesettings( $mcesettings ) {
    $this->mcesettings = $mcesettings;
}

So after we've added this filter, we call out editor_js function:

ob_start();
_WP_Editors::editor_js();
ob_end_clean(); 

We can now use our $mcesettings copy to fill in a list of IDs:

$ids = array();

foreach ( $this->mcesettings as $editor_id => $init ) {
    $ids[] = $editor_id;
}

The ids array can now be sent back in the AJAX response along with the html.

Once in the browser, we can insert the html into the page, and then using our editor_ids, we can instantiate the TinyMCE instances like this:

function tinyMCE_bulk_init( editor_ids ) {
    var init, ed, qt, first_init, DOM, el, i;

    if ( typeof(tinymce) == 'object' ) {

        var editor;
        for ( e in tinyMCEPreInit.mceInit ) {
            editor = e;
            break;
        }
        for ( i in editor_ids ) {
            var ed_id = editor_ids[i];
            tinyMCEPreInit.mceInit[ed_id] = tinyMCEPreInit.mceInit[editor];
            tinyMCEPreInit.mceInit[ed_id]['elements'] = ed_id;
            tinyMCEPreInit.mceInit[ed_id]['body_class'] = ed_id;
            tinyMCEPreInit.mceInit[ed_id]['succesful'] =  false;
        }

        for ( ed in tinyMCEPreInit.mceInit ) {
            // check if there is an adjacent span with the class mceEditor
            if ( ! jQuery('#'+ed).next().hasClass('mceEditor') ) {
                init = tinyMCEPreInit.mceInit[ed];
                try {
                    tinymce.init(init);
                } catch(e){
                    console.log('fail');
                }
            }
        }

    }
}

Because we don't have the ability to generate the necessary TinyMCE settings ourselves to match the WordPress style, we instead steal them from the instance we created in the initial page load, and make copies. We then modify the copies to use the correct element IDs and proceed as usual, checking that the elements dont already have an instance.

enter image description here

Issues

  • The tabs for plain text vs visual content do not work
  • No quick tags on the plaintext view
  • The extra weight of the initial TinyMCE instance
  • No Media uploader button
  • Adding 2 TinyMCE instances or more in an AJAX request leads to one working instance, and the others being broken. I'm not sure why this is the case, yet 2 AJAX requests with 1 instance each, gives you 2 working instances.
  • The JS could be modified to not modify the TinyMCEPreInit structure, and pass the copy straight into the initialiser, removing a DOM traversal in the process
share|improve this answer
    
For a realworld example, look at the Bulk Edit plugin on wordpress.org, which is directly based on the above answer –  Tom J Nowell Jan 31 at 15:04

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.