1

Topic: [HOWTO] Fix AJAX/DOM problems (moving, or re-creating textareas)

Hello all,

I ran into problems trying to use TinyMCE in an AJAX-ified page where the <textarea/> I was attaching TinyMCE to was being swapped in and out via DOM manipulation/AJAX.  Namely, the _second_ time my <textarea/> was loaded and I added a TinyMCE editor to it, clicking in or typing into the TinyMCE editor started throwing "this.getDoc() is null" Javascript exceptions and the changes I made in the editor were not being saved (they weren't copying back to the <textarea/>).

I spent all day in the Javascript debugger trying to figure this out (I didn't know much about Javascript before this morning) and promised myself I'd post the solution if I found it.

Basically, the problem is that when you swap out the <textarea/> element in the DOM, the TinyMCE iFrame is not removed.  The old editor instances (mce_editor_0 ... mce_editor_[n - 1]) stay in tinyMCE.instances[] and end up receiving all of the onFocus() and typing events.  This causes errors because these old instances are pointing to your old (and now-deleted) <textarea/> elements.

To solve this, you have to make sure that you remove the TinyMCE editor instances before you remove the backing <textarea/> instances.  When you next load a <textarea/> you want to attach TinyMCE to, you have to add it explicitly again.  If your <textarea/> has an id of "txaEditableContent", you should use the following algorithm/pseudocode:

1. Load the page.  Include the following code to init TinyMCE:

tinyMCE.init({
    mode : "none",
    theme : "simple"
});

2. Load a panel/div containing a <textarea/> with an id of "txaEditableContent".
3. Add a TinyMCE editor to that <textarea/>:

tinyMCE.execCommand('mceAddControl', false, 'txaEditableContent');

4. User makes and saves their changes in the editor.
5. Unload/swap out the panel/div containing the <textarea/>.  Before you remove the <textarea/> make sure you remove the TinyMCE editor:

tinyMCE.execCommand('mceRemoveControl', false, 'txaEditableContent');

6. User does something that causes you to load a new panel/div containing a <textarea/> whose id is also "txaEditableContent".
7. Add a TinyMCE editor to that <textarea/>:

tinyMCE.execCommand('mceAddControl', false, 'txaEditableContent');

8. Rinse.
9. Repeat as desired.

I hope this helps save someone else from the headache I had today.  Happy hacking!

-- Karl M. Davis

2

Re: [HOWTO] Fix AJAX/DOM problems (moving, or re-creating textareas)

Hi!

Thanks for the tips!

I am still experiencing a bug however, wich you might not have detected yet.

When you post a message into an iframe and then move or reset the editor, the whole page will become disabled!

You can test it here: http://testforum.obeyon.com/

I also posted a bug on http://sourceforge.net/tracker/index.ph … tid=635682

Best Regards,
Adult SEO

3

Re: [HOWTO] Fix AJAX/DOM problems (moving, or re-creating textareas)

Hi!

Thanks for the great tips!

I had encountered, a bug( or feature smile). If you're trying to perform step 5. (removing tinymce editor), but the user haven't focused any tinyMCE editor in your ajax application et, you will get an exception.

I had found a solution:
step 5.

tinyMCE.execCommand('mceFocus', false, 'txaEditableContent');                    
tinyMCE.execCommand('mceRemoveControl', false, 'txaEditableContent');

Note: focusing tinyMCE editor, after adding it, didn't help.

Last edited by dennis.fyodorov (2006-09-27 07:19:19)

4

Re: [HOWTO] Fix AJAX/DOM problems (moving, or re-creating textareas)

+++ BUMP for this topic. Thanks Karl!

5

Re: [HOWTO] Fix AJAX/DOM problems (moving, or re-creating textareas)

Hello everybody at this post!

Thanks a lot for your userful help!Worked fine for me!

Ved

6

Re: [HOWTO] Fix AJAX/DOM problems (moving, or re-creating textareas)

This post really helped me a lot except on one thing.

When I have two textareas that need to be activated and deactivated on demand.

When I load try to load the 2 I only get about one and a half. I mean that the first is ok but the second is greyd out. Also when using the toolbar on the second box, the actions happen on the first box.

any clues?

7

Re: [HOWTO] Fix AJAX/DOM problems (moving, or re-creating textareas)

this is exactly what i was looking for, i have the same problem and i will try your method and let you know.

8

Re: [HOWTO] Fix AJAX/DOM problems (moving, or re-creating textareas)

Hi
thanks for tip, it saved many hours and brain energy. But have an adding - after following instructions on unloading TinyMCE exeptions were gone, but somehow when I submit form, textarea contents were not sent with it. So nothing could be changed with MCE. And for it I had to make MCE unload onSubmit the form.

9

Re: [HOWTO] Fix AJAX/DOM problems (moving, or re-creating textareas)

maybe you could paste th entire code, I am pretty newbie in cakephp, I am trying to go back to php from rubyon rails but for now I am pretty negative to do that.

10

Re: [HOWTO] Fix AJAX/DOM problems (moving, or re-creating textareas)

Keeping track of which editors are active on a page is a pain in the ass, especially when there could be multiple methods of leaving a page. I wish there were a way for ask tinyMCE which editors are active so you could just loop and deactivate them.

11

Re: [HOWTO] Fix AJAX/DOM problems (moving, or re-creating textareas)

What do you mean by active. There is a collection with instances.

for (n in tinyMCE.instances) {
    inst = tinyMCE.instances[n];

    // Could be messed up due to prototype like libraries
    if (!tinyMCE.isInstance(inst))
        continue;

    // Do stuff
    inst.getHTML();
}
Best regards,
Spocke - Main developer of TinyMCE

12

Re: [HOWTO] Fix AJAX/DOM problems (moving, or re-creating textareas)

Here's how to solve the problem with creating textareas (or DIVs containing them) and getting rid of them;

in your page:

<textarea id="XX" name="IntroText" ></textarea>
<script language=javascript>
activateEditor('XX')
</script>           

at any place that causes this textarea to disappear, simply call: deactivateEditors()

the script:

var activeEditors = new Array()

function activateEditor(id) {
    activeEditors[activeEditors.length] = id
    toggleEditor(id)
}

function deactivateEditors() {
    for(x=0;x<activeEditors.length;x++) {
        toggleEditor(activeEditors[x])
    }
    activeEditors.length = 0
}

// functions
function toggleEditor(id) {
    var elm = document.getElementById(id);

    if (tinyMCE.getInstanceById(id) == null)
        tinyMCE.execCommand('mceAddControl', false, id);
    else
        tinyMCE.execCommand('mceRemoveControl', false, id);
}

13

Re: [HOWTO] Fix AJAX/DOM problems (moving, or re-creating textareas)

I'm using TinyMCE to WYSIWYG some text areas in an Ajax controlled bit of a web page. In this implementation, the entire form gets removed and possibly added to the DOM. In my Ajax code, once I determine that the area is about to be removed, I use mceRemoveControl to get rid of the control, then I replace the area, then if there's a textarea that needs control (cheat and seek ID), I use mceAddControl to put the control back on. The code's pretty straight forward, but essentially the only parts relating to tinyMCE are thus ("text" is the Ajax retreived HTML, and "which" is the DIV id that is to be retreived and replaced):

    if(document.getElementById("textarea")!=null){
        tinyMCE.execCommand('mceRemoveControl', false, 'textarea');
    }

    var elementText = parseForElement(text, which);
    if(elementText != ""){
        document.getElementById(which).innerHTML=elementText;
    }

    if(document.getElementById("textarea")!=null){
        tinyMCE.execCommand('mceAddControl',false,'textarea');
    }

I've got the swapping in and out of MCE working just dandy, but I find that the buttons that pop-up windows (plugin emoticons, insert image, preview...) don't work on the controls that are added by Ajax. The rest of the control works fine; that is, strictly anything that doesn't open another window will work, including styles and formatting and cut and paste and so on.

I know you're going to ask... Yes, the plug-ins and pop-ups do work. If you load a page that starts with the editor in it, not loaded by Ajax, then the buttons work as expected. If Ajax replaces the form (even to the same one) using the bits above, the buttons cease working.

I've noticed on this editor (using the Toggle link) that the insert image button works after turning the control off and back on. I must be missing something, or something.

As a token...regarding the saving of the contents of the MCE when swapping out, I found that adding a call to tinyMCE.triggerSave() does the trick of moving the bits from the control to the textarea.

       <input type="submit" name="submit" value="Save" onclick="tinyMCE.triggerSave();" />

This can be added (as shown) to the onClick event of a control (e.g., one you use to trigger a swap), in script that does other work, or in the onSubmit of the form.

14

Re: [HOWTO] Fix AJAX/DOM problems (moving, or re-creating textareas)

OK, so what I had to do was post a question on this site, and then the answer just happened upon me.

Someone injected a function named "open()" in our JavaScript, and that hijacked the method used to open the pop-up windows.

Stop wracking your brains...I've done enough for all of us.

Thanks for the consideration.

15

Re: [HOWTO] Fix AJAX/DOM problems (moving, or re-creating textareas)

I add function to run the script use xmlhttp for AJAX modify the script a little
HTML PAGE.
<ul class="shadetabs">
<li><a href="#default" onclick="makerequest('entrada.php','ajaxcontentarea'); return false;">Entrada</a></li>
<li><a href="paginador.php" onclick="makerequest('salida.php','ajaxcontentarea'); return false;">Enviados</a></li>
//select page with new textarea
<li><a href="redactar.htm" onclick="makerequest('redactar.php','ajaxcontentarea'); return false;">Redactar</a></li>
      </ul>
<div id="ajaxcontentarea" class="contentstyle">
</div>
I have other  page redactar.php with  other textarea> a id is 'content'


// see makerequest function
function makerequest(serverPage, objID) {
//if exist another textarea id 'content'
var elm = tinyMCE.getInstanceById('content');
if (elm)
//Destroy this instants
    tinyMCE.execCommand('mceRemoveControl', false, 'content');
setStatus ("Cargando...",objID);
var obj = document.getElementById(objID);
xmlhttp.open("GET", serverPage);
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
obj.innerHTML = xmlhttp.responseText;
//if the page load is redactar load content(I have trouble with 'content' not exist
if(serverPage == 'redactar.php')
    loadEditor('content');
}
// Load Editor always onclick event
function loadEditor(id) {
    if (tinyMCE.getInstanceById(id) == null)
        tinyMCE.execCommand('mceAddControl', false, id);
}

Here's how to solve the problem with creating textareas (or DIVs containing them) and getting rid of them;

in your page:

<textarea id="XX" name="IntroText" ></textarea>
<script language=javascript>
activateEditor('XX')
</script>           

at any place that causes this textarea to disappear, simply call: deactivateEditors()

the script:

var activeEditors = new Array()

function activateEditor(id) {
    activeEditors[activeEditors.length] = id
    toggleEditor(id)
}

function deactivateEditors() {
    for(x=0;x<activeEditors.length;x++) {
        toggleEditor(activeEditors[x])
    }
    activeEditors.length = 0
}

// functions
function toggleEditor(id) {
    var elm = document.getElementById(id);

    if (tinyMCE.getInstanceById(id) == null)
        tinyMCE.execCommand('mceAddControl', false, id);
    else
        tinyMCE.execCommand('mceRemoveControl', false, id);
}

Last edited by hemm (2007-05-25 19:43:39)

16

Re: [HOWTO] Fix AJAX/DOM problems (moving, or re-creating textareas)

Thanks for the tip, I still had a problem because I was using multiple inits on my page and I lost the configurations  in the AJAX response. I figured out a solution though to modify the activateEditor function below:

function activateEditor(id, c) {
    activeEditors[activeEditors.length] = id;
    tinyMCE.settings=tinyMCE.configs[c];
    toggleEditor(id);
}

The variable c tells the function which settings to use from the tinyMCE.configs array. If you used multiple inits then the 1st init creates configs[0], the second configs[1] etc.

Hope it helps someone.

Diodeus wrote:

Here's how to solve the problem with creating textareas (or DIVs containing them) and getting rid of them;

in your page:

<textarea id="XX" name="IntroText" ></textarea>
<script language=javascript>
activateEditor('XX')
</script>           

at any place that causes this textarea to disappear, simply call: deactivateEditors()

the script:

var activeEditors = new Array()

function activateEditor(id) {
    activeEditors[activeEditors.length] = id
    toggleEditor(id)
}

function deactivateEditors() {
    for(x=0;x<activeEditors.length;x++) {
        toggleEditor(activeEditors[x])
    }
    activeEditors.length = 0
}

// functions
function toggleEditor(id) {
    var elm = document.getElementById(id);

    if (tinyMCE.getInstanceById(id) == null)
        tinyMCE.execCommand('mceAddControl', false, id);
    else
        tinyMCE.execCommand('mceRemoveControl', false, id);
}

17

Re: [HOWTO] Fix AJAX/DOM problems (moving, or re-creating textareas)

Does it work under IE 7?

It's working perfectly in FF, but when I try under IE 7 the whole form become disabled...

Any idea how can I fix it?

At page unload I'm calling the function:

function unloadPage() {
    if (tinyMCE._getElementById("content") != null) {
        tinyMCE.execCommand("mceRemoveControl", false, "content");
    }
}

Thanks

18

Re: [HOWTO] Fix AJAX/DOM problems (moving, or re-creating textareas)

Some further notes:

the "init()" code used at the top of the page can be different than show. You can change the mode, etc. To load TinyMCE on demand when you click a textarea, you can use this:

<textarea id="whatever" onclick="tinyMCE.execCommand('mceAddControl', false, this.id);"></textarea>

You have to give the textarea an ID, but it doesn't matter what. Using "this.id" in the onClick call always find the right one!

   Mark

19

Re: [HOWTO] Fix AJAX/DOM problems (moving, or re-creating textareas)

Hi all!

I Use this code

    function ToggleTinyMCEEditors()
    {
        try
        {
             for (n in tinyMCE.instances) 
             {
                 tinyMCE.removeInstance(tinyMCE.instances[n]);
             }
             
             var nodeList = document.getElementsByTagName("textarea");
             var selector = tinyMCE.getParam("editor_selector");
               var elementRefAr = new Array();
             for (var i=0; i<nodeList.length; i++) 
             {
                var elm = nodeList.item(i);
        
                if (selector != '' && !new RegExp('\\b' + selector + '\\b').test(tinyMCE.getAttrib(elm, "class")))
                    continue;
        
                elementRefAr[elementRefAr.length] = elm;
                tinyMCE.addMCEControl(elm, elm.name);
             } 
        }
        catch(err)
        {
        }
    }

Last edited by minderm (2007-06-18 19:11:30)

20

Re: [HOWTO] Fix AJAX/DOM problems (moving, or re-creating textareas)

Hello allz

here 's a sample of code to put back tinyMCE 's iframe content to the original textarea :
(like you have to do before submittin the page .... )

function putBackContent(){
   document.getElementById('MY_TEXTAREAS_ID').innerHTML = tinyMCE.getContent();
}


But if you use it in an AjaX geeky Stance, here 's the basic of using tinyMce dynamically :


function updateThings(things_id){

   tinyMCE.execCommand('mceAddControl',false,'MY_TEXTAREAS_ID');

   var el = document.getElementById(things_id);
   tinyMCE.setContent(el.innerHTML);
   el.style.display = "none";
}


and then to save the edited things dynamically :


function saveUpdatedThings(things_id){

  var el = document.getElementById(things_id);

  //// Call an ajax save request here, don't forget to escape() the content of tinyMce before sending to server !!!
  /// AND THEN IF SERVER SIDE SAVIN GOES RIGHT :

   if(req.readyState == 4 && req.status == 200){
      alert('data saved !!! ');
      el.innerHTML = tinyMCE.getContent();
      tinyMCE.execCommand('mceRemoveControl',false,'MY_TEXTAREAS_ID');
      el.style.display = ''; /// REVERT TO REGULAR DISPLAY
      return true;
   }else{
      alert('Failed savin data ..... ');
      tinyMCE.execCommand('mceRemoveControl',false,'MY_TEXTAREAS_ID');
      el.style.display = ''; /// BACK TO THE OLD VERSION     
      return false;
   }
}


Hope this 'll help all my Geeks fellows to save time for non-Chipseted things ......

21

Re: [HOWTO] Fix AJAX/DOM problems (moving, or re-creating textareas)

Hi,

I have two init mathods on same page for two different themes. how can i add control to any one instance of tineMCE using mceAddControl. In other words, if i have following script tag:

tinyMCE.init({
    mode:"textareas",
    theme:"advanced",   
    editor_selector:"mceAdvanced"
})
tinyMCE.init({
    mode:"textareas",
    theme:"simple",   
    editor_selector:"mceSimple"
})

How can I add control to the advanced instance of tinyMCE?

22

Re: [HOWTO] Fix AJAX/DOM problems (moving, or re-creating textareas)

Hi;

I wanna switch on tinymce but I gotta first solve this AJAX update panel problem... I've tried several ways of doing that as I could find in this forum but none worked...

I have the textarea inside a panel in an updatepanel; when I make this panel visible tinymce gets lost..

So I have to reload it programmatically, but I can't...

Any help would be great..

Thanks
Kaan ÖZGEN

23

Re: [HOWTO] Fix AJAX/DOM problems (moving, or re-creating textareas)

gunjan wrote:

Hi,

I have two init mathods on same page for two different themes. how can i add control to any one instance of tineMCE using mceAddControl. In other words, if i have following script tag:

tinyMCE.init({
    mode:"textareas",
    theme:"advanced",   
    editor_selector:"mceAdvanced"
})
tinyMCE.init({
    mode:"textareas",
    theme:"simple",   
    editor_selector:"mceSimple"
})

How can I add control to the advanced instance of tinyMCE?

I think what is slipping you up is the use of mode: "textareas", because that trys to apply your tinyMCE instance to ALL text areas.  Instead try applying the tinyMCE instance to just the id of the text areas you are interested in.  I think the example on the page in the following link will do the trick:
http://wiki.moxiecode.com/index.php/Tin … ation/mode

24

Re: [HOWTO] Fix AJAX/DOM problems (moving, or re-creating textareas)

Even if i use the "exact" theme and give proper id..the problem of finding the correct instance always persists. I have to add the control back to the tinyMCE instance after ajax postback is completed. For which i need to know which instnace od tinyMCE is having the control.

Or is there anyway i can change the settings like mode, theme etc in javascript?

25

Re: [HOWTO] Fix AJAX/DOM problems (moving, or re-creating textareas)

There is an important point to use tinyMCE in a fullAjax context, point that take me 2 days to figure out !

the thing is YOU HAVE TO UNLOAD TINYMCE PROPERLY cause it won't work if you just unload it by setting it's node container 's innnerHTML to void,
you'll have to unload it by using the DOM way :

var container = document.getElementById('TINYMCE_CONTAINER');
var tinyNode = document.getElementById('TINYMCEPANE');
container.removeChild(tinyNode);


My guess is that the (container.innerHTML = ""; )  won't throw the apropriate DOM event,
but the  (container.removeChild(tinyNode); ) will do it, and so tinyMCE could catch it and know that it have been unloaded .

the tricky part if your using the wrong method is that it'll bug on the next loading of tinyMCE and not right on the unload !

in this case you'll have FF give you an error like (this.getDoc() has no properties) and a strange error on MSIE6/7 like (error on line -126589)

hope this would help


--
T1B0

Last edited by T1B0 (2007-06-28 16:30:54)