0

I am trying to develop a plugin, that shows on the page/post edit page. What I need to do, is detect when the content area changes. Either in visual mode, or text more. I would like to use a keyup event. So as the user is typing, I can provide my results.

But with the tinymce editor, I can't seem to properly detect changes in the content area. I was at one point able to detect changes if the page was loaded in text mode. But we need it to work in visual mode. When the keyup event occurs, I want to copy the entire contents of the body into a JS variable. Once I have that, I can go from there.

I can't seem to figure out how to accomplish this without hacking core and tweaking the tinymce init() method. Which isn't what I want to do.

Thank you.

Edit: Answer

Ok so I marked the proper answer. But I wanted to state that in my case, I needed to load this code in 'text' mode which mean that the included javascript file wasn't loaded at all. So I loaded the js into a script tag into the plugin area on the page and worked great. I still had to do the plugin init stuff, but it is loading an empty js file unless theres a way around that. Here is what I have in my javascript:

jQuery(document).ready(function($) {
    // Create 'keyup_event' tinymce plugin
    tinymce.PluginManager.add('keyup_event', function(editor, url) {

        // Create keyup event
        editor.on('keyup', function(e) {
            do_stuff_here();
        });
    });

    $('#content').on('keyup', function(e) {
        do_stuff_here();
    });

    // This function allows the script to run from both locations (visual and text)
    function do_stuff_here(content) {

        // test if the editor is available
        if (tinymce && null == tinymce.activeEditor)
        {
            console.log('tinymce not loaded (text mode)');
            // exit if the editor is not ready yet
            //return
            var data = $('#content-textarea-clone').text();
        }
        else
        {
            // visual mode
            data = $(tinymce.activeEditor.getContent()).text();
        }

        // rest of my processing
    }
});

Doing it this way works like a charm.

1 Answer 1

5

You can create a new plugin with the mce_external_plugins filter.. and link it to a js file. Then, in that file you can do your processing.

function tinymce_init() {
    // Hook to tinymce plugins filter
    add_filter( 'mce_external_plugins', 'tinymce_plugin' );
}
add_filter('init', 'tinymce_init');

function tinymce_plugin($init) {
    // We create a new plugin... linked to a js file.
    // Mine was created from a plugin... but you can change this to link to a file in your plugin
    $init['keyup_event'] = plugins_url() . '/test/keyup_event.js';
    return $init;
}

So, those functions will create the necessary hooks so our js file is loaded inside the tinymce editor.

Now... we can use the js file to grab the editor content on each keyup event.. and process it from there.

jQuery(document).ready(function($) {

    // Create 'keyup_event' tinymce plugin
    tinymce.PluginManager.add('keyup_event', function(editor, url) {

        // Create keyup event
        editor.on('keyup', function(e) {

            // Get the editor content (html)
            get_ed_content = tinymce.activeEditor.getContent();
            // Do stuff here... (run do_stuff_here() function)
            do_stuff_here(get_ed_content);
        });
    });

    // This is needed for running the keyup event in the text (HTML) view of the editor
    $('#content').on('keyup', function(e) {

        // Get the editor content (html)
        get_ed_content = tinymce.activeEditor.getContent();
        // Do stuff here... (run do_stuff_here() function)
        do_stuff_here(get_ed_content);
    });

    // This function allows the script to run from both locations (visual and text)
    function do_stuff_here(content) {

        // Now, you can further process the data in a single function
        alert(content);
    }
});

Now... each time you keyup in the editor.. the javascript file will process it's contents.

10
  • Wow! this is great. I will have to try it first thing in the morning. Thanks.
    – skift
    Oct 22, 2014 at 5:00
  • So this works great if the page is loaded with visual mode enabled. But does not work when text mode is enabled on page load. If it starts in text more, do my processing, it does not work. But as soon as i hit visual mode, it all works. I tried binding to this but doesnt work either: $('#content-textarea-clone')
    – skift
    Oct 22, 2014 at 17:52
  • Okay.. I thought you mentioned you already had a method of doing the text side. I may have misread your original post. Gimme a few minutes.. and I'll edit my answer.
    – josh
    Oct 22, 2014 at 18:02
  • I did, but now I can't get it to work. It must have been that wordpress black magic happening. :-) I tried to get it back as I some how removed what I had to get it to work. I was going to update my question on what I did. So I still want to get that to work and in case others find this they see how to as well. Thanks.
    – skift
    Oct 22, 2014 at 18:16
  • No worries. Answer edited. I realized you would have had to process the contents twice (once for visual side; once for text side). So instead of having to process your data in two different locations; I just made a do_stuff_here() function. This allows you to pass the editor data from both locations... to a single function... where you can further process the data.
    – josh
    Oct 22, 2014 at 18:35

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