VocabReminder
English dictionary with notifications so you won't forget what you're studying!
Click here for more info about the app
VocabQuiz
The app that quizzes and scores you on your vocabulary!
Click here for more info about the app

Rails Prototype JS and TinyMCE Autosave

       

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">

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);
/script

<%= 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 w/ #autosave #helpers #periodical #prototype #railsprogramming #ruby on rails