Written by Sean Behan on Sun Jun 17th 2012

TinyMCE is a nice little WYSIWYG for text processing online. It uses iFrames and Javascript callbacks to manipulate textarea form fields. Using it with Rails can be somewhat problematic if you want to set up an observer on a field that TinyMCE is managing. The reason is that TinyMCE uses an iFrame and a callback to update the textarea before the form is submitted.

More detailed information on the TinyMCE specifics can be found at this site <a href="http://www.crossedconnections.org/w/?p=88"&gt;

In Rails, there is a nifty helper function called "observe_field" that will generate Javascript which listens for changes on form fields. However, because TinyMCE only updates the field after the form is submitted the contents of the textarea are not updated when you type in it. Therefore, your observe_field function is listening but doesn't see anything new. The iFrame is a kind of buffer that will write to the textarea later.

A simple solution to this problem is to call the function that writes to the textarea. This will update the textarea and the observer_field function will notice the changes. You can use prototype "PeriodicalExecuter" to trigger a function that will contain the TinyMCE callback function. Below is the code.

script type="text/javascript" charset="utf-8"
  function triggerTinyMCE(){
    tinyMCE.triggerSave(true, true);
  new PeriodicalExecuter(triggerTinyMCE, 30);

<%= observe_field( :post_body, :frequency => 1, :update => :update_status, :url => { :action => :update_body } ) %>

However, the only problem with this approach is that you're kind of running two functions that do the same thing. Instead it would make more sense to get rid of the observe_field function altogether and have the PeriodicalExecuter trigger a function that makes the ajax request at the same time. This would look something like
script type="text/javascript" charset="utf-8"
  function triggerTinyMCE(){
    tinyMCE.triggerSave(true, true);
    var content = escape($F('post_body'));
    var url = "/posts/update_body";
    var params = "post_body="+content;
var aRequest = new Ajax.Request(url,
  method: 'post',
  parameters: params,
  onSuccess: function(data){
    $("update_status").innerHTML = data.responseText;

}); } new PeriodicalExecuter(triggerTinyMCE, 10); /script

Tagged with..
#autosave #helpers #periodical #prototype #Rails #Programming #Ruby on Rails

Just finishing up brewing up some fresh ground comments...