今回のテーマ

さてさて。だいぶdojoにも慣れてきましたし、ちょっとしたアプリを作ってみましょうか。 hello, world だけじゃつまんないですもんね。

手頃ないいネタないかなー、って面白そうなAPIありましたよ。

github Markdown Rendering API

みんな大好きgithub、のAPIですね。マークダウンで書いたテキストを渡すと、それをHTMLに変換したものを返してくれます。便利便利♪これを使って、簡易マークダウンエディタ作りましょう。手順はこんな感じ。

  • 画面にはテキストエリアがあって
  • そこにmarkdownで入力したテキストをajaxってサーバにpost
  • レスポンスのHTMLを描画

dojoで部品を探す

上記手順で、ajaxでサーバとやり取りする部分は前々回あたりでやりましたね。となると、今回やるべきは

  • テキストを(markdownで)入力するところ
  • サーバ通信するきっかけ
  • テキストを(HTMLで)出力するところ
のあたりで、dojoでうまいことできる部品があればいいなーってとこですね。 それでは、今回の目的にはどんなUIが考えられますかね?

UI案

案1:入力するところと、出力するところを横に並べて、間のボタンクリックのタイミングでサーバ通信する、とか?

案2:入力するところタブと、出力するところタブを作って、タブ切り替えのタイミングでサーバ通信する、とか?

イメージ図。
イメージ図

どちらでもできそうですね。でもせっかくdojo使うので面白いやつでいきましょう。

InlineEditBox

dijitの部品であるInlineEditBoxは、その名の通りインラインのeditboxです。…つ、つまり一見普通のHTML要素をクリックするとその部分がテキストエディタになって、編集することができます。編集後はもともと普通のHTML要素がアップデートされます。

言葉で説明するより、testを見ると一目瞭然ですね。

これって、先ほど述べた今回欲しいUIの3つの条件にばっちり満たしますよね。

こいつは使えそうってのは分かったけど、具体的にどう書けば良いのか?最近のバージョンに対応した素敵な解説本でも出ていれば、それを読みたいところですがそうもいかないので、公式のドキュメントに頼ります。まあdojoに限らないですけど

この2つ(とソース)があればなんとかなるもんです。dojoはこの2つとも充実してます。今回もそれをもとに、プロパティはこんな感じで設定しますよ。

  • 表示はHTMLで行いたいので、renderAsHtmlをtrueに。
  • 登録するボタンを表示したいので、autoSaveをfalseに。
  • 登録するボタンのラベル表示が「保存」だとなんなんで、buttonSaveを "preview"に。
  • 登録するボタンを押した時にxhr通信をしたいので、onChangeにその旨を記述。

コードで書くとこんな感じになります。

mdEditor = new InlineEditBox({
    editor: Textarea,
    renderAsHtml: true,
    buttonSave: "preview",
    buttonCancel: "cancel",
    autoSave: false,
    onClick: function(){
        // クリックされたときには、markdown形式の方のテキストをセット
        this.set("value", inputString);
    },
    onChange: function(){
        var mdEditorVal = this.get("value");
        if (string.trim(mdEditorVal) != string.trim(previewString)){
            // ajaxするところ
            request.post(
                "./md",
                {
                    data:{
                        text: mdEditorVal
                    }
                }).then(
                    function(text){
                        // うまく結果を受け取ったらHTMLになったテキストをセット
                        inputString = mdEditorVal;
                        previewString = text;
                        mdEditor.set("value", text);
                    },
                    function(error){
                        console.log("An error occurred: " + error);
                    }
                );
        }
    }
}, "markdown_editor"); // ターゲットdomのid

サーバー側を駆け足で

サーバー側はメインとなるmarkdownエンジンは前述のとおりgithubなんで、特になんもないです。ただ、JSONPのAPIがないんで、プロキシってあげます。個人的に今年はpython勉強年なんで、pythonのbottle.pyを使ってみました。

@post('/md')
def md():
    requestedParam = request.POST
    params = dict(text=requestedParam.text, mode="gfm")
    res = urlopen('https://api.github.com/markdown', json.dumps(params))
    return res.read()

簡単便利♪

こんな感じになりました

初期表示

15

クリックすると…

47

マークダウンで書いてプレビューを押すと…

37

HTMLになりました!

11

全体をgithubにおいておきます。

https://github.com/haseg/dojo-md-editor