38

I am trying to add the tinyMCE editor to my page, remove it, then add it again but am getting errors.

When I run Part A, then Part B, Than Part A again I get the error:

Error: g.win.document is null
Source File: tiny_mce/tiny_mce.js Line: 1

Part A

tinyMCE.init({
    'mode' : 'exact',
    'elements' : '" + ctrl.ID + "Editor',
    'plugins' : 'insertdatetime,TVCMSLink,TVCMSImage',
    'theme' : 'advanced',
    'theme_advanced_layout_manager' : 'SimpleLayout',
    'theme_advanced_buttons1' : 'backcolor, forecolor, |, bold, underline, strikethrough, |, numlist, bullist, charmap, |, undo, redo, |, anchor, link, tvlink, unlink',
    'theme_advanced_buttons2' : '',
    'theme_advanced_buttons3' : ''
});

Part B

tinyMCE.getInstanceById('" + ctrl.ID + "Editor').remove();

Edit:

Below is the full JavaScript function. The first time through it opens the dialog and works, the contents is in the editor and there is no error. When I click the close button, the dialog is closed. When I run the function again, the dialog displays but the editor is empty and there is the above error.

function show_HP1B0() {
$('.EditLink').hide();
$.ajax({
    type: 'post',
    url: 'genericHandler.ashx',
    data: 'cmd=select&tableName=ExtraBlocks&id=4',
    dataType: 'json',
    success: function(data) {
        $('#HP1B0Editor').html(data['rows'][0]['Content']);
        alert($('#HP1B0Editor').html());
        tinyMCE.init({                 'mode' : 'exact', 
            'elements' : 'HP1B0Editor', 
            'plugins' : 'insertdatetime,Link,Image',
            'theme' : 'advanced',
            'theme_advanced_layout_manager' : 'SimpleLayout',
            'theme_advanced_buttons1' : 'backcolor, forecolor, |, bold, underline, strikethrough, |, numlist, bullist, charmap, |, undo, redo, |, anchor, link, tvlink, unlink',
            'theme_advanced_buttons2' : '',
            'theme_advanced_buttons3' : ''
        });
        var dlg = $('#ctl00_EXTRA_HTML_0_HP1B0Editor').dialog({
            modal: false,
            draggable: false,
            position: 'center',
            zIndex: 99999,  // Above the overlay
            width: 370,
            title: 'Content Block Editor',
            closeText: '',
            open: function () {
                $('body').css('overflow', 'hidden');
                if ($.browser.msie) { $('html').css('overflow', 'hidden'); } $('<div>').attr('id', 'loader').appendTo('body').show();
            },
            close: function () { $('body').css('overflow', 'auto'); if ($.browser.msie) { $('html').css('overflow', 'auto'); } $('#loader').remove(); },
            buttons: {
                'Save': function () {
                    tinyMCE.getInstanceById('HP1B0Editor').remove();
                    $('.EditLink').show();
                    $(this).dialog('close');
                },
                'Cancel': function () {
        alert('HP1B0Editor');
                    tinyMCE.getInstanceById('HP1B0Editor').remove();
                    $('.EditLink').show();
                    $(this).dialog('close');
                }
            }
        }).parent();
        dlg.appendTo(jQuery('form:first'));
    },
    error: function(data) {
        $('.EditLink').show();
        $('#HP1B0Editor').html('Error');
    }
});
}
peterh
  • 11,875
  • 18
  • 85
  • 108
Justin808
  • 20,859
  • 46
  • 160
  • 265
  • 1
    I don't know how this editor works but i'd check to make sure when you call `remove` it isn't removing the elements from the page also. – Josiah Ruddell Jan 10 '11 at 21:34

14 Answers14

81

To cleanly remove an editor instance and avoid any errors use:

tinymce.EditorManager.execCommand('mceRemoveControl',true, editor_id);

To reinitialize the instance use:

tinymce.EditorManager.execCommand('mceAddControl',true, editor_id);

Be aware that when moving TinyMCE editors in the DOM you need to removeControl and addControl too, otherwise it results in JS errors.


