ラベル JsRender編 の投稿を表示しています。 すべての投稿を表示
ラベル JsRender編 の投稿を表示しています。 すべての投稿を表示

2015年1月8日木曜日

【JsRender】GAEとの連携

あけましておめでとう。
株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。

本年もよろしくお願いします。

さて、ここしばらくはJavaScriptによる画面レンダリングツール「JsRender」について連載していましたが、
それも今回で最終回を迎えます。

最終回はGAEとの連携です。

思い出す

過去の記事を掘り返してみたら、GAEの記事を最後に書いたのは2014年9月でした。
もう4ヶ月も経ってしまったのですね……。

そして、そのGAEでの連載で私が何度も主張していたこと。それは。

GAEはjspを使わず、フルAjaxで書いてこそ真価を発揮する。

これでした。
そして、そのGAEの連載を中断して始めたのが、本連載である画面レンダリングツール「JsRender」のご紹介……。

もうお分かりですね。

この一連の連載は、JsRenderをGAEで使用する為の前振りだったのです。

ようやく本懐を遂げること出来ました。
では、さっそくGAEに適用してみましょう。

JSON発行

GAEからJSONを発行する方法は過去の記事で紹介しておりましたね。



昔の記事なので改めて書きますが、
GAEでは「GSON」というライブラリを使ってJavaのオブジェクトをJSON文字列化するやり方をオススメします。

Gson gson = new Gson();
String json = gson.toJson(jet);

その結果、以下のようなJSON文字列が出力されます。

{"shohinList":[{"key":{"kind":"Shohin","id":57},"seqNo":1,"shohinId":"57","shohinName":"%E5%95%86%E5%93%813","stock":345,"deliveryDate":"2015/01/10","createdAt":"2015/01/08 21:45:28","updatedAt":"2015/01/08 21:45:28"},{"key":{"kind":"Shohin","id":56},"seqNo":2,"shohinId":"56","shohinName":"%E5%95%86%E5%93%81%EF%BC%92","stock":234,"deliveryDate":"2015/01/09","createdAt":"2015/01/08 21:45:15","updatedAt":"2015/01/08 21:45:15"},{"key":{"kind":"Shohin","id":55},"seqNo":3,"shohinId":"55","shohinName":"%E5%95%86%E5%93%81%EF%BC%91","stock":123,"deliveryDate":"2015/01/08","createdAt":"2015/01/08 21:44:48","updatedAt":"2015/01/08 21:44:48"}],"responseCode":0}

ゴジャゴジャしていて分かりませんが……。
実は「日本語はURLエンコードしないと文字化けして送受信出来ない」とか色々問題があるのですが、その辺については後日の連載で。

ともかく、この文字列を以下のやり方でレスポンスに乗せてあげれば、Ajaxでレスポンスを取得することが出来ます。
response.getWriter().write(json);

画面出力

文字列さえ出力出来てしまえばこっちのものです。

標準的なJQueryの非同期通信で文字列を取得し、そのままJsRenderに流し込んでしまいます。

function doSearch() {

 $.ajax({
  url : $("#form").attr('action'),
  type : $("#form").attr('method'),
  data : $("#form").serialize(),
  dataType : 'json',
  success : function(json) {

   var items = json.shohinList;

   var length = items.length;
   for (i = 0; i < length; i++) {
    items[i].shohinName = decodeURI(items[i].shohinName);
   }

   $("#shohinList").html($("#shohinListTemplate").render(json));
  }
 });
}
JsRenderのテンプレートはこちら。
<script id="shohinListTemplate" type="text/x-jsrender">

<table class="shohinList">
 <tr>
  <th class="no">NO</th>
  <th class="shohinId">商品ID</th>
  <th class="shohinName">商品名</th>
  <th class="action"></th>
 </tr>
 {{for shohinList}}
 <tr>
  <td class="no">{{>seqNo}}</td>
  <td class="shohinId">{{>shohinId}}</td>
  <td class="shohinName">{{>shohinName}}</td>
  <td class="action">詳細 編集</td>
 </tr>
 {{/for}}
</table>

</script>

>/script<

結果は、ほら。
普通のjspと比較しても遜色無い機能的な検索結果一覧が出力出来ました。


これでGAEの画面出力も安心ですね。

終わりに

ようやくGAEに戻って参りました。

画面出力機能の骨子が出来上がったことですし、
次回からは再びGAEに復帰。

GAEのDBであるBigTableの『検索』についてご紹介して行きたいと思います。

2014年12月23日火曜日

【JsRender】#parent

株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。

現在はJavaScriptによる画面レンダリングツール「JsRender」について連載しています。

今回も公式サイトに乗っていない秘密機能「parent」についてのご紹介です。

必要になるシチュエーション

#parentはfor文の真っ最中などで、親クラスを遡ってパラメータを取得する機能です。

例えば、私は「技術開発事業部」の所属ですが、同じ部にはメンバーが何人もいます。

  • 技術開発事業部:Aさん
  • 技術開発事業部:Bさん
  • 技術開発事業部:Cさん

こういう場合、データの持ち方によっては

  • 親クラス:部署
  • 子クラス:メンバー


というように、親子関係が生ずることになります。

このデータの持ち方で所属とメンバーを表現したい場合は、以下のような形式にするのが合理的です。


<div id="result"></div>

<script id="jsRenderTmpl" type="text/x-jsrender">
★{{:department}}
{{for members}}
<div>
・{{:name}}
</div>
{{/for}}
</script>

<script>
var data = {
  "department": "技術開発事業部",
  "members": [
      {"name": "Aさん"},
      {"name": "Bさん"},
      {"name": "Cさん"}
 ]
};

var template = $.templates("#jsRenderTmpl");

