Using TinyMCE with an AJAX form submit
I never thought getting TinyMCE to work with an AJAX post would be difficult, but a day of poking and prodding (with eventual success), brought me back to reality and reminded me how useful a browser Developer Toolbar can be.
The more I work with AJAX technologies, the more I like working away from the typical get/post page life-cycle. Developers can have dozens of pages for different functions, yet still place all the server-side validation and database connectivity code in one ajax end-point. It may not work in every environment, but in a managed corporate environment it works just fine.
TinyMCE is probably the premiere (free) browser based publishing tool, but if you have ever explored the DOM tree of a page that uses TinyMCE, you will see that all of the coolness is actually embedded in an IFRAME, which adds some complexity when applying validation to the contents, or in the case of an AJAX call, getting the content.
The trick to the process is realizing that TinyMCE uses the page unload event as a trigger to move all the content back into the TextArea that the instance of TinyMCE is tied to. The function that the unload event calls is the “triggerSave” function that you can see on line 467 of the “tiny_mce_src.js” file. This function performs some tiny magic and then moves the contents from the IFRAME into the TextArea.
So the javascript function that does the AJAX call needs to first call the triggerSave function. Couple this knowledge with our handy-dandy protoype.js library ajax calls, and it all comes together quite nicely.
function postForm(){
tinyMCE.triggerSave(true,true);
var mceContent = escape($F('myTextArea'));
var otherContent = $F('someField');
var url = 'http://yoursever/app/post_content';
var pars = 'body=' + mceContent + '&other=' + otherContent;
var myAjax = new Ajax.Request(
url,
{
method: 'post',
parameters: pars,
onComplete: showResponse
}
);
}
Remember to POST when you have alot of content since a GET places all of the parameters into the URL of the request and you can run into some serious limitations with respect to maximum URL lengths.
April 18th, 2006 at 11:11 am
Howdy, cheers for the tip, I think it will come in very handy when I get to that stage. But a quick question I have too and maybe you have come across this. When generating a form from an ajax request, the textarea that is targeted doe snot load, in fact the whole browser loads up this mad window of whiteness… anyhow, will let you know it I figure it out. Thanks for sharing.
April 18th, 2006 at 8:41 pm
Having never attempted to load a TinyMCE form from an AJAX call, all I can offer is opinions. If you load the body into the textarea with the ajax call, I would think you would need to call the init() function at the end of the ajax function. Something like:
tinyMCE.init({mode : “textareas”,theme : “simple”});
What have you attemped so far?
April 19th, 2006 at 11:47 am
Well, one last thought for the day, I remember there was a function of TinyMCE called “updateContent” that would copy the value of a given document element into the TinyMCE instance that is tied to it. It seems this function may be made for exactly what you are attempting. So populate the textarea with the ajax call, then update:
TinyMCE.updateContent(’textarea_id’)
May 1st, 2006 at 8:16 am
Dude thanks for sharing this research. A small note, however. The object you refer to in your code-snippet should be tinyMCE.triggerSave(true,true); (not the extra ‘y’ - probably a typo).
May 1st, 2006 at 7:21 pm
DOOH!!!
thanx 4 the tip!
May 10th, 2006 at 12:46 am
This tip was invaluable for getting my AJAXed comments form working. Thanks for that. For those readers who are using AJAX to generate the textarea as well, it might help to add this script:
tinyMCE.execCommand(’mceAddControl’, true, ‘textarea_name’)
To the partial form that you’ll be loading. This has the effect of initializing TinyMCE on the textarea specified, since it didn’t exist when the page initially loaded.
May 10th, 2006 at 12:49 am
oops, I got sanitized on that one, just in case it wasn’t clear, it should look like this:
< script type=”text/javascript” >
tinyMCE.execCommand(’mceAddControl’, true, ‘comment[content]’)
< /script >
hopefully that displays properly.
May 14th, 2006 at 10:12 am
thanks kito, your comment really helped me.
).
i was building a small ajax thingy (something of mine, a small cms, if you could call it that
so i put this on top of my main page:
tinyMCE.init({
mode : “textareas”,
auto_reset_designmode : true
});
and this one into my request onload function that is executed when my ajax request function loads the page (an event basically)
requestOnLoad = function(){
tinyMCE.execCommand(’mceAddControl’, true, ‘articleEditor’);
}
thaks again
June 5th, 2006 at 10:45 am
Hi,
Thanks for all the tips. I got tinyMCE working in an ajax context (in Ruby on Rails), but only in MS IE. In Firefox, tinyMCE does not save upon the SECOND submit.
It says somewhere: “If you load a TinyMCE form from an AJAX call, Firefox saves the content only once, even if you use auto_reset_designmode : true.” So included this in my initialization:
I have got this code to init tinyMCE:
tinyMCE.init({
mode:”textareas”, editor_selector : “tiny_mce”,
language : “nl”,
theme: “simple”,
auto_reset_designmode : true
});
The textarea code is in rhtml (Ruby on Rails):
“height:50px;width:350px;” %>
And this is my submit button:
Whenever I submit the tinyMCE content for the SECOND time (i.e. 2nd save), Firefox tells me:
this.getDoc() has not properties
../javascript/tiny_mce/tiny_mce.js
In MS IE, no problems whatsoever.
Cheers,
Onno
June 5th, 2006 at 11:04 am
My code got mangled. Let’s try that again:
My text area code (in Ruby on Rails):
<%= text_area ‘exercise’, ‘question’ , :style => “height:50px;width:350px;” %>
My submit button:
<input class=”submit” onclick=”tinyMCE.triggerSave(true,true);” type=”submit” value=”Bewaren”/>
And the code to actually add a tinyMCE instance to the page:
tinyMCE.execCommand(’mceAddControl’, true, ‘exercise_question’);
Cheers,
Onno
June 5th, 2006 at 11:22 am
I have found the solution to the ajax troubles with TinyMCE in Firefox:
http://tinymce.moxiecode.com/punbb/viewtopic.php?pid=10867#p10867
Which says basically: before adding a new mce control, first set the id counter to zero
tinyMCE.idCounter=0;
tinyMCE.execCommand(’mceAddControl’, true, ‘exercise_question’);
Cheers!
Onno
September 18th, 2006 at 11:28 pm
Can some explain where to put that code for a newb? Thanks.
October 14th, 2006 at 12:09 am
R u all crazy? Never use encodeURIComponent(tinyMCE.getContent())? Cheers!
October 23rd, 2006 at 12:52 pm
Another solution I used to solve the problem is upon submit or page change convert the editor back to a textarea like so:
tinyMCE.execCommand(’mceRemoveControl’, false, ‘instanceName’);
Make sure to replace ‘instanceName’ with the name of the instance you want to replace.
This way you just access it like a normal form element
Best of luck!
October 26th, 2006 at 7:04 pm
[…] Ok, the controller is taken care of. At this point according to comments I found here you might be able to use it with IE, but it needs more massaging to work with Firefox. So onto our views to put in place the necessary adjustments. […]
December 19th, 2006 at 12:34 am
tiny mce does not work when change content of div with ajax !!! help ????
December 19th, 2006 at 12:39 am
I used XmlHttpRequest for change content of div.
December 19th, 2006 at 1:57 pm
I’ve use TinyMCE without form or textarea, with little modification
I’ve add in tiny_mce.js in init function (ajax parameter):
this._def(”ajax”, false);
and in save plugin in editor_plugin.js
if(formObj||inst.getParam(’ajax’)) {
…..
[ ]
function ajax_post(tinyInstance) {
sendAjaxRequest(tinyInstance.getBody().innerHTML());
}
tinyMCE.init({
mode:”exact”,
elements: “editor”,
ajax: true,
plugins: “save”,
theme: “advanced”,
save_onsavecallback: “ajax_post”,
theme_advanced_buttons1_add_before: “save,separator”,
…
});
[ ]
With this you can use save plugin for sending ajax request.
December 19th, 2006 at 2:03 pm
Sorry for previous post it eats html tags:
I’ve use TinyMCE without form or textarea, with little modification
I’ve add in tiny_mce.js in init function (ajax parameter):
this._def(”ajax”, false);
and in save plugin in editor_plugin.js
if(formObj||inst.getParam(’ajax’)) {
…..
This is html file
[script]
function ajax_post(tinyInstance) {
sendAjaxRequest(tinyInstance.getBody().innerHTML());
}
tinyMCE.init({
mode:”exact”,
elements: “editor”,
ajax: true,
plugins: “save”,
theme: “advanced”,
save_onsavecallback: “ajax_post”,
theme_advanced_buttons1_add_before: “save,separator”,
…
});
[/script]
…
[body]
[div id=”editor”][/div]
[/body]
With this you can use save plugin for sending ajax request.
December 20th, 2006 at 5:05 am
please more detail ?
January 8th, 2007 at 12:34 am
Thank you so much for your knowledge!
You just saved me a hour’s worth of work!
January 10th, 2007 at 6:06 am
I implemented kuba’s trick to do an ajax save. My only difference was that I called the parameter save_ajax in stead of just ajax. Since this is so easy, maybe this can be implemented in the new builds. Saves us changing the tinyMCE code for every new release. There are just two minor adjustments, but I’m lazy
January 28th, 2007 at 6:54 pm
You may want to have a look at a handy hash function in prototype which takes care of the asking-for-typos ‘body=’ + mceContent + ‘&other=’ + otherContent;’-bit and the serialization / url-encoding issue mentioned earlier in the comments. You can basically put your variables in a hash and call toQueryString on that hash. You do NEED some kind of encoding, as the raw output of tinyMCE can contain HTML-entities which start with an ampersand (&), which would break the string given to pars in the Request.
More info at http://www.prototypejs.org/api/hash/toQueryString
March 3rd, 2007 at 9:59 pm
I’m trying to use ajax to auto-save the tinyMCE document. It’s running a triggerSave and ajax request every few seconds.
When using tinyMCE.triggerSave(true,true); the cursor is always reset to the very top.
Does anyone know a way to keep the cursor in the same place through the call?
March 9th, 2007 at 2:58 pm
Thanks Onno Schuit
that tinyMCE.idCounter=0; was a life saver
April 3rd, 2007 at 11:57 am
Using ruby on rails with ajax request and submit…i can’t edit a link..Do i have to do somthing special to access this functionality ? the other popup windows seem to work normally otherwise…