As of TinyMCE 4 the methods to remove and reinitialize an instance are now...

To cleanly remove an editor instance and avoid any errors use:

tinymce.EditorManager.execCommand('mceRemoveEditor',true, editor_id);

To reinitialize the instance use:

tinymce.EditorManager.execCommand('mceAddEditor',true, editor_id);
Thariama
  • 50,002
  • 13
  • 138
  • 166
  • 4
    I am getting NS_ERROR_UNEXPECTED in firefox, Can you help me on this? Thanks – TheFoxLab Apr 13 '15 at 13:52
  • @Thariama : I have tried above solution but it's didn't worked for re-initialize tinymce object. But i have fixed myself to adding tinyMce.Editors = []. – TheFoxLab Apr 14 '15 at 09:21
  • @Rajnish: are you using tinymce3 or tinymce4? – Thariama Apr 14 '15 at 10:11
  • @Theriama: I've used tinymce4 – TheFoxLab Apr 18 '15 at 06:06
  • can you show your code or maybe create a tinymce fiddle for your issue? – Thariama Apr 20 '15 at 09:13
  • The TinyMCE 4.x solution worked for me as-is. I'm using version 4.2. – jdhildeb Sep 17 '15 at 20:54
  • 1
    @Rajnish see my answer - I was able to get firefox to work by forcing tinyMCE to save before I removed it. – John Naegle Dec 09 '15 at 22:39
  • its not work a lastest version, my opinion add div after textarea, example
    to call re-add $('div#edit').html('') ... basic is work and not try remove!
    – KingRider Mar 10 '16 at 14:06
  • As a quick reference for any WP devs here, the main editor id is "content" so it would be `tinymce.EditorManager.execCommand('mceRemoveEditor',true, 'content');` and `tinymce.EditorManager.execCommand('mceAddEditor',true, 'content');`. This will reset the main TinyMCE on post / page edit. – RestlessWeb Jun 02 '16 at 20:59
  • tinymce takes the id of the tinymce source dom element and uses that one as the editor id. if the dom elment had no id then 'content' is used – Thariama Jun 03 '16 at 07:33
  • Do you happen to know where in the tynmce editor lifecycle this fits? It does not cause the oninit event to fire for tinymce editor , making me think that the editor is never destroyed or re initialized. However all the events that I have bound in the on init previously to using removeEditor, no longer fire. – Pasha Skender Jun 25 '16 at 23:11
  • 1
    For those running into the NS_ERROR_UNEXPECTED issue with Firefox as mentioned by @Rajnish: upgrading to the latest (4.4.3 at this time) version fixes it. – Michielvv Nov 07 '16 at 12:52
  • This worked perfectly for my situation. I am loading a tinymce control in a modal dynamically and if the user closed and opened again the control would try to rebind and would break. By removing the editor on close I can rebind on open and everything works. Thanks – BrianLegg Nov 17 '16 at 16:23
40

Late to the party but it might save someone the headache. Here's what worked for me on version 4.2.4 (2015-08-17):

tinymce.EditorManager.editors = []; 

Then I could re-init an editor on the same dynamically created div

tinymce.init({selector:"#text"});   

Edit : 2020-06-20

With version: 5.2.x, do

 tinymce.activeEditor.destroy();
 

or

 tinymce.remove('#myeditor');
Eric
  • 9,870
  • 14
  • 66
  • 102
  • 3
    This is the best solution that also works when using multiple editors – eztam Dec 15 '15 at 22:11
  • 1
    @Eric Thanks a lot :D .. I spent the whole day with my tinyMCE inside ASP.Net update panel on Firefox and thought there is no hope. Thanks – hsobhy Apr 06 '16 at 03:45
  • 1
    Definitely the best solution. I'd previously used `tinymce.execCommand('mceRemoveEditor');` but it wasn't re-initializing. – lintuxvi Sep 23 '16 at 01:37
  • 1
    Tried this and all other solutions found here. I try to reset the menu/button bars but my custom menus/buttons remains, whatever I do! – Jonny Sep 30 '16 at 21:53
  • 1
    One more to the party - this is what saved me after no other answers in no other threads would. – ESR Dec 06 '16 at 12:33
  • 1
    Thank you, this worked for me as well for version 4.2! – N. Djokic Aug 08 '21 at 15:02
