[[JSライブラリ]] > Handlebars.js
* Handlebars.js [#d97b8a36]
#setlinebreak(on)
&color(red){書きかけの記事};
#contents
** Handlebars.js とは [#g6d7ced2]
#html(<div style="padding-left:20px">)
JavaScriptテンプレートエンジン
双方向データバインドの機能等はなく、単純なテンプレートエンジン。
#html(</div>)
** 利用準備 [#xec49783]
#html(<div style="padding-left:20px">)
http://handlebarsjs.com/ からダウンロードした js をヘッダで読み込む
#myhtmlcode(){{
<head>
<meta charset="utf-8" />
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="handlebars-v3.0.3.js"></script>
</head>
・
・
}}
#html(</div>)
** 単純な値の展開 [#sf5e2266]
#html(<div style="padding-left:20px;">)
HTML
#myhtmlcode(){{
<script id="entry-template" type="text/x-handlebars-template">
<div class="entry">
<h1>{{title}}</h1>
<div class="body">
{{body}
</div>
</div>
</script>
<div id="area1"></div>
<input id="btn1" type="button" value="test1" />
<input id="btn2" type="button" value="test2" />
}}
JavaScript
#mycode(){{
$(function(){
var source = $("#entry-template").html();
var template = Handlebars.compile(source);
var context = {title: "My New Post", body: "This is my first post!"};
var html = template(context);
$("#area1").html(html);
$("#btn1").on("click", function(){
var html = template({ title : "title1", body : "test1 body!!!" });
$("#area1").html(html);
});
$("#btn2").on("click", function(){
var html = template({ title : "title2", body : "test2 body!!!" });
$("#area1").html(html);
});
}}
#html(</div>)
** 単純な値の展開(scriptタグにテンプレートを記述しない場合) [#ib1cde78]
#html(<div style="padding-left:20px;">)
HTML
#myhtmlcode(){{
<div id="area1">
<div class="entry">
<h1>{{title}}</h1>
<div class="body">
{{body}
</div>
</div>
</div>
<input id="btn1" type="button" value="test1" />
<input id="btn2" type="button" value="test2" />
}}
JavaScript
#mycode(){{
$(function(){
var source = $("#area1").html();
var template = Handlebars.compile(source);
var context = {title: "My New Post", body: "This is my first post!"};
var html = template(context);
$("#area1").html(html);
$("#btn1").on("click", function(){
var html = template({ title : "title1", body : "test1 body!!!" });
$("#area1").html(html);
});
$("#btn2").on("click", function(){
var html = template({ title : "title2", body : "test2 body!!!" });
$("#area1").html(html);
});
});
}}
#html(</div>)
** リストの展開 [#he181744]
#html(<div style="padding-left:20px;">)
ビルトインヘルパー(http://handlebarsjs.com/builtin_helpers.html)の each block helper 等を利用する事により実現可能。
また、registerHelper を利用して独自の展開方法を指定する事も可能。(後述:[[ラップ例>#p8027239]]を参照)
HTML
#myhtmlcode(){{
<div id="div1">
{{#each people}}{{firstName}} {{lastName}}<br />{{/each}}
</div>
}}
JavaScript
#mycode(){{
$(function(){
var data1 = {
people: [
{firstName: "Yehuda", lastName: "Katz"},
{firstName: "Carl", lastName: "Lerche"},
{firstName: "Alan", lastName: "Johnson"}
]
};
var source1 = $("#div1").html();
var template1 = Handlebars.compile(source1);
var html1 = template1(data1);
$("#div1").html(html1);
});
}}
#html(</div>)
** 条件分岐 [#x143bb57]
#html(<div style="padding-left:20px;">)
条件分岐もビルトインヘルパー(http://handlebarsjs.com/builtin_helpers.html)として提供されている。
#myhtmlcode(){{
<!-- 変数 author が定義されているかどうかで表示内容を変える -->
<div class="entry">
{{#if author}}
<h1>{{firstName}} {{lastName}}</h1>
{{else}}
<h1>Unknown Author</h1>
{{/if}}
</div>
}}
※ 反対に変数が定義されていない時に展開する場合は、unless を使用。
#html(</div>)
** ラップ例 [#p8027239]
#html(<div style="padding-left:20px;">)
先にデザインだけを行いたいケースで scriptタグにテンプレートを記述するのが嫌な場合。
以下のような感じでラップすれば、(自分的には)そんなに違和感がない。
HTML/CSS
#myhtmlcode(){{
<style type="text/css">
.my_tmpl {
.display:none; /* デザイン時はコメントアウトしておく */
}
</style>
<table border="1">
<tr>
<th>id</th>
<th>isbn</th>
<th>title</th>
<th>price</th>
</tr>
<tr id="mylist" class="my_tmpl">
<td>{{id}}</td>
<td>{{isbn}}</td>
<td>{{title}}</td>
<td>{{price}}</td>
</tr>
</table>
}}
JavaScript
#mycode(){{
var templates = {};
$(function(){
///// 共通処理 START /////
// {{#list ... }} ... {{/list}}の展開を行うヘルパ関数を登録
Handlebars.registerHelper('list', function(items, options) {
var out = "";
var preTag = options.hash["type"] ? "<" + options.hash["type"] + " class=\"list_row\" >" : "";
var sufTag = options.hash["type"] ? "</" + options.hash["type"] + ">" : "";
for(var i=0, l=items.length; i<l; i++) {
out = out + preTag + options.fn(items[i]) + sufTag;
}
return out;
});
// テンプレートHTMLを取得する関数
var getListTempl = function(id, opts){
opts = opts || {};
var tmpl = $("#"+id).html();
var varName = opts["row"] || $("#"+id).data("row") || "row";
var tagName = $("#"+id)[0].nodeName;
var className = ""; // TODO
var source = "{{#list " + varName+ " type=\"" + tagName + "\" class=\"" + className+ "\" }}" + tmpl + "{{/list}}";
return source;
};
// 指定されたIDの要素に変数の内容を展開する関数
var renderList = function(id, data, opts){
var template = null;
var templId = id + "_" + JSON.stringify(opts);
if (!templates[templId]){
var source = getListTempl(id, opts);
templates[templId] = Handlebars.compile(source);
}
var template = templates[templId];
var html = template(data);
$("#" + id).parent().find(".list_row").remove(); // 再描画用に、既に動的に展開されている部分をいったん削除(ここらへんは状況に応じて要考慮)
$("#" + id).after(html);
};
///// 共通処理 END /////
// リストの描画
var listData = {
book : [
{id: 1, isbn : "test1", title : "タイトル1", price : 1000 }
,{id: 2, isbn : "test2", title : "タイトル2", price : 2000 }
,{id: 3, isbn : "test3", title : "タイトル3", price : 3000 }
,{id: 4, isbn : "test4", title : "タイトル4", price : 4000 }
,{id: 5, isbn : "test5", title : "タイトル5", price : 5000 }
]
};
renderList("mylist", listData, { row : "book"});
});
}}
#html(</div>)