SNBinderを試してみる
Life is beautiful: JavaScript HTMLテンプレートエンジン SNBinder 公開 で紹介されていたSNBinderが面白そうなので試してみる。
サンプルの内容
ブログっぽい何か。
サーバ側は、手元の環境が整えやすいのでJSPだけど、そこはどうでもいい。
/snbinder/index.html
HTML。左カラムに「ようこそ」メッセージ、右カラムにブログ記事の一覧が表示される。
<html> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"/> <title>test</title> <style type="text/css"> #navi { float: left; width: 20%; padding: 10px; } #content { margin-left: 20%; } .entry { border: 1px black solid; padding: 10px; margin: 10px; } </style> </head> <body> <div id="navi"> <div id="navi-head">Navigation:</div> <div id="greeting"></div> </div> <div id="content"> <div id="content-head">Recent blog entries:</div> <div id="entries"></div> </div> </body> <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script> <script type="text/javascript" src="/snbinder/assets/snbinder-0.5.3-modified.js"></script> <script type="text/javascript" src="/snbinder/assets/index.js"></script> </html>
snbinder-0.5.3-modified になっている点については後述。
/snbinder/user/info.jsp
ユーザ情報のJSONデータを返すだけ。
<%@ page language="java" contentType="application/json; charset=utf-8" pageEncoding="utf-8"%> {"name": "Leonardo da Vinci"}
/snbinder/blog/entries.jsp
ブログエントリ一覧のJSONデータを返す。
<%@ page language="java" contentType="application/json; charset=utf-8" pageEncoding="utf-8"%> [ { "id": "2", "content": "I know that many will call this useless work.", "posted_at": "2011/01/23 23:59:59" }, { "id": "1", "content": "Hello, world!", "posted_at": "2011/01/22 00:00:00" } ]
/snbinder/assets/template.htm
テンプレート。
{%}greeting{%} <p>Hello, <b>$(.name)!</b></p> {%}blog_entry{%} <div class="entry"> <div class="index">entry #<b>$(.id)</b></div> <div class="text"> <b>$(.content)</b> </div> <div class="status"> posted at <b>$(.posted_at)</b> </div> </div>
/snbinder/assets/index.js
実際にテンプレートエンジンでビューを構築する部分。
var debug = { delay: 0 }; $(function(){ //SNBinder.init({}); SNBinder.get_named_sections("/snbinder/assets/template.htm", null, function(templates) { SNBinder.get("/snbinder/user/info.jsp", null, true, function(json) { // bind() は、テンプレートの "greeting" セクションに // info.jsp が返したJSONデータを埋め込んで返す $("#greeting").html(SNBinder.bind(templates["greeting"], json)); }); SNBinder.get("/snbinder/blog/entries.jsp", null, true, function(json) { // bind_rowset() は、entries.jsp が返したJSONデータ内の各要素を使って、 // テンプレートの "blog_entry" セクションに対して繰り返し埋め込みを行い、 // 全ての結果を結合して返す。 $("#entries").html(SNBinder.bind_rowset(templates["blog_entry"], json)) // 以下の省略形と考えればOK // var template_func = SNBinder.compile(templates["blog_entry"]); // var html = ""; // for (var key in json) { // html += template_func(json[key], key); // } // $("#entries").html(html); }); }); })
debugという名前の、上のようなグローバルオブジェクトがないとエラーになる模様。最新バージョンではすでに修正されています。
- SNBinder.init({}); は、READMEには必要とあるけど、エラーハンドリングやログイン処理のカスタマイズをしないなら、必要ない模様。
- SNBinder.get_named_sections は、上述の {%} つきテンプレートを読んで、「セクション名」がキー、「本体」が値になったオブジェクトを第三引数のコールバック関数に渡してくれる。
実際の関数名がいくつかREADMEと異なっているので、ソースを読もう。最新バージョンではすでに修正されています。
/snbinder/assets/snbinder-0.5.3-modified.js
注:最新バージョンではすでに修正されています(コメント参照)。
オリジナルから以下を修正した。
@@ -57,7 +57,7 @@ var SNBinder = (function() { get: function(url, params, isJson, callback, _options) { var options = { bypass_cache: false, - cache_result: true, + cache_result: true }; $.extend(options, _options); @@ -167,6 +167,9 @@ var SNBinder = (function() { })(); }, // end of post evaluate: function(json) { + if (typeof(json) == 'object') { + return json; + } try { var obj; eval("obj=" + json);
動作結果
以下のようにJSONデータがテンプレートに埋め込まれて表示された(太字の箇所が「動的」な部分)。デザイン能力がまったくないのでとんでもなくしょぼいけど…
IE8とChromeで試したけど、どちらも普通にうまくいった。
どうせ今時のWebアプリケーションならJavaScriptを書かないということはありえないので、いっそのことMVCのVは完全にHTML+JavaScriptのみに集約してしまう、というのはすごく良さげな気がする。HTMLを操作するならJavaScript(というかjQuery)を使うのが一番楽だし、JSTLやらStrutsやらの汚らしいタグを必死こいて使ってHTMLをこねくり回すのに比べたら遥かにシンプルで自然だ。