16

This works for me:

if (typeof(tinyMCE) != "undefined") {
  if (tinyMCE.activeEditor == null || tinyMCE.activeEditor.isHidden() != false) {
    tinyMCE.editors=[]; // remove any existing references
  }
}
dageddy
  • 161
  • 1
  • 2
16

It is now possible to just do

tinymce.remove("#id .class or tag");
jberculo
  • 1,084
  • 9
  • 27
9

In case you have more editors with different settings, this is the way to reastart them preserving settings.

tinymce.EditorManager.editors.forEach(function(editor) {
    // code injection
    var old_global_settings = tinymce.settings;
    tinymce.settings = editor.settings;
    tinymce.EditorManager.execCommand('mceRemoveEditor', false, editor.id);
    tinymce.EditorManager.execCommand('mceAddEditor', false, editor.id);
    tinymce.settings = old_global_settings;
});
rioted
  • 1,076
  • 13
  • 24
  • This worked great for me, gave me a way to make the editor read only on the fly. There are plenty of other suggestions out there that say to set the property on the iframe, but this works MUCH better. – Blair Connolly Feb 18 '16 at 03:51
  • You're saving the old settings, destroying the old editor, making a new one and then assigning the old settings to this editor, but you do this for each editor instance on the page. It's easy as that! – rioted Feb 06 '17 at 15:50
  • 1
    Gotta deep clone `tinymce.EditorManager.editors` for the for loop as `execCommand` manipulates `tinymce.EditorManager.editors` while the sync loop is going on. – Hao Chang Aug 21 '18 at 01:37
5

Ok. just a word of caution.

If you have, say.. total of 5 textareas where you want to add/ remove tinymce instances.

AND

you want to do this more than once on a given page, Then its better to look for an alternative solution for your requirement.

Why?.. because even though everything would work fine, all the detaching and re-attaching of tinymce is going to take much time to execute. The browser will offer to stop the script for you etc.

source : my own experience where i tried keeping different textareas in separate hidden divs, and show it to the user when required.

Rakesh
  • 1,336
  • 2
  • 11
  • 13
5

Try this:

 tinymce.remove();

    setTimeout(function () {
    tinymce.init(
        {
        selector: 'textarea',
        menubar: false,
        height: "300",
        plugins: [
            'advlist autolink lists link image charmap print preview anchor textcolor ksfm',
            'searchreplace visualblocks code fullscreen',
            'insertdatetime media table contextmenu paste code help'
        ],
        toolbar: 'undo redo | fontselect fontsizeselect styleselect | alignleft aligncenter alignright alignjustify | bold italic underline strikethrough | link table | ksfm'
        }
        );

    }, 1);
Kamil Smrčka
  • 81
  • 1
  • 4
2
// Remove all editors bound to divs
tinymce.remove('div');

// Remove all editors bound to textareas
tinymce.remove('textarea');

// Remove all editors
tinymce.remove();

// Remove specific instance by id
tinymce.remove('#id');

from the tinymce documentation

mehmet
  • 7,720
  • 5
  • 42
  • 48
2

Try this:

    var default_value_1 = 'test';
    var default_value_2 = 'test';

    tinyMCE.remove();

    tinyMCE.init({
        selector: '#id_element_1',
        plugins: 'print preview searchreplace autolink directionality visualblocks visualchars fullscreen image link media template codesample table charmap hr pagebreak nonbreaking anchor toc insertdatetime advlist lists textcolor wordcount imagetools contextmenu colorpicker textpattern help code',
        toolbar: "code formatselect | bold italic strikethrough forecolor backcolor | link | alignleft aligncenter alignright alignjustify  | numlist bullist outdent indent  | removeformat"
    }).then(function(editors){
        editors[0].setContent(default_value_1 || '');
    });

    tinyMCE.init({
        selector: '#id_element_2',
        plugins: 'print preview searchreplace autolink directionality visualblocks visualchars fullscreen image link media template codesample table charmap hr pagebreak nonbreaking anchor toc insertdatetime advlist lists textcolor wordcount imagetools contextmenu colorpicker textpattern help code',
        toolbar: "code formatselect | bold italic strikethrough forecolor backcolor | link | alignleft aligncenter alignright alignjustify  | numlist bullist outdent indent  | removeformat"
    }).then(function(editors){
        editors[0].setContent(default_value_2 || '');
    });
