jQueryでtemplates。


 Templates – jQuery API
 jQuery Templates, Data Link, globalization が公式 jQuery プラグインに加わりました - THE TRUTH IS OUT THERE - Site Home - MSDN Blogs

 もう自分的には随分と前の話なので細かいところはすっかりわすれてすっきりくんなのですけども、いい加減書いておかないとなぁと言うことで重い重い重い腰を上げて。

 去年の終わりくらいにこのページの作り替えに着手しまして、それは別に見た目がどうこうじゃなくて、twitterとかがやっていたshebang(とかhashbang)と呼ばれる仕組みをやってみたかっただけで、まぁ、それは興味本位に先走り過ぎた愚行でありましてこれから先苦労するみたいな話もありますけど、実はうちはshebang無しのURLもそれなりに用意しているので勝手に「うん、大丈夫だよね。両方メンテするので面倒くさいけど」みたいな気持ちでありますのですが、その際にJavaScriptでajax通信を行いデータを持ってきて、HTMLとして成形して出力みたいな処理が必要になるのですけど、これが凄く面倒でたまりませんでした。普通にHTMLを書くだけでも面倒くさいのに、JavaScript内なのでエスケープだの連結だのと。
 でまぁ、どうしたものかなぁと思っていたのですけど、解決策としてはテンプレートエンジン的なものを導入すればいいかと、JavaScript版の。早速ググってみましたら思った通りいつくかそれっぽいのが見つかりまして、中でも目を引いたのが当時から次期バーションには標準搭載と言われていたjquery-tmplです。

 実はこれ、もともとはMicrosoft製らしいのですよね。以前はMicrosoftさんでも自前でJavaScriptライブラリを開発していたのですけど、ある時からjQueryを推奨するように変わりました。この辺はadobeさん辺りも同様の施策を行っていたので世の中的な流れだと思います。私もある時から「もうみんなjQueryでいいじゃん、jQueryやっといたらいいよ」と洗脳されて言っていたのですけど、本当にそんな世になってしまうと「それで善いのか悪いのか」です。どっちだよ。
 そしてそれをjQueryさん本家に寄贈してくださったので公式のplug-inとして提供される……、はずです、もうしばらくしたら。最初に私が目にしたときは「次期バージョンである1.5に標準搭載」という話だったのですけど、結局その後の1.6でも提供されませんでした。曰く、「まだベータ版のモノを含めるわけにはいかない。そしてそれを決めるのは我々ではなく提供してくれる側だ」とどこかで見たような見てないような。どっちだ。
 そういう事情で今のところ、jQuery本体は別にもう一つファイルを読み込まねばなりませんが、MicrosoftさんがCDNで用意してくれています。そちらを有り難く活用させていただきましょう。ただし、未だにベータ版でありますから一応自己責任でとかおきまりのごにょごにょ。

 基本的な使い方はまず専用のテンプレート言語的なものを用いてテンプレートを定義して、それにJSON形式でデータを渡します。するとデータをバインドして出力をしてくれます。一応テンプレートタグでif文があるので簡単な判断ができます。同じ構造のデータを配列に入れて渡すと勝手にループしてくれたりもします(たまにいい迷惑かもしれないですけど)。あと、オプションで連想配列で値やら無名関数やらを渡せるので頑張ればある程度なんとかできる気がします。当ページでもいろいろと試してそれをネタにしたかったのですけど、基本的な使い方だけでなんとかなってしまいました。
 テンプレートはJavaScript内で文字列として定義してもいいし、専用のtypeを指定してscriptタグ内にそのままの形で記述する事もできます。今回私は後者の方法をとりました。だってこれがやりたかったのだもの。

 ちなみに、記事本文部分のテンプレートは以下のようになっていますよ。type="text/x-jquery-tmpl"と指定したscriptタグ内に記述できている事がわかると思います。


<script id="entryArticleTemplate" type="text/x-jquery-tmpl">
  <article class="entry">
    <header class="entryHeader"><h3 class="green">${title}</h3></header>
    <time pubdate="${attr_created}" class="pubdate">${display_created}</time>
    {{html body}}
    {{if rel_entries.length}}
      <nav class="entryFooter">
        <ul>
        {{each rel_entries}}
          <li><a href="#!${url}">${title}</a></li>
        {{/each}}
        </ul>
      </nav>
    {{/if}}
    {{if tags.length}}
      <nav class="entryTags">
        <ul>
        {{each tags}}
          <li><a href='#!${url}'>${name}</a></li>
        {{/each}}
        </ul>
      </nav>
    {{/if}}
  </article>
</script>

 ${hoge}の部分が渡されたデータの同じ名前のキーの値で置き換わります。その値にタグなどを含むようならtemplates側のHTMLタグを用いる事でエスケープされる事を防ぎます。あと、ifタグでは値が無かったら表示しない様な判断をしています。
 jQueryには関係ないのですけど、見てお分かりの通りDjangoのテンプレート言語と {{ の時点で被りますので、Djangoを使っている当ページではそこいらへも対応を迫られました。ちゃんと公式にtemplatetagというタグが用意されているのですけど、なんだか面倒だなと思ってしまって {{ }} で囲んで出力するオレオレfilterを用意しました。どちらが面倒だったのだろう。

 その時のcommitログを一応以下に。参考にもならないと思いますけどね。

 Commit 0cee62e68ed0ba5ffe4639410a161c7fa4629a83 to tactactad/reiare - GitHub

 この分野のものには新旧様々色々なものが既に公開されていて、中でも

 Life is beautiful: JavaScript HTMLテンプレートエンジン SNBinder 公開

 というのが気にはなったのですが、標準搭載というお手軽さに引かれてこちらを選択していました。まぁ、今のところその標準搭載というのは実現されていないのですけど。別途テンプレート用のインクルードファイルを用意するのではなくて、scriptタグ内で普通のHTMLファイルの中に埋められるというのはそれはそれでメリットだと思います。scriptタグ内に記述すると、テンプレート内でscriptタグが必要になるとさらに工夫が必要になりますが、幾つか解決策も提示されていますよ。無理矢理っぽいのもありましたけど。
 実際に使ってみてそれほど苦にはならなかったし、仕組み的にも面白いと思ったのでこれからも使っていきたいですよ。早くベータ取れて標準搭載されて欲しい、待ってます!