RailsでTinyMCEを使う

自分で作っているアプリケーションにリッチテキストなエディタを使いたいと思い、TinyMCEを使うことにした。
通常使う分にはTinyMCEをインクルードして初期化するだけでよいみたいだけど、Ajaxで動的にフォームをロードしているような状況だと、いろいろ問題が出て苦労した。
以下、今回対処した手順をメモ。

フォーム生成時にtinyMCE初期化を行う

通常は、HTMLのロード時にTinyMCEが対象のtextareaを見つけてリッチテキスト化するけど、動的にロードする場合は自分で初期化してやらなければいけない。
以下の記述はlink_to_remoteタグでフォームをロードするという前提。

設定のポイント:
  • synchronousにする (synchronousにしないと、次項afterオプションのJavaScript実行時に、tinyMCEが対象のtextareaを見つけられない)
  • afterオプションで以下のJavaScriptを実行
tinyMCE.idCounter=0; // "this.getDoc() has no properties"というエラーがやたらと出る対策のため → *1
tinyMCE.execCommand("mceAddControl",true,"targetid"); // targetidはリッチテキスト化するtextareaのid
    • *1 - エラーの内容と対処はこちらのリンクに示してある 参照

入力したリッチテキストの更新

リッチテキストの実体は、対象のtextareaを隠し、その直下(nextSibling)に挿入されているみたい。
従って、フォームをsubmitする前にエディタに入力されたテキストを本来のtextareaに戻してやらなければならないが、動的ロードした場合だとどうもうまく動かないので、自分で移送してやることにする。

設定のポイント:
  • form_remote_tag の beforeオプションに以下のJavaScriptを実行するように設定
copyMCE2TextArea("targetid"); // targetidは対象フォームのID
function copyMce2TextArea(id) {
  var form = $(id);
  var areas = form.getElementsByTagName('textarea');
  for (var i = 0; i < areas.length; i++) {
    var area = areas[i];
    var frame = area.nextSibling.getElementsByTagName('iframe')[0];
    area.value = frame.contentDocument.body.innerHTML;
  }
}
    • リッチテキストはiframeで挿入されるようだ。数が多くなるとなんか重そう。
    • iframeのコンテンツはcontentDocumentプロパティで取得できる。