nthaih
  • 71
  • 3
1

Just update it !

if you are looking at this to reset the content of the editor, instead of destroying it and initializing it again you can simply change the content like this

var editor = tinymce.get('editor_id'); //the id of your textarea
editor.setContent(content);  //any html as string
Community
  • 1
  • 1
azerafati
  • 18,215
  • 7
  • 67
  • 72
1

To remove existing tinymce editor and add new needs clearance of tinymce.EditorManager.editors array. This solution works in both cases : 1. If you have only one editor and you want to remove and add it again. 2. If you have multiple editors and you want to remove some special editor and add it again.

console.log(tinymce.EditorManager.editors);

This will give you a view of the array and exact index of you desired editor which you want to remove. For example one sample output of above console can be:

Array[2]
0:B
1:B
length:2
textarea-1:B
textarea-2:B
_proto_Array[0]

This is the output of the console when i have two tinymce editors on textareas : #textarea-1 and #textarea-2 Lets suppose I want to delete #textarea-2 and re-add it then it can be done as follows:

tinymce.EditorManager.editors.splice(1, 1);//removing second element in array.
delete tinymce.EditorManager.editors['textarea-2'];//deleting respective textarea id from array

Then you can add it again simply using init:

tinymce.init({
    selector:'#ts-textarea-2'
});

If you have only one textarea associated with tinymce editor lets say : #textarea-1 and you want to remove and re-initialize it then you can just empty tinymce.EditorManager.editors by :

tinymce.EditorManager.editors = [];

And then you can add using init command as explained above. Worked for me without any error.

I hope it helps

Abhay Maurya
  • 11,819
  • 8
  • 46
  • 64
0

All the above solutions didn't work for me ... This worked fine in my popup close event

var editor = tinyMCE.get('txtMailingText');
if (editor!=null) {
    editor.destroy();
}
0

For what its worth, I ended up doing this:

  1. Try to remove the editor right before I add it to the page (this worked for chrome)
  2. Before I remove the editor, trigger a save. This was important for firefox for some reason.

Here is what it looked like to add the editor:

  $(function() {
    tinymce.EditorManager.execCommand('mceRemoveEditor',true, 'fred');
    #{tinymce_javascript(:simple_editor, {height: 150, :selector => 'fred'})}
  });

  $(document).on('click', '.tinyMCE-save', function(event) {
    tinyMCE.triggerSave();
    return true;
  });

I had an explict click that removed the editor:

<a href="#" class="tinyMCE-save cool-js-click-handler">Cancel</a>
John Naegle
  • 8,077
  • 3
  • 38
  • 47
0

In the beginning I used:

tinymce.execCommand('mceRemoveEditor', true, id);
tinymce.execCommand('mceAddEditor', true, id);

But those commands run asynchronous, so the add command would often fail. As a workaround, I would:

tinymce.execCommand('mceRemoveEditor', true, id);
setTimeout(function() {
    tinymce.execCommand('mceAddEditor', true, id);
}, 500);

But I hated this solution, because it appeared slower to the user and even so you couldn't be sure that 500 milliseconds was enough if the computer was slow.

Now I'm using:

tinymce.remove(id);
tinymce.init({
    selector: id
});

I'm not sure why this works, but it works and this code doesn't have any of the asynchronous issues that the old code I used had.

Try it here: https://jsfiddle.net/g0u059au/

Bjørn Stenfeldt
  • 1,432
  • 1
  • 18
  • 25