28 Oct 2009

memo: gaeにTinyMCE導入

最近google app engineをちょこちょこいじって、webアプリなど作っているんですが、コンテンツの入力画面を作るのにTinyMCEを使ったので、その作業メモです。

TinyMCEとは

TinyMCE - Home

TinyMCEとはjavascriptで動くWysiwygエディタです。ユーザはふつうのワープロソフトのようなインタフェースで文章を書くことができ、TinyMCEはそれを適切なhtmlへ変換します。導入やカスタマイズが簡単で、WordpressやJoomlaなどのCMSやオラクル, MS, Apple, SAPのソフトウエアなど、豊富な導入実績があります。見た目はこんな感じです

インストール

パッケージをダウンロード、解凍後、任意の場所に設置します。あとはhtmlファイルのヘッダに、

<script type="text/javascript" src="./js/tiny_mce/tiny_mce.js">script>

<script type="text/javascript">
tinyMCE.init({
	mode : "textareas"
});
script>
head>
body>



<textarea>textarea>

と書くだけで、textareaがtinymceのインタフェースになります。

GAEの場合

GAE上で使用する場合は、まずapp.yaml(設定用のyamlファイル)に静的ファイルを定義します。

- url: /js
  static_dir: js

htmlヘッダでのパスの指定は、先頭にコンマなど入れないよう注意します。

<script type="text/javascript" src="/js/tiny_mce/tiny_mce.js">script>

あとは通常と同様です。

カスタマイズ

多くのカスタマイズはhtmlヘッダのtinyMCE.init()関数で行います。設定項目の一覧はこちらです。

TinyMCE:Configuration - Moxiecode Documentation Wiki

以下は、今回僕が使用したものです。

editor_selector

tinymceを適用させるclassを指定します。デフォルトでは、上記の例では全てのtextareaに適用ますが、このオプションにより、任意の要素に適用できます。

width, height

エディタの縦横の大きさを決めます。単位はpixel。

theme

エディタのテーマを変更します。tinymceにはビルトインでsimpleとadvancedの2つのテーマが付属しており、theme属性を指定しない場合はsimpleになります。themeをadvancedにすることで、使える機能も増え、また細かなカスタマイズも可能になります。

theme_advanced_layout_manager

advancedテーマのレイアウトの指定方法を決めるオプションです。3種類ありますが、とりあえずSimpleLayoutを指定しておけば、次のtheme_advanced_buttons*でボタンを出したり消したりできます。

theme_advanced_buttons*

エディタに、行ごとにどのボタンを表示させるかを決定します。最大3行です。使えるボタンはこちらで一覧できます。

TinyMCE:Control reference - Moxiecode Documentation Wiki

external_image_list_url

画像挿入ボタンを押した際に、挿入できる画像の一覧を渡すためのオプションです。次のようにして、jsのファイルを渡します。

        external_image_list_url: "/externallist.js",

externallist.jsの中身は、以下のようなarrayにします。

var tinyMCEImageList = new Array(
// Name, URL
["Logo 1", "logo.jpg"],
["Logo 2 Over", "logo_over.jpg"]
);

このjsファイルを、サーバ上にアップロードされた画像をリストにするように、サーバサイドで動的に生成してあげると良いです。

external_image_list_urlをGAEで使う場合

画像は全てデータストアに格納されており、"/img?id=*"というURIでアクセスできるものとします。(方法はこちらの記事を参考にしてください:throw Life - Google App Engineのデータストアから気持ちよく画像を取り出すオススメできない方法)。画像データのモデルは、以下のように、imageというblobと、titleというstring、dateという日時を持っているものとします。

class ImageModel(db.Model):
    title = db.StringProperty(required=True)
    image = db.BlobProperty(required=True)
    date = db.DateTimeProperty(auto_now_add=True)

このImageModelの全画像データを、上記の形式でjsのファイルに出力します。

class ExternalList(webapp.RequestHandler):
    def get(self):
        query = ImageModel.all()
        output = ''
        output += 'var tinyMCEImageList = new Array('
        first = 1
        for img in query:
            if first:
                first = 0
            else:
                output += ','
            output += '["' + img.title + '", '
            output += '"/img?id=' + str(img.key().id()) + '"]'
        output += ');'
        self.response.headers['Content-Type'] = 'text/javascript'
        self.response.out.write(output)

リストの最後にコンマを入れないようにする処理がちょっとださいですが、見逃してください。このハンドラを適当なURIにマップし、

application = webapp.WSGIApplication(
                                     [('/', MainPage),
                                      ('/externallist', ExternalList),
                                      ], debug=True)

そしてこのURIをexternal_image_list_urlで指定してあげればOKです。

        external_image_list_url: "/externallist",
まとめ

ここまでをまとめると、こうなります。

<script type="text/javascript" src="/js/tiny_mce/tiny_mce.js">script>

<script type="text/javascript">
tinyMCE.init({
	mode: "textareas",
        editor_selector: "tinymce",
        width: "800",
        height: "500",
        external_image_list_url: "/externallist",
        theme: "advanced",
	theme_advanced_layout_manager: "SimpleLayout",
	theme_advanced_buttons1: "bold, italic, underline, separator, forecolor, backcolor, fontselect, fontsizeselect",
	theme_advanced_buttons2: "justifyleft, justifycenter, justifyright, separator, bullist, numlist, separator, link, unlink, image, code",
	theme_advanced_buttons3: "",
});
script>

見た目はこんなんです。