var htmlOutput = template.render(data);

$("#result").html(htmlOutput);
</script>

しかしですね、場合によっては以下みたいな表示にしたいケースもあるわけですよ。


これは痛いんですよね。
何故なら、階層が違うから。

JSONの定義では「members」をfor文のスコープとして回していますので、membersより配下のデータを表示する場合は何も難しくありません。
普通に順を追って定義していけば表示出来ます。

しかし、membersより上のデータはスコープの中に入っていませんので、単純に取得することが出来ません。
今回のテーマである#parentはこういう場合に使用します。

#parentを活用

#parentは、まあ、タグ名から分かりますようにfor文のスコープの外にある親データを取ってくる機能です。
その実装方法はこちら。

<script id="jsRenderTmpl" type="text/x-jsrender">
{{for members}}
<div>
・{{:#parent.parent.data.department}}:{{:name}}
</div>
{{/for}}
</script>

<script>
var data = {
  "department": "技術開発事業部",
  "members": [
      {"name": "Aさん"},
      {"name": "Bさん"},
      {"name": "Cさん"}
 ]
};

var template = $.templates("#jsRenderTmpl");

var htmlOutput = template.render(data);

$("#result").html(htmlOutput);
</script>

「#parent.parent.data.department」、これで「技術開発事業部」という値が取れています。

詳細解説

「あれ? parent2連打になってるのは何?」と思われたかと思います。

jsrenderでは「parent」を一個各毎に階層を一個遡るという意味になります。

今回の場合、スタート地点となるのはfor文の中のメンバーですから、


  • 単にそのレコードを出したい場合⇒「#data.name」(dataは通常省略)
  • その一個上のmembersを取りたい場合⇒「#parent.data」
  • その一個上のdataを取りたい場合⇒「#parent.parent.data」
  • 目的のdepartmentはdataの子供なので⇒「#parent.parent.data.department」

こういうわけです。
parentを連結することで一回一番上まで遡って、それからdepartmentを狙い撃ちするという段取りになるわけです。

parentを連発する辺り最初は戸惑いますが、分かってしまえば簡単なことですね。

終わりに

今回ご紹介した#parentは結構便利な機能です。
これを知らないと画面を表示する為にクラスを非正規化しなければならなくなり、手間も転送データ量も増えて大変ですからね。
上手く活用すれば開発効率もUPするでしょう。

ぜひマスターすることをオススメします。

2014年12月8日月曜日

【JsRender】#index

株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。

現在はJavaScriptによる画面レンダリングツール「JsRender」について連載しています。

さて、私はこの連載を行うに辺り、基本的に以下の公式サイトを読んで執筆しています。




しかし、どうも公式サイトのドキュメントに載っていない機能があるようです。
酷い話ですが、今回はその機能の一つ「#index」についてご紹介します。

for文のループ回数「#index」

普通、for文だと「for(int i=0;i;10;i++)」みたいに現在がfor文の何番目なのかを
iなどの変数で認識することが出来ます。

しかし、JsRenderのfor文はfor文と言ってもJavaで言う所の「for(String str : list)」の形式と言いますか、
つまり『配列全出力』の体を取っています。

この為、実装する上では通常のプログラミングである「i」に相当する変数が登場しません。
この為、「偶数行と奇数行で色を変えたい」みたいな、現在が何ループ目であるかを認識するには、挿入の元になっているJSONにパラメータを持たせる必要があるように見えます。

しかし、実は隠しパラメータとしてループの行数を持っていまして、それが「#index」です。

<script id="jsRenderTmpl" type="text/x-jsrender">
★{{:title}}
{{for members}}
<div>
・{{>#index}}:{{:name}}
</div>
{{/for}}
</script>

<script>
var data = {
  "title": "for文サンプル一覧",
  "members": [
      {"name": "碇シンジ",sex:"male"},
      {"name": "綾波レイ",sex:"female"},
      {"name": "ゼルエル",sex:"unknown"}
 ]
};

var template = $.templates("#jsRenderTmpl");

var htmlOutput = template.render(data);

$("#result").html(htmlOutput);
</script>



ちゃんと行数が出ているでますね?

加工

では、この「#index」がちゃんと加工したりif文で使えたりするかも検証してみましょう。

まずは偶数/奇数の判定から。

<script id="jsRenderTmpl" type="text/x-jsrender">
★{{:title}}
{{for members}}
<div>
・{{>#index}}:{{:name}}:
 {{if #index %2 == 0}}
  偶数行
 {{else}}
  奇数行
 {{/if}}
</div>
{{/for}}
</script>

<script>
var data = {
  "title": "for文サンプル一覧",
  "members": [
      {"name": "碇シンジ",sex:"male"},
      {"name": "綾波レイ",sex:"female"},
      {"name": "ゼルエル",sex:"unknown"}
 ]
};

var template = $.templates("#jsRenderTmpl");

var htmlOutput = template.render(data);

$("#result").html(htmlOutput);
</script>


バッチリですね。

では、「0からスタートではなく、1からスタートしたい」という場合は、
単純にindexに+1すればOKです。

<script id="jsRenderTmpl" type="text/x-jsrender">
★{{:title}}
{{for members}}
<div>
・{{>#index + 1}}:{{:name}}
</div>
{{/for}}
</script>

<script>
var data = {
  "title": "for文サンプル一覧",
  "members": [
      {"name": "碇シンジ",sex:"male"},
      {"name": "綾波レイ",sex:"female"},
      {"name": "ゼルエル",sex:"unknown"}
 ]
};

var template = $.templates("#jsRenderTmpl");

var htmlOutput = template.render(data);

$("#result").html(htmlOutput);
</script>



簡単ですね!

終わりに

この「#index」は、前述の通り無くてもJSON定義の方で回避可能です。
しかし、知っていると知らないとでは便利さが格段に違います。

何で公式サイトに載っていないのか謎ですが、ぜひ活用していきたいものです。

引き続き隠し機能を検証します。

2014年11月5日水曜日

【JsRender】prop

株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。

現在はJavaScriptによる画面レンダリングツール「JsRender」について連載しています。

今回は「props」、つまり「プロパティ」についてご紹介します。

要するにMap

このpropsとは、要するにJavaで言えばMap総当たりのことです。
propsは「Mapに格納されている全てのkeyに対して値を取得する」というものです。

例を挙げてみましょう。

まず以下にまたしてもメンバー情報一覧を表示するソースを記載します。

<script id="jsRenderTmpl" type="text/x-jsrender">
★{{:title}}
<table>
 <tr>
  <td>名前</td>
  <td>年齢</td>
  <td>性別</td>
  <td>血液型</td>
 </tr>
{{for members}}

<tr>
 <td>{{:name}}</td>
 <td>{{:age}}</td>
 <td>{{:sex}}</td>
 <td>{{:blood}}</td>
</tr>

{{/for}}

</table>
</script>

<script>
var data = {
  "title": "名前一覧",
  "members": [
      {"name": "Tacy1号","age": "28","sex": "男","blood": "AB"},
      {"name": "Tacy2号","age": "28","sex": "男","blood": "AB"},
      {"name": "Tacy17号","age": "28","sex": "男","blood": "AB"}
 ]
};

var template = $.templates("#jsRenderTmpl");

var htmlOutput = template.render(data);

$("#result").html(htmlOutput);
</script>



今回問題になるのは「横の長さ」です。
サンプルでは「名前」「年齢」「性別」「血液型」の4列ですけれども、案件によってはズラッと長々と出てくることもありますので、そういう場合に一つ一つペタペタ書いていくのは結構大変というもの。

そこで、「JSONタグの中にあるものを全て出力する」としたい場合に出番となるのがpropsです。

そのサンプルがこちら。

<script id="jsRenderTmpl" type="text/x-jsrender">
★{{:title}}
<table>
{{props members}}
<tr>
 {{props prop}}
 <td>{{>key}}:{{>prop}}</td>
 {{/props}}
</tr>
{{/props}}

</table>
</script>

<script>
var data = {
  "title": "名前一覧",
  "members": [
      {"seq":0,"name": "Tacy1号","age": "28","sex": "男","blood": "AB"},
      {"seq":1,"name": "Tacy2号","age": "28","sex": "男","blood": "AB"},
      {"seq":2,"name": "Tacy3号","age": "28","sex": "男","blood": "AB"}
 ]
};

var template = $.templates("#jsRenderTmpl");

var htmlOutput = template.render(data);

$("#result").html(htmlOutput);
</script>



「{{props members}}」とやることで、menbersの中の情報を全部取得します。
ここから、


  • 「{{>key}}」でそのパラメータのキー値を。(配列の場合はシーケンス番号)
  • 「{{>prop}}」と指定することそのパラメータを。


これらをループで取得することが出来るわけです。

propsは入れ子で使うことも可能で、上記の例も入れ子型です。
「{{props prop}}」となっている部分が入れ子に書いている部分ですね。

デザインが……

「あれ? 上と下で画面レイアウトが違うじゃねえか!!」とお気づきの方、その通りです。

propsはパラメータ総出力なので、細かいレイアウト調整が効かないのです。
なので「ヘッダーを日本語で追加したい」とか「JSONタグのうち、必要なカラムだけ出す」とか、
そういう細かい要望にはif文でも使わない限り対応出来ません。

そんなロジック入れるのであれば、最初から従来のやり方通りにkey値をペタペタ決め打ちして、for文で回して書いていった方が良いと思いますね。

需要としては「JSONタグの中身をシンプルに全部出す」というケースくらいしか無いでしょう。

JSONタグを合わせる

「加工無しの全出力なんて、デバッグでしか使わないよ!!」と思ってしまうかもしれませんが、
しかしですね、この問題は発想の転換で乗り切りましょう。
ズバリ、JsRender側ではなく、JSONタグの方を合わせる方法で解決出来ます。

「サーバ側処理で必要なデータ加工を全て完了させて、HTML側ではそれを出すだけ」という切り分けを徹底すれば、
非常に便利な機能になります。

こんな感じに。


<script id="jsRenderTmpl" type="text/x-jsrender">
★{{:title}}
<table>
<tr>
 {{props header}}
 <td>{{>prop}}</td>
 {{/props}}
</tr>
{{props members}}
<tr>
 {{props prop}}
 <td>{{>prop}}</td>
 {{/props}}
</tr>
{{/props}}

</table>
</script>

<script>
var data = {
  "title": "名前一覧",
  "header": {"seq":"No","name": "名前","age": "年齢","sex": "性別","blood": "血液型"},
  "members": [
      {"seq":0,"name": "Tacy1号","age": "28","sex": "男","blood": "AB"},
      {"seq":1,"name": "Tacy2号","age": "28","sex": "男","blood": "AB"},
      {"seq":2,"name": "Tacy3号","age": "28","sex": "男","blood": "AB"}
 ]
};

var template = $.templates("#jsRenderTmpl");

var htmlOutput = template.render(data);

$("#result").html(htmlOutput);
</script>


ほら?
ヘッダーの属性とかも全部ひっ包めてJSONに入れてしまえばキッチリ綺麗になるでしょ?

これはコーディング思想として一つの基準になると思いますね。
HTMLやJavaScriptにボコボコ書き過ぎてしまうと可読性や生産性が大幅に下がります。

JsRenderは確かに便利なライブラリですが、しかしJsRenderは重い処理をする為にあるのではないのです。
「必要な情報はJSONに全部入れる」という実装思想を持つことが良いモジュールを作るキーとなるでしょう。

終わりに

引き続きJsRenderについて連載を継続します。

2014年10月31日金曜日

【JsRender】include文

株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。

現在はJavaScriptによる画面レンダリングツール「JsRender」について連載しています。

前回までで「if文」と「for文」のご紹介は終わりました。
それだけ分かってればJsRenderはもう十分やっていけるのですが、JsRenderには他にもチョコチョコ機能がありまして、そういうのを使うと開発効率が向上しますので知っておいて損はありません。

今回は外部定義の取り込み機能「include」についてご紹介します。

includeを使わない場合

JsRenderではテンプレート部分を「scriptタグ」で定義するわけですが、一方のscriptタグの中に、別のscriptタグを取り込む機能が「incude」です。

要するに、

  • 一個のscriptタグに全部書くと複雑だったりサイズが大きすぎる。
  • 同一テンプレートを再利用したい。


こういう需要の為に使う機能です。

例を挙げてみましょう。

「メンバーの名前一覧を表出力する」という機能を想定します。
テーブル出力ですので「ヘッダー」と「ボディ」があります。
ただし、特殊な事情として「スクロール対策として10行置きにヘッダーを挿入したい」という
仕様があります。

画面としてはこんな感じ。



それを実現するソースが以下です。

<script id="jsRenderTmpl" type="text/x-jsrender">
★{{:title}}
<table>
{{for members}}

{{if seq % 10 == 0}}
 <tr>
  <td>名前</td>
 </tr>
{{/if}}

<tr>
 <td>・{{:name}}</td>
</tr>

{{/for}}

</table>
</script>

<script>
var data = {
  "title": "名前一覧",
  "members": [
      {"seq":0,"name": "Tacy1号"},
      {"seq":1,"name": "Tacy2号"},
      {"seq":2,"name": "Tacy3号"},
      {"seq":3,"name": "Tacy4号"},
      {"seq":4,"name": "Tacy5号"},
      {"seq":5,"name": "Tacy6号"},
      {"seq":6,"name": "Tacy7号"},
      {"seq":7,"name": "Tacy8号"},
      {"seq":8,"name": "Tacy9号"},
      {"seq":9,"name": "Tacy10号"},
      {"seq":10,"name": "Tacy11号"},
      {"seq":11,"name": "Tacy12号"},
      {"seq":11,"name": "Tacy13号"},
      {"seq":11,"name": "Tacy14号"},
      {"seq":11,"name": "Tacy15号"},
      {"seq":11,"name": "Tacy16号"},
      {"seq":12,"name": "Tacy17号"}
 ]
};

var template = $.templates("#jsRenderTmpl");

var htmlOutput = template.render(data);

$("#result").html(htmlOutput);
</script>

if文とfor文とテンプレHTMLが入り乱れてちゃってますよね?

まあ、このサンプルはカラムが「名前」しか無いので何とでもなりますが、
もっとカラムが増えると、段々と可読性が下がってきます。

そこで、includeの出番です。

includeを使う場合

上記のサンプルの可読性を向上させる為にincludeタグを使ってみましょう。
構造としては以下の3分割にしようと思います。


  • ベース部分を担当する親
  • ヘッダー部のテンプレート
  • ボディ部のテンプレート


これでそれぞれの性質、機能毎にscriptタグが切れますので、
「ちょっとヘッダーだけ修正したい」みたいな要望にも対応しやすいです。

その対応バージョンがこちら。

<script id="jsRenderTmpl" type="text/x-jsrender">
★{{:title}}
<table>
{{for members}}
{{if seq % 10 == 0}}
 {{include tmpl="#jsRenderTmpl_head"/}}
{{/if}}
{{include tmpl="#jsRenderTmpl_body"/}}
{{/for}}
</table>
</script>

<script id="jsRenderTmpl_head" type="text/x-jsrender">
 <tr>
  <td>名前</td>
 </tr>
</script>

<script id="jsRenderTmpl_body" type="text/x-jsrender">
 <tr>
  <td>・{{:name}}</td>
 </tr>
</script>

どうです?
ソースの総量は増えてしまいますけど、キチッと分割されているので見易くなったでしょう?

まあ、ちょっとしたことにイチイチincludeしていると逆に面倒なだけですので、
includeを使うかどうかは、実装者の判断ですね。

上手くやれば巨大な画面でも綺麗にコーディング出来るでしょう。

終わりに

次回はテンプレートに送り込むJSONタグが複雑な場合に活躍する機能「prop」についてご紹介します。

2014年10月27日月曜日

【JsRender】for文

株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。

現在はJavaScriptによる画面レンダリングツール「JsRender」について連載しています。
今回はif文に続きロジックの基本、for文です。

for文ではないもの

まず前置きですが、今までの例で使用してきましたように、
以下のようにJsRenderに配列を流し込みますと、それはループで処理されます。

<script id="jsRenderTmpl" type="text/x-jsrender">
<div>
{{:name}}
</div>
</script>

<script>
var data = [
{"name": "碇シンジ",sex:"male"},
{"name": "綾波レイ",sex:"female"},
{"name": "ゼルエル",sex:"unknown"}
];

var template = $.templates("#jsRenderTmpl");

var htmlOutput = template.render(data);

$("#result").html(htmlOutput);
</script>

ただ、これだと本当に何の芸も無いループに過ぎませんからね。
例えばループの中に更にループを持たせたいとか、ループとは別に通信の成功コードを持たせたいとか、ループ単品ではなくてヘッダー情報とセットでJSONを扱うとか、現実的なコード設計を考えますと、配列ではとても対応出来ません。

配列ダイレクトの使用は、まあ単なる動作確認程度の話。
実際の実装時は、仮に配列で十分なシチュエーションであったとしても、全実装をキッチリfor文型に統一して粒度を合わせた方が綺麗な実装になると思います。

for文

では、さっそく本題のfor文に入りましょう。

上のソースに近い状態でfor文構成にしますと、以下のようなサンプルになります。

<script id="jsRenderTmpl" type="text/x-jsrender">
★{{:title}}
{{for members}}
<div>
・{{:name}}
</div>
{{/for}}
</script>

<script>
var data = {
  "title": "for文サンプル一覧",
  "members": [
      {"name": "碇シンジ",sex:"male"},
      {"name": "綾波レイ",sex:"female"},
      {"name": "ゼルエル",sex:"unknown"}
 ]
};

var template = $.templates("#jsRenderTmpl");

var htmlOutput = template.render(data);

$("#result").html(htmlOutput);
</script>


「{{for members}}」「{{/for}}」でfor文になるわけです。

ちなみに、for文と言っても「for(var i=0;i<10;i++)」みたいな終了条件は設定出来ません。
流し込んだ配列を全件出力します。

「for(Map m : List<Map> list)」みたいな意味合いだと言えるでしょう。

if文との組み合わせ~偶数と奇数~

ここが一つの残念なお知らせなのですが、「偶数の行」「奇数の行」でテーブルの行を色分けする時に使うみたいな
for文の中でのその時の行数の読み分けする機能は存在しないのです。

この為、偶数/奇数を判断したい場合などは最初からJSONデータの中分岐に必要な情報を持たせておく必要があるわけです。

この場合、私だったら行数のカウントをJSONに持たせます。
そして、偶数/奇数の判断はJavaScriptの計算で実現します。

<script id="jsRenderTmpl" type="text/x-jsrender">
★{{:title}}
{{for members}}
<div>
・No.{{:no}}:{{:name}}:
{{if no % 2 == 0}}
  偶数行
{{else}}
  奇数行
{{/if}}
</div>
{{/for}}
</script>

<script>
var data = {
  "title": "for文サンプル一覧・if文と組みわせ",
  "members": [
      {no:"0","name": "あああああ"},
      {no:"1","name": "いいいいい"},
      {no:"2","name": "ううううう"},
      {no:"3","name": "えええええ"},
      {no:"4","name": "おおおおお"}
 ]
};

var template = $.templates("#jsRenderTmpl");

var htmlOutput = template.render(data);

$("#result").html(htmlOutput);
</script>


これで偶数行/奇数行の判断が出来ました。
後はスタイルシートの記述等を入れてしまえば色分けも完了です。

if文の説明になってしまいますが、このように「{{if no % 2 == 0}}」みたいな計算判定も出来ます。

こうやって簡易的なロジックも織り交ぜて実現していくのが現実的な実装と言えるでしょう。

終わりに

今回で「if文」と「for文」の使い方が分かりました。
ハッキリ言って、これだけ分かっていれば十分!!

基本的にテンプレートはシンプルに定義して、複雑な設定が必要な場合はAjax通信先のサーバ側など
別の所で頑張るべきですから……。

しかし、JsRenderには他にも便利機能がありますので、
次回以降はそれらについてご紹介していきたいと思います。

2014年10月8日水曜日

【JsRender】if文

株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。

現在はJavaScriptによる画面レンダリングツール「JsRender」について連載しています。
今回はロジックの基本中の基本、if文です。

if文(文字列一致)

「if」「else if」「else」は言語の基本中の基本かと思いますが、実は意外に不便することがあります。

例えばjspタグ。

「ifがあってもelseが無い」

elseを実現したい場合はif文ではなくて「when」とかを使わなければならないのですが、
それを知らないプログラマーが「ありゃ。elseは無いんだ。ならifだけで頑張ろう」とかってifだけで強引に書こうとしてグダグダのソースになる悲劇が多発しています。(泣)

今回は基本中の基本であるif文をチェックしていきましょう。

まずは基本から。
メンバーの一覧の性別をチェックして、男性か女性かチェックする機能を作ってみます。

それがこちら。

<div id="result"></div>

<script id="jsRenderTmpl" type="text/x-jsrender">
<div>
{{:name}}は
{{if sex == "male"}}
  男性
{{else sex == "female"}}
  女性
{{else}}
  性別不明
{{/if}}
です。
</div>
</script>

<script>
var data = [
{"name": "碇シンジ",sex:"male"},
{"name": "綾波レイ",sex:"female"},
{"name": "ゼルエル",sex:"unknown"}
];

var template = $.templates("#jsRenderTmpl");

var htmlOutput = template.render(data);

$("#result").html(htmlOutput);
</script>

この結果として、以下のように表示されます。



つまり、代表的なif-elseの構えで分岐が実現出来るわけですね。
whenとか使わなくて済みます。
分かり易くて助かりますね。

  • {{if sex == "male"}}
  • {{else sex == "female"}}
  • {{else}}
  • {{/if}}


if文(数値一致)

上は「{{if sex == "male"}}」と文字列一致で行いましたが、数字ならどうでしょう?

それもOKです。

普通に「{{if sex == 0}}」とでも書いて下さい。

<script id="jsRenderTmpl" type="text/x-jsrender">
<div>
{{:name}}は
{{if sex == 0}}
  男性
{{else sex == 1}}
  女性
{{else}}
  性別不明
{{/if}}
です。
</div>
</script>

<script>
var data = [
{"name": "碇シンジ",sex: 0},
{"name": "綾波レイ",sex: 1},
{"name": "ゼルエル",sex: 2}
];

var template = $.templates("#jsRenderTmpl");

var htmlOutput = template.render(data);

$("#result").html(htmlOutput);
</script>

ちなみに、JavaScriptは型の検証がいい加減ですから、


  • {{if sex == 0}}
  • {{if sex == "0"}}


このようにダブルクォート(")で括ろうと括るまいと同じように処理されます。

if文(数値大小比較)

では、数値の大小比較はどうでしょう?

これも普通に「<」「>」が通用します。

<script id="jsRenderTmpl" type="text/x-jsrender">
<div>
{{:name}}は
{{if 10 <= age && age <20 }}
  10台
{{else 20 <= age && age <30}}
  20台
{{else}}
  それ以外
{{/if}}
です。
</div>
</script>

<script>
var data = [
{"name": "碇シンジ",age: 14},
{"name": "綾波レイ",age: 29},
{"name": "ゼルエル",age: -1}
];

var template = $.templates("#jsRenderTmpl");

var htmlOutput = template.render(data);

$("#result").html(htmlOutput);
</script>

合わせて「AND条件は &&」、「OR条件は || 」で実現可能であることが分かりました。

boolean

ここまで来ると、どうやら直感で使うような普通の機能は全部備わっているということが分かってきました。
一応、「true」「false」といったboolean型の動作も確認してみましたが、こちらも何ら問題は起きないようです。

<script id="jsRenderTmpl" type="text/x-jsrender">
<div>
{{if flg}}
  {{:name}}
{{/if}}
</div>
</script>

<script>
var data = [
{"name": "碇シンジ",flg: true},
{"name": "綾波レイ",flg: false},
{"name": "ゼルエル",flg: true}
];

var template = $.templates("#jsRenderTmpl");

var htmlOutput = template.render(data);

$("#result").html(htmlOutput);
</script>


ロジック入り

極め付けはコレ。

if文の中にJavaScriptのロジックを入れてしまうという。

<script id="jsRenderTmpl" type="text/x-jsrender">
<div>
{{:name}}は
{{if age.substr(0,1) == 1 }}
  10台
{{else age.substr(0,1) == 2}}
  20台
{{else}}
  それ以外
{{/if}}
です。
</div>
</script>

<script>
var data = [
{"name": "碇シンジ",age: "14"},
{"name": "葛城ミサト",age: "29"},
{"name": "ゼルエル",age: "-1"}
];

var template = $.templates("#jsRenderTmpl");

var htmlOutput = template.render(data);

$("#result").html(htmlOutput);
</script>

「{{if age.substr(0,1) == 1 }}」みたいな記述も可能。
要するに、JavaScriptの機能がそのまま動くように作られているわけです。

ただし、JsRenderのif文にこういうロジックが入ってしまうとソースが複雑化してしまいます。

分岐が必要な場合はシンプルに記述出来るようJSON定義の設計を見直すことをオススメしますが、
諸々の事情で出来ない場合等は、こういう小技で乗り切るのもエンジニアの現場判断と言えるでしょう。

終わりに

次回は同じく基本中の基本、「for文」の書き方をご紹介します。

2014年10月3日金曜日

【JsRender】JSON定義

株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。

現在はJavaScriptによる画面レンダリングツール「JsRender」について連載しています。
今回のテーマはJSONです。

JSONデータ定義

さて、前回は単純な「ただ文字列を表示するだけ」という基本についてご紹介しました。

ここからif文やfor文など様々な機能に行きたいわけですが、その前にJSONの定義方法について検証したいと思います。

シンプル

一番シンプルなのが前回のこれ。

Scrpit

<script id="jsRenderTmpl" type="text/x-jsrender">
私の名前は{{:name}}です。
</script>

JSON

var data = {"name": "遠藤 太志郎"};

これで「私の名前は遠藤 太志郎です。」になります。

配列

次に配列に行ってみます。

Scrpit

<script id="jsRenderTmpl" type="text/x-jsrender">
<div>
私の名前は{{:name}}です。
<div>
</script>

JSON

var data = [
{"name": "遠藤 太志郎"},
{"name": "えんどう たしろう"},
{"name": "エンドウ タシロウ"}
];

結果がこちら。



ふ~む……。
どうやら導入データが配列になっていると、自動的にループでやってくれるようですね。

でもこれ、本当に単純なデータをベロベロ出すだけなら良いけど、
例えばゼロ件の時はメッセージを出すとか、僅かでも工夫が必要になると途端にデータ定義が不便になっちまうんですよ。

単純配列の出番は本当にシンプルな場合のみです。
まあ、配列にはこういう機能があるとだけ覚えておけば良いでしょう。


入れ子

JSON定義ってオブジェクト指向的な性質を持っていますから、JavaのクラスをJSONに置き換えるようなイメージで
定義することもできます。

こんなようなクラスがあるとしますと、

public class Person {

    /** 名前 */
    private String name;

    /** 年齢 */
    private int age;

}

JSONで書けばこうなります。

var data = [
var data = {person:{"name": "遠藤 太志郎",age:28}};
];

この場合、テンプレートはこうやって書く。

<script id="jsRenderTmpl" type="text/x-jsrender">
私の名前は{{:person.name}}です。年齢は{{:person.age}}です。
</script>

「.(ドット)」で連結すれば、JSONの階層構造を掘り進んで読んでくれるわけです。
これがJsRenderの良い所で、JavaでBEAN定義したクラスを丸ごとJSON化して叩き込むことが出来ますので、ロジックが非常に楽になるのです。
JavaScriptの機能がそのまま踏襲されています。

配列番号指定

次は「入れ子と配列の合体で番号指定」です。

以下みたいに入れ子構造の先が配列になっている場合です。

var data = {person:{"name": ["遠藤","太志郎"],age:28}};

nameの属性に「苗字」と「名前」が別々に入っていますね。
こんなデータ構造になってしまうのは余り良いサンプルとは言えませんが、
仮に「firstname」「familyname」と別々のフィールドに定義しますと、それだけでJSONもデータ量が増えてしまいます。

「転送データ量削減の為に定義を省略する」など、諸々の事情で配列でやらなきゃならないタイミングもあります。

こういう状況で、「配列のゼロ番目に入っている苗字部分だけを取り出したい」という需要があるとします。
その場合はこうやって記述すればOKです。

<script id="jsRenderTmpl" type="text/x-jsrender">
私の苗字は{{:person.name[0]}}です。年齢は{{:person.age}}です。
</script>

[0]で順番指定出来るわけですね。
痒い所まで手が届く便利設計になっています。

ちなみに「苗字+名前」としたい場合は「{{:person.name[0]}}{{:person.name[1]}}」と
単に続けて書けばOKです。

文字番号指定
最後に小ネタを。

JsRenderって、「文字列の何番目だけを出したい」という文字番号指定機能があるのです。

JSONデータをこれとします。

var data = [
var data = {person:{"name": "遠藤 太志郎",age:28}};
];

そしてこう書くと。

<script id="jsRenderTmpl" type="text/x-jsrender">
私の苗字は{{:person.name[0]}}{{:person.name[1]}}です。年齢は{{:person.age}}です。
</script>

これでもちゃんと「遠藤」ってなります。


  • {{:person.name[0]}}=遠
  • {{:person.name[1]}}=藤


この辺りもJsRenderの機能と言うより、JavaScriptの仕様なんですけどね。

JavaScriptには偶に変わった仕様が入っていることがあるのです。
配列と見間違えてバグの温床を化すのがオチなような仕様ですけれども、
テクニシャンな人は使ってみると良いでしょう。

終わりに

以上でデータ定義編は終わりです。
JavaScriptの標準に乗っ取った、直感的に理解出来る定義方法になっていると思います。

次回もJsRenderは続きます。

2014年9月30日火曜日

【JsRender】基本表示機能

株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。

本日よりJavaScriptによる画面レンダリングツール「JsRender」について本格的に連載を開始します。
最初の今日は導入編です。

ダウンロード

さて、まずは必要なJSファイルをゲットする所から始まります。

「JsRender」は単体でも機能するライブラリのようですが、普通はjQueryと組み合わせて使うものかと思います。
なので、本連載ではjQueryも併用することを前提で進めてまいります。

それぞれ、ダウンロード元は以下になりますので、各自ダウンロードして下さい。




取得したら、普通にHTMLのヘッダー部分でインポートしてあげればOK。
簡単ですね。

<head>
  <script src="./js/jquery-1.11.1.js"></script>
  <script src="./js/jsrender.js"></script>
</head>

表示箇所を定義

次に、HTML上のどこにJsRenderの結果を出力したいのかどうかを意味する場所を定義します。

DIVタグでIDを記述すれば良いでしょう。

<div id="result"></div>

「id="result"」と定義しました。この場所にJsRenderを使って文字列を流し込みます。

ちなみに、これはHTMLを作成する上では常識ですが「ID」とは画面上で一意にするのがルールです。

HTMLはいい加減な言語なので、IDが重複しようがタグを閉じ忘れようが、かなりテキトーに書いても
そこそこちゃんと表示されてしまいます。

しかし、本件の処理は「JavaScript」ですから、こっちはそういい加減に書くわけにはいきません。
ID属性は常に一意。
その他、可能な限りHTMLの記述ルールを守って実装して頂けますよう、お願い致します。

テンプレートを定義

では、この辺りからJsRenderならではの要素に入ります。
テンプレート定義です。

例えば、「私の名前は○○です。」という文章を表示したいと思います。
この○○の部分だけは動的に変更して、それ以外は固定値、というテンプレートにしたい。
そのテンプレートが以下になります。

<script id="jsRenderTmpl" type="text/x-jsrender">
私の名前は{{:name}}です。
</script>

これでもう何となくお察し頂けたかと思いますが、「{{:name}}」で、「画面上に文字を記述する」という
意味を持つJsRenderの定義なのです。

Strutsで言う所の以下みたい記述ものです。

<bean:write name="usrdata" property="name" />

もう一つの特徴が「type」です。普通であれば「type="text/javascript"」と書くところ、
JsRenderの場合は「type="text/x-jsrender"」となります。

「このスクリプトはJsRenderの記述だ」と宣言しているわけですね。

これにより、


  • scrpitタグで括っているのでHTMLには表示されない。
  • 「type="text/x-jsrender"」なので、JavaScriptとは認識されない。


この特性が得られて、純粋な外部定義のように扱うことが出来るのです。


JsRenderを実行
さて、上記でテンプレート定義が出来ました。
後はJavaScriptとしてJsRenderを実行するのみです。

そのスクリプトはこちら。

<script>
var data = {"name": "遠藤 太志郎"};

var template = $.templates("#theTmpl");

var htmlOutput = template.render(data);

$("#result").html(htmlOutput);
</script>

まず最初にJSONを読み込みます。

「var data = {"name": "遠藤 太志郎"};」

ここではサンプルなのでJSONは固定値ですが、本番ではこのJSONを非同期通信により
サーバから動的に持ってくることになります。
キー値としましては、上記のテンプレートと合わせて「name」としました。

JSONはAjaxとは切っても切れない基本要技術です。
ご存じ無い方はぜひ習得して下さい。

次に、テンプレートを読み込みます。

「var template = $.templates("#jsRenderTmpl");」

これはJsRender独自の記述ですね。
「type="text/x-jsrender"」のID「jsRenderTmpl」を指定してテンプレートを読み込みます。

そして次に、テンプレートとJSON定義を合体させて、描画する文字列を作成。
ここもJsRenderの機能です。

「var htmlOutput = template.render(data);」

最後に、jQueryの機能で描画して終わり。

「$("#result").html(htmlOutput);」

なので、JsRenderは描画する文字列を出力する機能に絞っており、
それを描画する機能はjQueryの標準機能で行うという関係にあるわけです。

機能毎の独立性が担保された良い設計だと思います。

ほら、簡単に表示されました。


まとめると以下のようなソースになっています。

<!DOCTYPE html>

<html>
<head>
  <script src="./js/jquery-1.11.1.js"></script>
  <script src="./js/jsrender.js"></script>
</head>
<body>

<div id="result"></div>

<script id="jsRenderTmpl" type="text/x-jsrender">
私の名前は{{:name}}です。
</script>

<script>
var data = {"name": "遠藤 太志郎"};

var template = $.templates("#jsRenderTmpl");

var htmlOutput = template.render(data);

$("#result").html(htmlOutput);
</script>

</body>
</html>

どってことは無い簡単なスクリプトで実現可能であることがお分かり頂けるでしょう。

終わりに

以上で、基本の基本。
「ただ描写するだけ」という機能についてのご紹介は終わりです。

ハッキリ言って、JsRenderが無くても描画は出来るって言えば出来るんですが、
「type="text/x-jsrender"」によって外部定義することにより、
ロジックとテンプレートを独立させることが出来るようになっています。

これはソースの可読性を高める為には大変効果的です。すばらしい!!

次回から順次、if文やfor文などの機能についてもご紹介していきます。

2014年9月17日水曜日

【JsRender】始めに

株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。

ここ最近は、クラウド基盤「Google App Engine(以下、GAE)」の連載していますが、
本日からは少し趣向を変えてAjax関連のお話に行こうと思います。

jsp禁止

さて、なぜ急にGAEからAjaxに話が触れたかと言いますと、こちらの回でご紹介しましたとおり、GAEというのはフルAjaxで開発するのがベストなのです。

jspを使うと画面がホワイトアウトしている時間が発生してしまいますからね。
まあ、機能を果たすという意味ではjspを使っても良いんですけど、やっぱり何秒もホワイトアウトしているのは心象が悪いでしょう。
私は断固としてAjaxを推したいと思います。

しかしですね、jspが使えないとなると、一体どうやって画面上の分岐を表現すれば良いのでしょう?
例えば、「検索結果がある時は一覧を表示する。無い時は赤文字でエラーメッセージを表示する」とか。

jspが使えればifタグで一発なのですが、使えないとなるとこれは厳しい。

そこをAjaxを使って動的に……。
って、もちろんやろうと思えば自前でAjaxを作って実現出来ますけれども、その度にロジックを組むのは効率悪過ぎです。

jspと比較しての生産性の低下が深刻です……。

そこで私が考えたのが、「AJaxでjspみたいなことが出来る便利なライブラリは無いの?」でした。
そう、Ajaxによるテンプレートエンジンです。

テンプレートエンジン

さて、Ajaxで困った時はjQueryに限ります。

十年ほど前ははAjaxライブラリが群雄割拠していましたが、今はjQueryが支配的になりました。
「何かAjaxで良い機能無いかな?」と思った時は、とりあえずjQueryから着手するのが一番効率的です。

そして私が探した所、ありました!!


  • jQuery Template


まさに期待通り、jspタグみたいな機能をAjaxでやる為のjQuery公式プラグインです。
jQuery公式なら安心ですね。早速導入を、と思いきや。

何と開発停止。(泣)




作り始めたは良いものの、途中で方針を変更して、まだ諦めずに頑張ると言いつつも、そのうち頓挫したというオチのようですね……。

残念な限りですが、その代わりに台頭してきたのが「JsRender」です。


JsRender

JsRenderはjQuery公式ではありませんが、jQuery Templateの後継のようなポジションにあるライブラリです。
公式サイトはこちらです。


公式サイトに解説も沢山載っていますので習得も捗ります。

フライングになりますが、例として『検索結果一覧の表示』のサンプルをご紹介すると、以下になります。

まず、HTMLにテンプレートとなるタグを書いて、

<script id="shohinListTemplate" type="text/x-jsrender">

<table class="shohinList">
 <tr>
  <th class="no">NO</th>
  <th class="shohinId">商品ID</th>
  <th class="shohinName">商品名</th>
  <th class="action"></th>
 </tr>
 {{for shohinList}}
 <tr>
  <td class="no">{{>seqNo}}</td>
  <td class="shohinId">{{>shohinId}}</td>
  <td class="shohinName">{{>shohinName}}</td>
  <td class="action">詳細 編集</td>
 </tr>
 {{/for}}
</table>

</script>

後はJavaScript部に「$("#shohinList").html($("#shohinListTemplate").render(json));」を一発書くだけでOK。
(json変数にはもちろんjsonのデータが入ります)

「{{for shohinList}}」を見ただけでも、何となくfor文でループしていることがお分かりになるでしょう。
直感的に使いやすい良いデザインのライブラリですね。

終わりに

このJsRender作戦はGAEに限ったことではありません。
私は別業務でAndroidの開発も行った事があるのですが、その時に「HTML5アプリ」と「ネイティブアプリ」の良い所取りをする「ハイブリット型」の設計を採用しました。

その時に、ネイティブ機能で整形したデータをHTMLに表示する時に使ったのも、この「JsRender」でした。

とても使い勝手の良いライブラリなのでぜひオススメです。

次回から各種機能について順次ご紹介していきます。