TinyMCE: How bind on event after its initialized

2019-06-16 06:06发布

I already searched a lot but by google-fu'ing don't get me any results :(

I have an already initialized tinyMCE editor which initialization process I cannot control, so code like the following don't work at all:

tinyMCE.init({
   ...
   setup : function(ed) {
          ed.onChange.add(function(ed, l) {
                  console.debug('Editor contents was modified. Contents: ' + l.content);
          });
   }
});

Code like the following doesn't work either since the jQuery tinymce plugin isn't defined:

$('textarea').tinymce({
    setup: function(ed) {
        ed.onClick.add(function(ed, e) {
            alert('Editor was clicked: ' + e.target.nodeName);
        });
    }
});

I mean, it has to be using the tinymce.something syntax.

How can I bind a callback function to whatever tinyMCE event after tinyMCE is already initialized?

5条回答
萌系小妹纸
2楼-- · 2019-06-16 06:50

Although this post is old now but I think other people will need this answer. I had the same problem and to fix it I did this:

tinyMCE.init({
        ...
        init_instance_callback : "myCustomInitInstance"
});

Based on http://www.tinymce.com/wiki.php/Configuration3x:init_instance_callback

查看更多
forever°为你锁心
3楼-- · 2019-06-16 06:50

In TinyMCE 4, onChange doesn't exist. You have to use:

tinymce.get('myeditorname').on("change", function() { alert("stuff"); });
查看更多
我欲成王,谁敢阻挡
4楼-- · 2019-06-16 07:02

Here is my solution for binding events to one or multiple textareas at any time, given this code is appended after including the tinymce javascript file into your page. (In other words, the only thing required for this to work, is the existence of the 'tinymce' variable)

// Loop already initialised editors
for(id in tinymce.editors){
    if(id.trim()){
        elementReady(id);
    }
}

// Wait for non-initialised editors to initialise
tinymce.on('AddEditor', function (e) {
    elementReady(e.editor.id);
});

// function to call when tinymce-editor has initialised
function elementReady(editor_id){

    // get tinymce editor based on instance-id
    var _editor = tinymce.editors[editor_id];

    // bind the following event(s)
    _editor.on("change", function(e){

        // execute code
    });
}

Note that the 'change' event is not bound to always trigger instantly after something changed. According to the documentation, it “gets fired when changes are made inside the editor that cause an undo level to be added.” Which in my experience, does not always happen when you expect it to happen.

One way to overcome this is by binding multiple events, such as 'input change', however, there will be some overlapping, which should then be filtered.

查看更多
\"骚年 ilove
5楼-- · 2019-06-16 07:05

After hacking into the tinymce object with console.log(), I found a working solution:

setTimeout(function () {
       for (var i = 0; i < tinymce.editors.length; i++) {
             tinymce.editors[i].onChange.add(function (ed, e) {
             // Update HTML view textarea (that is the one used to send the data to server).
         ed.save();
       });
            }
}, 1000);

Inside that callback function one can set the whatever event binding one wants.

The setTimeout call is to overcome the racing condition of tinymce and jQuery, since when the call to tinymce.editors[i].onChange.add() is made tinymce wasn't initialized yet.

查看更多
爷的心禁止访问
6楼-- · 2019-06-16 07:05

EDIT: oops - I thought this was another question I was looking at that was specific to WordPress + TinyMCE, guess not. Though I'll leave the answer here as it may be helpful to others.

The proper way to do this would be to append to the tinyMCE init with the WordPress filter. For example:

PHP (in functions.php or other location that is run on edit page load):

  add_action( 'init', 'register_scripts' );     
  function register_scripts(){
    if ( is_admin() ) {
      wp_register_script(
        'admin-script',
        get_stylesheet_directory_uri() . "/js/admin/admin.js",
        array('jquery'),
        false,
        true
      );
    }
  }

  add_action( 'admin_enqueue_scripts', 'print_admin_scripts' );
  function print_admin_scripts() {        
    wp_enqueue_script('admin-script');
  }

  add_filter( 'tiny_mce_before_init', 'my_tinymce_setup_function' );
  function my_tinymce_setup_function( $initArray ) {
    $initArray['setup'] = 'function(ed){
      ed.onChange.add(function(ed, l) {
        tinyOnChange(ed,l);
      });
    }';
    return $initArray;
  }

JavaScript (/js/admin/admin.js)

  (function($){
    window.tinyOnChange = function(ed, l){        
      console.log('Editor contents was modified. Contents: ' + l.content);      
    }
  }(jQuery);

This is tested and working in WordPress 3.9 (though I am simply getting the console output:

Deprecated TinyMCE API call: <target>.onChange.add(..) 

But that's due to tinyMCE deprecating code you're trying to use. This method does still work to modify to any of the tinyMCE init options - I'm currently using it for init_instance_callback and it's working great.

-Thomas

查看更多
登录 后发表回答