Do You PHP はてな このページをアンテナに追加 RSSフィード Twitter

2015-03-27

[]JsViewsチュートリアル - データリンクされたオブジェクトを操作する

JavaScript製でjQuery非依存なテンプレートエンジンであるJsRender/JsViewsを使ったチュートリアルを書いてみようと思います。

以前に書いたエントリJsRender入門 - Do You PHP はてなも参照してください。

今回やること

JsViewsでデータリンクされたオブジェクトに対して更新・削除などの操作をする

コード

<html>
<body>

<!-- レンダリング結果を表示するスペース -->
<div id="result"></div>

<a href="#" id="add">add</a>
<a href="#" id="modify">modify</a>
<a href="#" id="reset">reset</a>

<script src="https://code.jquery.com/jquery-1.11.1.min.js" type="text/javascript"></script>
<script src="http://www.jsviews.com/download/jsviews.min.js" type="text/javascript"></script>
<script type="text/javascript">
// オブジェクトの操作
$(function() {
    // 表示するデータ(オブジェクト)
    var fruits = { name: "りんご", num: 3 };

    // テンプレートに名前をつけて登録する
    // linkPropsTemplateはデータリンクしたpropsタグを使ったテンプレート
    $.templates({
        linkTemplate: "#template"
    });

    // テンプレート"linkTemplate"と変数fruitsをリンク
    $.link.linkTemplate('#result', fruits);

    $(document)
        /**
         * "add"をクリックすると、オブジェクトに新しいプロパティを
         * 追加して再レンダリング
         */
        .on('click', '#add', function(ev) {
            $.observable(fruits).setProperty('color', 'green');
            ev.preventDefault();
        })
        /**
         * "modify"をクリックすると、既存のプロパティを更新して
         * 再レンダリング
         */
        .on('click', '#modify', function(ev) {
            if (fruits.name) {
                $.observable(fruits).setProperty('name', 'ドリアン');
            }
            ev.preventDefault();
        })
        /**
         * "remove"をクリックすると、プロパティを削除して
         * 再レンダリング
         */
        .on('click', '.remove', function(ev) {
            // removePropertyはドキュメント化されていないメソッド
            $.observable(fruits).removeProperty(
                // clickイベントが発生したViewオブジェクトを取得し、
                // そのデータのキーを取得する
                $.view(this).data.key
            );
            ev.preventDefault();
        })
        /**
         * "reset"をクリックすると、既存のプロパティを更新して
         * 再レンダリング
         */
        .on('click', '#reset', function(ev) {
            if (fruits.color) {
                $.observable(fruits).removeProperty('color');
            }
            $.observable(fruits).setProperty({
                name: "りんご",
                num: 3
            });
            ev.preventDefault();
        });
});
</script>

<!-- テンプレート -->
<script id="template" type="text/x-jsrender">
{^{props #data}}
    <p>{^{>key}}の値は{^{:prop}}です <a href="#" class="remove">×</a></p>
{{/props}}
</script>
</body>
</html>

説明

前回は配列の操作でしたので、今回はリンクされたオブジェクトの操作の説明です。

JsViews(実際にはJsObservableという別ライブラリ)では、リンクされたオブジェクトについては、更新と削除の2つのメソッドが用意されています。

更新

オブジェクトプロパティを1つまたは複数同時に更新します。複数更新する場合は、オブジェクトとして渡します。

$.observable([データリンクしたオブジェクト]).setProperty([プロパティ名], [プロパティの値])
$.observable([データリンクしたオブジェクト]).setProperty({
    [プロパティ名1]: [プロパティの値1],
    [プロパティ名2]: [プロパティの値2],
          :
})

コード例では、"add"というリンクをクリックした時に、変数fruitsに"color"というプロパティを追加しています。

$.observable(fruits).setProperty('color', 'green');

また、"modify"というリンクをクリックした時には、nameプロパティの値を"ドリアン"に変更しています。

$.observable(fruits).setProperty('name', 'ドリアン');

もう一つ。"reset"というリンクをクリックした時には、name, numの各プロパティの値を同時に変更しています。

$.observable(fruits).setProperty({
    name: "りんご",
    num: 3
});
削除

公式サイトにドキュメント化されていませんが、プロパティを削除するメソッドも用意されています。

$.observable([データリンクしたオブジェクト]).removeProperty([プロパティ名])

コード例では、"×"というリンクをクリックした際に、当該プロパティを変数fruitsから削除しています。

$.observable(fruits).removeProperty(
    $.view(this).data.key
);

なお、該当するプロパティ名は、クリックされた要素を含むViewオブジェクトを取得し、そのデータから取得しています。

JSFiddleで動作を見る

参照

[]JsViewsチュートリアル - データリンクされた配列データを操作する

JavaScript製でjQuery非依存なテンプレートエンジンであるJsRender/JsViewsを使ったチュートリアルを書いてみようと思います。

以前に書いたエントリJsRender入門 - Do You PHP はてなも参照してください。

今回やること

JsViewsでデータリンクされた配列データに対して追加・削除などの操作をする

コード

<html>
<body>

<!-- レンダリング結果を表示するスペース -->
<div id="result_link"></div>
<hr/>
<div id="result_link_for"></div>

<a href="#" id="add">add</a>

<script src="https://code.jquery.com/jquery-1.11.1.min.js" type="text/javascript"></script>
<script src="http://www.jsviews.com/download/jsviews.min.js" type="text/javascript"></script>
<script type="text/javascript">
// 配列の操作
$(function() {
    // データの配列(もしくはオブジェクト)
    var fruits = [
        { name: "りんご", num: 3 },
        { name: "いちご", num: 5 },
        { name: "バナナ", num: 2 },
    ];

    // テンプレートに名前をつけて登録する
    // linkForTemplateはデータリンクしたforタグを使ったテンプレート
    $.templates({
        linkTemplate: "#template",
        linkForTemplate: "#template_for"
    });

    // テンプレート"linkTemplate"と変数fruitsをリンク
    $.link.linkTemplate('#result_link', fruits);
    $.link.linkForTemplate('#result_link_for', {fruits: fruits});

    $(document)
        /**
         * "add"をクリックすると、配列データに新しいデータを
         * 追加して再レンダリング
         */
        .on('click', '#add', function(ev) {
            // リンクされた配列データへの追加は$.observable().insert()
            $.observable(fruits).insert(
                { name: "ドリアン", num: fruits.length }
            );
            ev.preventDefault();
        })
        /**
         * "×"をクリックすると、配列データから当該データを
         * 削除して再レンダリング
         */
        .on('click', '.remove', function(ev) {
            // リンクされた配列データから削除は$.observable().remove()
            $.observable(fruits).remove(
                // clickイベントが発生したViewオブジェクトを取得し、
                // そのindexを取得する
                $.view(this).index
            );
            ev.preventDefault();
        });
});
</script>

<!-- テンプレート -->
<script id="template" type="text/x-jsrender">
    <p>{^{>#index}}:{{:name}}{{:num}}個あります <a href="#" class="remove">×</a></p>
</script>
<script id="template_for" type="text/x-jsrender">
{^{for fruits}}
    <p>{^{>#index}}:{{:name}}{{:num}}個あります <a href="#" class="remove">×</a></p>
{{/for}}
</script>
</body>
</html>

説明

前回までのチュートリアルでは、テキストボックスに値を入力することでデータリンクした値を更新していましたが、当然JavaScriptコード内からデータを更新したい場合もあります。

例えば配列データの場合、

fruits.push({ name: "ドリアン", num: 4 });

などとやっても、JsViewsにはデータが更新されたかどうか判断できません。逆に、リンクの情報を壊してしまう結果になります。JsViewsでは、配列オブジェクトを更新するための仕組みが提供されています(実際にはJsObservableという別ライブラリ)ので、これを使うことになります。配列データの更新については、追加・削除・移動・全更新の4つが用意されています。

追加

配列データの任意の場所、もしくは最後にデータを追加します。

$.observable([データリンクした配列データ]).insert([追加するデータの位置], [追加するデータ])

追加するデータの位置は配列の添字(0始まり)です。省略可能でその場合は最後に追加されます。

コード例では、"add"というリンクをクリックした際に、変数fruitsの最後にオブジェクトを追加しています。

$.observable(fruits).insert({ name: "ドリアン", num: fruits.length });
削除

配列データの任意の場所のデータを削除します。

$.observable([データリンクした配列データ]).remove([削除するデータの位置], [削除するデータの数])

削除するデータの位置は配列の添字(0始まり)で、削除した位置より後ろのデータは前に詰められます。削除するデータ数は省略した場合は1となります。

コード例では、"×"というリンクをクリックした際に、当該データを変数fruitsから削除しています。

$.observable(fruits).remove($.view(this).index);
移動

配列データの任意の場所のデータを任意の場所に移動します。

$.observable([データリンクした配列データ]).move([移動するデータの位置], [移動先の位置], [移動するデータの数])

移動するデータの位置と移動先の位置は配列の添字(0始まり)です。移動するデータの数を省略した場合は1となります。

全更新

配列データをすべて入れ替えます。

$.observable([データリンクした配列データ]).refresh([新しい配列データ])

JSFiddleで動作を見る

参照

[]JsViewsチュートリアル - タグをデータリンクさせる

JavaScript製でjQuery非依存なテンプレートエンジンであるJsRender/JsViewsを使ったチュートリアルを書いてみようと思います。

以前に書いたエントリJsRender入門 - Do You PHP はてなも参照してください。

今回やること

JsViewsでタグをデータリンクさせた場合の動作を確認する

コード

<html>
<body>

<!-- レンダリング結果を表示するスペース -->
<p>テキストボックスに入力すると表示されたデータが更新される</p>
<div id="result"></div>

<script src="https://code.jquery.com/jquery-1.11.1.min.js" type="text/javascript"></script>
<script src="http://www.jsviews.com/download/jsviews.min.js" type="text/javascript"></script>
<script type="text/javascript">
// タグのリンク
$(function() {
    // 表示するデータ
    var message = {
        greet: 'Hello !'
    };

    // テンプレートに名前(ここでは"linkTemplate")をつけて登録する
    $.templates({
        linkTemplate: "#template"
    });

    // テンプレート"linkTemplate"と変数greetをリンク
//    $.templates('#template').link('#result', message);
    $.link.linkTemplate('#result', message);
});
</script>

<!-- テンプレート -->
<script id="template" type="text/x-jsrender">
    <div>
        <p>タグにキャレットなし</p>
        <p>{{if greet != 'Hello'}}{^{>greet}}{{/if}}</p>
    </div>
    <div>
        <p>タグにキャレットあり</p>
        {{!-- タグに"^"(キャレット/サーカムフレックス)が付いていることに注意 --}}
        <p>{^{if greet != 'Hello'}}{^{>greet}}{{/if}}</p>
        <div><input type="text" data-link="greet trigger=true"/></div>
    </div>
</script>
</body>
</html>

説明

先日のチュートリアルでは、値を表示する場合に"^"(キャレット/サーカムフレックス)を付けるパターンが出てきましたが、これはifやforなどのタグにも使えます

書式は値の場合と同様で、

{^{[タグ名] ... }} ... {{/[タグ名]}}

のようになります。具体的には

{^{if ... }}
    :
{{/if}}

といった具合です。

こうすると、データが更新された場合にタグも再評価され、入力フォームなどに入力された値と連動させることができるようになります。

コード例では、テキストボックスに入力した値が"Hello"と一致した場合は表示しない、というものです。その他の値の場合は、先日のチュートリアルと同様に表示されます。

JSFiddleで動作を見る

参照

2015-03-24

[]JsRenderチュートリアル - for、propsタグとelseタグ

JavaScript製でjQuery非依存なテンプレートエンジンであるJsRender/JsViewsを使ったチュートリアルを書いてみようと思います。

以前に書いたエントリJsRender入門 - Do You PHP はてなも参照してください。

今回やること

テンプレート内のfor、propsタグとelseタグを組み合わせて使ってみる

コード

<html>
<body>

<!-- レンダリング結果を表示するスペース -->
<div id="result"></div>

<script src="https://code.jquery.com/jquery-1.11.1.min.js" type="text/javascript"></script>
<script src="http://www.jsviews.com/download/jsviews.min.js" type="text/javascript"></script>
<script type="text/javascript">
// for、propsタグとelseタグ
$(function() {
    // 表示するデータ
    var data = [
        {
            color: "赤",
            fruits: [
                { name: "りんご", num: 3 },
                { name: "いちご", num: 5 },
                {}
            ]
        },
        {
            color: "緑",
        },
        {
            color: "黄",
            fruits: [
                { name: "バナナ", num: 2 }
            ]
        }
    ];

    // テンプレートに名前(ここでは"linkTemplate")をつけて登録する
    $.templates({
        linkTemplate: "#template"
    });

    // テンプレート"linkTemplate"に変数dataを渡し、
    // レンダリング結果を表示
    $("#result").html($.render.linkTemplate(data));
});
</script>

<!-- テンプレート -->
<script id="template" type="text/x-jsrender">
    {{for #data tmpl="#template_item"/}}
</script>
<script id="template_item" type="text/x-jsrender">
    <h3>{{>color}}色</h3>
    {{for fruits}}
        {{props #data}}
            <p>{{>key}}の値は{{>prop}}です</p>
        {{else}}
            空っぽです!
        {{/props}}
    {{else}}
        何もありません
    {{/for}}
</script>
</body>
</html>

説明

forタグやpropsタグ、カスタムタグはelseタグと組み合わせて使うことができます。データが存在しない場合のメッセージなど、elseタグ側に条件を満たさない場合の内容を記述します。

    {{for [配列]}}
        :
    {{else}}
        :
    {{/for}}

    {{props [オブジェクト]}}
        :
    {{else}}
        :
    {{/prop}}

JSFiddleで動作を見る

参照

[]JsRenderチュートリアル - if、for、propsタグで子テンプレートを読み込む

JavaScript製でjQuery非依存なテンプレートエンジンであるJsRender/JsViewsを使ったチュートリアルを書いてみようと思います。

以前に書いたエントリJsRender入門 - Do You PHP はてなも参照してください。

今回やること

テンプレート内のif、for、propsタグで子テンプレートを指定して値をレンダリングする

コード

<html>
<body>

<!-- レンダリング結果を表示するスペース -->
<div id="result"></div>

<script src="https://code.jquery.com/jquery-1.11.1.min.js" type="text/javascript"></script>
<script src="http://www.jsviews.com/download/jsviews.min.js" type="text/javascript"></script>
<script type="text/javascript">
// if、for、propsタグで子テンプレートを読み込む
$(function() {
    // 表示するデータ
    var data = {
        items: [
            { name: "りんご", num: 3 },
            { name: "いちご", num: 5 },
            { name: "バナナ", num: 2 }
        ],
        options: {
            library: "JsRender",
            language: "JavaScript"
        }
    };

    // テンプレートに名前(ここでは"linkTemplate")をつけて登録する
    $.templates({
        linkTemplate: "#template"
    });

    // テンプレート"linkTemplate"に変数dataを渡し、
    // レンダリング結果を表示
    $('#result').html($.render.linkTemplate(data));
});
</script>

<!-- テンプレート -->
<script id="template" type="text/x-jsrender">
{{for items tmpl="#template_for"/}}
{{props options tmpl="#template_props"/}}
</script>
<script id="template_for" type="text/x-jsrender">
    <p>{{:name}}{{:num}}個あります</p>
    {{if num < 3 tmpl="#template_if" /}}
</script>
<script id="template_if" type="text/x-jsrender">
    <p>{{:name}}はそろそろ少なくなってきました</p>
</script>
<script id="template_props" type="text/x-jsrender">
    <p>{{>prop}}の値は{{>key}}です</p>
</script>
</body>
</html>

説明

ifタグ(elseも含む)、forタグ、propsタグは、タグ中にデータをレンダリングするテンプレートを指定することができます。この場合、いずれもtmpl属性に続いてテンプレートへのセレクタ(もしくはテンプレート文字列)を指定します。

    {{if [条件式] tmpl="[テンプレートへのセレクタ]" /}}

    {{if [条件式] tmpl="[テンプレートへのセレクタ]"}}
         :
    {{else [条件式] tmpl="[テンプレートへのセレクタ]"}}
         :
    {{else tmpl="[テンプレートへのセレクタ]"}}
         :
    {{/if}}

    {{for [配列] tmpl="[テンプレートへのセレクタ]" /}}

    {{props [オブジェクト] tmpl="[テンプレートへのセレクタ]" /}}

JSFiddleで動作を見る

参照

[]JsViewsチュートリアル - まずはHello World

JavaScript製でjQuery非依存なテンプレートエンジンであるJsRender/JsViewsを使ったチュートリアルを書いてみようと思います。

以前に書いたエントリJsRender入門 - Do You PHP はてなも参照してください。

今回やること

JsViewsでテキストボックスに入力されたメッセージを表示する

コード

<html>
<body>

<!-- レンダリング結果を表示するスペース -->
<p>JsRender</p>
<p>テキストボックスに入力しても表示されたデータは更新されない</p>
<div id="result_render"></div>
<p>JsViews</p>
<p>テキストボックスに入力すると表示されたデータが更新される</p>
<div id="result_link"></div>

<script src="https://code.jquery.com/jquery-1.11.1.min.js" type="text/javascript"></script>
<script src="http://www.jsviews.com/download/jsviews.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(function() {
    // 表示するデータ
    var message = {
        greet: 'Hello !'
    };

    // テンプレートに名前(ここでは"linkTemplate")をつけて登録する
    $.templates({
        linkTemplate: "#template"
    });

    // テンプレート"linkTemplate"に変数greetを渡し、
    // レンダリング結果を表示
    $('#result_render').html($.render.linkTemplate(message));

    // テンプレート"linkTemplate"と変数greetをリンク
    $.link.linkTemplate('#result_link', message);
});
</script>

<!-- テンプレート -->
<script id="template" type="text/x-jsrender">
    {{!-- "^"(キャレット/サーカムフレックス)が付いていることに注意 --}}
    <p>{^{>greet}}</p>

    <div>
        <p>triggerなし</p>
        {{!-- data-link属性に注目! --}}
        <input type="text" data-link="greet"/>
    </div>

    <div>
        <p>trigger=true</p>
        {{!-- data-link属性の"trigger=true"に注目! --}}
        <input type="text" data-link="greet trigger=true"/>
    </div>
</script>
</body>
</html>

説明

JsViewsは単純なテンプレートエンジンではなく、

テンプレートに渡した値と表示された値が同期(リンク)されている

という特徴があります。

上のコード例は、テンプレートとリンクさせた変数をテキストボックスの値とし、その値を表示させるサンプルになります。JSFiddleで動作を見ると、

  • テキストボックスの値を変更してフォーカスを外す(blur)
  • テキストボックスの値を変更したタイミング

と表示されている値が変わる2種類があることが確認できると思います。

JsViewsを使用する際の基本的な流れはJsRenderの流れと似ており、以下のようになります。

1. JsViewsファイルを読み込む

ここはJsRenderの時と同じです。

2. テンプレートを用意する

基本的にはJsRenderと同じなのですが、well-formedである必要があります。ここで言うwell-formedとは、

HTML要素だけがwell-formedと言うわけではなく、HTML要素とテンプレートのタグの組み合わせでwell-formed

ということです。したがって、JsViewsのテンプレートでは、属性の値にifタグなどを使うことはできません。この場合、別途用意された方法を使用する必要があります。

さて、リンクされたデータを表示する方法についてですが、大きく2種類あります。

1つ目はJsRenderで使っていた書式に"^"(キャレット/サーカムフレックス)が付くようになります。例えば、上のコード例でgreetという変数を表示する場合、

{^{>greet}}

と記述します。

もう1つは、HTMLタグに"data-link"という特別な属性をつけることで、そのタグの値を変数の値にする、というものです。コード例では以下のように記述しています。

    <input type="text" data-link="greet">

ここではとりあえず、フォーム要素(inputタグやselectタグなど)の場合はdata-link属性の値に変数名を指定すると値がリンクされる、と覚えておいてください。

また、data-link属性の値に変数名の他に"trigger=true"を指定すると、入力したタイミングでデータが更新されるようになります。

    <input type="text" data-link="greet trigger=true">
3. JavaScript内で表示したい値を用意する

コード例では、比較のために

としています。

4. JsViewsが提供しているlinkメソッド引数としてリンクさせたい変数を渡してテンプレートとリンクする

JavaScriptコード内にある

    $.link.linkTemplate('#result_link', message);

がこれに相当します。いきなり名前付きテンプレートを使っていますが、名前付きテンプレートを使わない場合は

    $.templates([テンプレートへのセレクタ]).link([表示スペースへのセレクタ], [リンクする変数]);

のようになります。具体的には

    $.templates('#template').link('#result_link', message);

となります。

JSFiddleで動作を見る

参照

[]JsRenderチュートリアル - テンプレートヘルパーを渡す

JavaScript製でjQuery非依存なテンプレートエンジンであるJsRender/JsViewsを使ったチュートリアルを書いてみようと思います。

以前に書いたエントリJsRender入門 - Do You PHP はてなも参照してください。

今回やること

ヘルパーの定義と使い方の説明

コード

<html>
<body>

<!-- レンダリング結果を表示するスペース -->
<div id="result"></div>

<style type="text/css">
<!--
.blue { color: #3face0; }
.red { color: #e03fac; }
-->
</style>
<script src="https://code.jquery.com/jquery-1.11.1.min.js" type="text/javascript"></script>
<script src="js/jsrender.min.js" type="text/javascript"></script>
<script type="text/javascript">
// ヘルパーの定義と使い方
$(function() {
    // 表示するデータ
    var items = [
        { name: "りんご", num: 3 },
        { name: "いちご", num: 5 },
        { name: "バナナ", num: 2, unit: '本' }
    ];

    // ヘルパーの定義
    var helper = {
        unit: function(data) {
            if (data.unit === undefined) {
                return 'こ';
            }

            return data.unit;
        },
        color: "blue"
    };

    // ヘルパーをJsRenderに登録する場合(1)
    //
    // ただし、render時にヘルパーが渡された場合、
    // 同名のメソッドやプロパティは上書きされる
    $.views.helpers({
        unit: function(data) {
            if (data.unit === undefined) {
                return '個';
            }

            return data.unit;
        },
        color: "red",
        greet: "こんにちは!"
    });

    // ヘルパーをJsRenderに登録する場合(2)
    //
    // $.views.helpersで登録した同名のヘルパーメソッド、プロパティは
    // 後勝ちとなる
    $.views.helpers("greet", "Hello !");


    // テンプレートに名前(ここでは"linkTemplate")をつけて登録する
    $.templates({
        linkTemplate: "#template"
    });

    // テンプレート"linkTemplate"に変数itemsとヘルパーを渡し、
    // レンダリング結果を表示
    $('#result').html($.render.linkTemplate(items, helper));
});
</script>

<!-- テンプレート -->
<script id="template" type="text/x-jsrender">
    <p>
        <span>{{>~greet}}</span>
        <span class="{{>~color}}">{{:name}}</span>が{{:num}}{{:~unit(#data)}}あります
    </p>
</script>
</body>
</html>

説明

JsRenderチュートリアル - テンプレートに渡したオブジェクトのメソッドを呼び出す - Do You PHP はてなではレンダリングする際にメソッドを含むデータをテンプレートに渡しましたが、JsRenderではヘルパーと呼ばれるオブジェクトを第2引数に渡すこともできます。

このヘルパーメソッドプロパティを定義しておくと、テンプレート内から呼び出し・参照することができます。

この場合、"~"(チルダ)を使ってメソッド名やプロパティ名を指定します。

~[メソッド名]([引数], ...)
~[プロパティ名]

また、ヘルパーをJsRender自身に登録することもできます。この場合の構文は以下のようになります。

$.views.helpers([ヘルパー名], [JavaScriptの関数やプロパティの値]);
  もしくは
$.views.helpers([プロパティやメソッドを含むオブジェクト]);

コード例ではJsRenderにヘルパーを2回登録し、またrender時にもヘルパーを渡していますが、この場合に同名のメソッドプロパティがあった場合は、それぞれ

render時に渡されたヘルパー > JsRenderに登録したヘルパー(2) > JsRenderに登録したヘルパー(1)

という具合に上書きされます。

JSFiddleで動作を見る

参照

2015-03-20

[]JsRenderチュートリアル - テンプレートに渡したオブジェクトメソッドを呼び出す

JavaScript製でjQuery非依存なテンプレートエンジンであるJsRender/JsViewsを使ったチュートリアルを書いてみようと思います。

以前に書いたエントリJsRender入門 - Do You PHP はてなも参照してください。

今回やること

テンプレートに渡したオブジェクトメソッドを呼び出す

コード

<html>
<body>

<!-- レンダリング結果を表示するスペース -->
<div id="result"></div>

<script src="https://code.jquery.com/jquery-1.11.1.min.js" type="text/javascript"></script>
<script src="http://www.jsviews.com/download/jsviews.min.js" type="text/javascript"></script>
<script type="text/javascript">
// 渡されたオブジェクトのメソッドを呼び出す
$(function() {
    var items = [
        { name: "りんご", num: 3 },
        { name: "いちご", num: 5 },
        { name: "バナナ", num: 2, unit: '本', getUnit: function() { return this.unit; } }
    ];

    // 表示するデータ
    var model = {
        items: items,
        unit: function(item) {
            if (item.unit === undefined) {
                return '個';
            }

            return item.unit;
        }
    };

    // テンプレートに名前(ここでは"linkTemplate")をつけて登録する
    $.templates({
        linkTemplate: "#template"
    });

    // テンプレート"linkTemplate"に変数modelを渡し、
    // レンダリング結果を表示
    $('#result').html($.render.linkTemplate(model));
});
</script>

<!-- テンプレート -->
<script id="template" type="text/x-jsrender">
{{for items}}
    <p>{{:name}}{{:num}}{{:~root.unit(#data)}}あります</p>
    {{if getUnit}}
        <p>{{:name}}{{:num}}{{:getUnit()}}あります</p>
    {{/if}}
{{/for}}
</script>
</body>
</html>

説明

テンプレートに渡されたオブジェクトメソッド呼び出しも変数と同様に行えます。

JSFiddleで動作を見る

参照

2015-03-19

[]JsRenderチュートリアル - テンプレートで使える特殊な変数とその中身

JavaScript製でjQuery非依存なテンプレートエンジンであるJsRender/JsViewsを使ったチュートリアルを書いてみようと思います。

以前に書いたエントリJsRender入門 - Do You PHP はてなも参照してください。

今回やること

テンプレートで使える特殊な変数とその中身を確認する

コード

<html>
<body>

<!-- レンダリング結果を表示するスペース -->
<div id="result"></div>

<script src="https://code.jquery.com/jquery-1.11.1.min.js" type="text/javascript"></script>
<script src="http://www.jsviews.com/download/jsviews.min.js" type="text/javascript"></script>
<script type="text/javascript">
// ハッシュ付き変数
$(function() {
    // デバッグ出力用タグの定義
    // 渡された値をconsole.logに出力するだけ
    $.views.tags({
        log: function(obj) {
            console.log('%cDebug', 'color: red;', obj);
        }
    });

    // 表示するデータ
    var fruits = {
        items: [
            { name: "りんご", num: 3 },
            { name: "いちご", num: 5 },
            { name: "バナナ", num: 2 }
        ]
    };

    // テンプレートに名前(ここでは"linkTemplate")をつけて登録する
    $.templates({
        linkTemplate: "#template"
    });

    // テンプレート"linkTemplate"に変数fruitsを渡し、
    // レンダリング結果を表示
    $('#result').html($.render.linkTemplate(fruits));
});
</script>

<!-- テンプレート -->
<script id="template" type="text/x-jsrender">
<p>ブラウザの開発ツール/デベロッパーツール、FireBugのコンソールタブを確認して下さい</p>

{{!-- このViewのオブジェクト --}}
{{log #view/}}

{{!-- このViewのオブジェクトの各プロパティ --}}
{{log #content/}}
{{log #ctx/}}
{{log #data/}}
{{log #linked/}}
{{log #parent/}}
{{log #tmpl/}}
{{log #type/}}
{{log #views/}}

{{for items}}
    <p>インデックス={{>#index}}</p>
    {{!-- このViewのオブジェクト --}}
    {{log #view/}}

    {{!-- このViewのオブジェクトの各プロパティ --}}
    {{log #content/}}
    {{log #ctx/}}
    {{log #data/}}
    {{log #index/}}
    {{log #linked/}}
    {{log #parent/}}
    {{log #tmpl/}}
    {{log #type/}}
    {{log #views/}}
{{/for}}

{{!-- 渡されたデータのトップレベル --}}
{{log ~root/}}
</script>
</body>
</html>

説明

JsRenderチュートリアル - ループ内のタグブロック内でインデックスが取得できない - Do You PHP はてなで作成したデバッグ用タグを使って、テンプレートで使える特殊な変数を確認してみます。

現在のテンプレート(Viewオブジェクト)は、テンプレート上では#viewとして参照できます。これを使ってデバッグ出力してみると、Viewオブジェクトの各プロパティが確認できると思いますが、これらのプロパティテンプレート上で

#[プロパティ名]

として直接参照することができます。

変数名概要
#contentテンプレートに渡されたコンテンツ
#ctxテンプレートコンテキスト
#dataテンプレートに割り当てられたデータ
#index現在のテンプレート配列の場合、そのインデックス
#linkedリンクされているかどうか
#parent現在のViewの親Viewオブジェクト
#tmplテンプレートに関する情報を格納したオブジェクト
#typeViewの種類
#views現在のViewにネストされた子Viewオブジェクト

最初のチュートリアルから「テンプレートに渡されたデータは#dataで参照できる」と書いてきましたが、実際はViewオブジェクトプロパティを参照していた、ということです。

また、JsRenderチュートリアル - テンプレートでループのインデックスを取得する - Do You PHP はてなで使った#indexも同様で、JsRenderチュートリアル - ループ内のタグブロック内でインデックスが取得できない - Do You PHP はてなで出てきた#getIndex()は#indexが取得できない場合のみ定義されるViewオブジェクトメソッドになります。

もう一つ、~rootという特殊な変数もあります。この変数はテンプレートに渡されたデータのトップレベルを表し、テンプレートのどの場所からでも使えます。

変数名概要
~rootテンプレートに渡されたデータのトップレベル

JSFiddleで動作を見る

参照

2015-03-18

[]JsRenderチュートリアル - 独自のタグを作る

JavaScript製でjQuery非依存なテンプレートエンジンであるJsRender/JsViewsを使ったチュートリアルを書いてみようと思います。

以前に書いたエントリJsRender入門 - Do You PHP はてなも参照してください。

今回やること

デバッグ出力用の独自タグを作る

コード

<html>
<body>

<!-- レンダリング結果を表示するスペース -->
<div id="result"></div>

<script src="https://code.jquery.com/jquery-1.11.1.min.js" type="text/javascript"></script>
<script src="http://www.jsviews.com/download/jsviews.min.js" type="text/javascript"></script>
<script type="text/javascript">
// カスタムタグ
$(function() {
    // デバッグ出力用タグの定義
    // 渡された値をconsole.logに出力するだけ
    $.views.tags("log", function(obj) {
        console.log('%cDebug', 'color: red;', obj);
    });

    // 表示するデータ
    var fruits = {
        items: [
            { name: "りんご", num: 3 },
            { name: "いちご", num: 5 },
            { name: "バナナ", num: 2 }
        ]
    };

    // テンプレートに名前(ここでは"linkTemplate")をつけて登録する
    $.templates({
        linkTemplate: "#template"
    });

    // テンプレート"linkTemplate"に変数fruitsを渡し、
    // レンダリング結果を表示
    $('#result').html($.render.linkTemplate(fruits));
});
</script>

<!-- テンプレート -->
<script id="template" type="text/x-jsrender">
<p>ブラウザの開発ツール/デベロッパーツール、FireBugのコンソールタブを確認して下さい</p>
{{log #data/}}
</script>
</body>
</html>

説明

JsRenderでは、独自のタグを追加することができます。基本的な構文は以下のようになります。

$.views.tags([タグ名], [JavaScriptの関数]);
  もしくは
$.views.tags([プロパティ名がタグ名、値がJavaScriptの関数のオブジェクト]);

コード例では、前者の書式で、渡された値をブラウザの開発ツールデベロッパーツールのコンソールにそのまま出力する"log"というタグを定義しています。

複数同時に登録する場合は、後者の書式で登録します。

    $.views.tags({
        log: function(obj) {
            console.log('%cDebug', 'color: red;', obj);
        },
        anotherTag: function(obj) {
            ...
        }
    });

JSFiddleで動作を見る

参照

[]JsRenderチュートリアル - ループ内のタグブロック内でインデックスが取得できない

JavaScript製でjQuery非依存なテンプレートエンジンであるJsRender/JsViewsを使ったチュートリアルを書いてみようと思います。

以前に書いたエントリJsRender入門 - Do You PHP はてなも参照してください。

今回やること

テンプレート内でループ内のタグブロック内でインデックスが取得できない場合の対処

コード

<html>
<body>

<!-- レンダリング結果を表示するスペース -->
<div id="result"></div>

<script src="https://code.jquery.com/jquery-1.11.1.min.js" type="text/javascript"></script>
<script src="http://www.jsviews.com/download/jsviews.min.js" type="text/javascript"></script>
<script type="text/javascript">
// ループ - forタグ
$(function() {
    // 表示するデータ
    var fruits = {
        items: [
            { name: "りんご", num: 3 },
            { name: "いちご", num: 5 },
            { name: "バナナ", num: 2 }
        ]
    };

    // テンプレートに名前(ここでは"linkTemplate")をつけて登録する
    $.templates({
        linkTemplate: "#template"
    });

    // テンプレート"linkTemplate"に変数fruitsを渡し、
    // レンダリング結果を表示
    $('#result').html($.render.linkTemplate(fruits));
});
</script>

<!-- テンプレート -->
<script id="template" type="text/x-jsrender">
{{for items}}
    <p>インデックス={{>#index}}</p>
    {{if #index > 0}}
        <p>インデックス"{{>#index}}"{{>name}}{{>num}}個あります</p>
    {{/if}}

    {{if #index > 0}}
        <p>インデックス"{{>#getIndex()}}"{{>name}}{{>num}}個あります</p>
    {{/if}}

    {{if #index > 0 ~idx=#index}}
        <p>インデックス"{{>~idx}}"{{>name}}{{>num}}個あります</p>
    {{/if}}
{{/for}}
</script>
</body>
</html>

説明

forタグなどのループ内でも当然ifタグ等が使えますが、このタグブロック内でループの#indexを使用すると

Unavailable (nested view): use #getIndex()

というエラーになります。

JsRenderでは、記述されたテンプレートは実際にはViewと呼ばれるオブジェクトに変換され、タグごとにネストした構造になっています。ループのインデックスを表す#indexは、このViewオブジェクト配列もしくはオブジェクトを表す場合にのみ数値がセットされる仕組みになっていて、ifタグを表すViewオブジェクトなど、それ以外の場合はエラーメッセージがセットされます。

解決方法は少なくとも2つあります。

1つ目は、メッセージに表示される"#getIndex()"を#indexの代わりに使用することです。これは、インデックスを再評価して返すものです。

    <p>インデックス"{{>#getIndex()}}"{{>name}}{{>num}}個あります</p>

もう一つは、JsRenderチュートリアル - 他のテンプレートを読み込む際に変数を渡す - Do You PHP はてなにあるように、変数をネストした子Viewオブジェクトに渡すというものです。JsRenderチュートリアル - 他のテンプレートを読み込む際に変数を渡す - Do You PHP はてなでは子テンプレートに渡しましたが、ifタグなど他のタグでも使用できます。上のコード例では、#indexを~idxとして子Viewオブジェクトに渡しています。

    {{if #index > 0 ~idx=#index}}
        <p>インデックス"{{>~idx}}"{{>name}}{{>num}}個あります</p>
    {{/if}}

JSFiddleで動作を見る

参照

2015-03-10

[]JsRenderチュートリアル - テンプレートでループのインデックスを取得する

JavaScript製でjQuery非依存なテンプレートエンジンであるJsRender/JsViewsを使ったチュートリアルを書いてみようと思います。

以前に書いたエントリJsRender入門 - Do You PHP はてなも参照してください。

今回やること

テンプレート内でループのインデックスを取得する

コード

<html>
<body>

<!-- レンダリング結果を表示するスペース -->
<div id="result"></div>

<script src="https://code.jquery.com/jquery-1.11.1.min.js" type="text/javascript"></script>
<script src="http://www.jsviews.com/download/jsviews.min.js" type="text/javascript"></script>
<script type="text/javascript">
// ループ - forタグ
$(function() {
    // 表示するデータ
    var fruits = {
        items: [
            { name: "りんご", num: 3 },
            { name: "いちご", num: 5 },
            { name: "バナナ", num: 2 }
        ]
    };

    // テンプレートに名前(ここでは"linkTemplate")をつけて登録する
    $.templates({
        linkTemplate: "#template"
    });

    // テンプレート"linkTemplate"に変数fruitsを渡し、
    // レンダリング結果を表示
    $('#result').html($.render.linkTemplate(fruits));
});
</script>

<!-- テンプレート -->
<script id="template" type="text/x-jsrender">
{{for items}}
    <p>{{>#index}}:{{>name}}{{>num}}個あります</p>
{{/for}}
</script>
</body>
</html>

説明

ループ内のインデックスはforタグ、propsタグ共に#indexで取得できます。

    {{>#index}}

JSFiddleで動作を見る

参照

2015-03-09

[]JsRenderチュートリアル - テンプレートオブジェクトプロパティをループで取得する

JavaScript製でjQuery非依存なテンプレートエンジンであるJsRender/JsViewsを使ったチュートリアルを書いてみようと思います。

以前に書いたエントリJsRender入門 - Do You PHP はてなも参照してください。

今回やること

テンプレート内でオブジェクトプロパティをループで取得しながら値を表示する

コード

<html>
<body>

<!-- レンダリング結果を表示するスペース -->
<div id="result"></div>

<script src="https://code.jquery.com/jquery-1.11.1.min.js" type="text/javascript"></script>
<script src="js/jsrender.min.js" type="text/javascript"></script>
<script type="text/javascript">
// ループ - propsタグ
$(function() {
    // 表示するデータ(オブジェクト)
    var fruits = { name: "りんご", num: 3 };

    // テンプレートに名前(ここでは"linkTemplate")をつけて登録する
    $.templates({
        linkTemplate: "#template"
    });

    // テンプレート"linkTemplate"に変数fruitsを渡し、
    // レンダリング結果を表示
    $('#result').html($.render.linkTemplate(fruits));
});
</script>

<!-- テンプレート -->
<script id="template" type="text/x-jsrender">
{{props #data}}
    <p>{{>key}}の値は{{>prop}}です</p>
{{/props}}
</script>
</body>
</html>

説明

JsRenderのfor文はPHPと異なり配列に対してのみ有効です。PHPで言うところのforeachに相当する構文はpropsタグになります。

    {{props [オブジェクト]}}
         :
    {{/props}}

propsによるループ中、キーと値はそれぞれ"key"、"prop"で参照できます。

{{props #data}}
    <p>{{>key}}の値は{{>prop}}です</p>
{{/props}}

JSFiddleで動作を見る

参照

[]JsRenderチュートリアル - テンプレートでのループ

JavaScript製でjQuery非依存なテンプレートエンジンであるJsRender/JsViewsを使ったチュートリアルを書いてみようと思います。

以前に書いたエントリJsRender入門 - Do You PHP はてなも参照してください。

今回やること

テンプレート内でforタグを使ってループさせながら値を表示する

コード

<html>
<body>

<!-- レンダリング結果を表示するスペース -->
<div id="result"></div>

<script src="https://code.jquery.com/jquery-1.11.1.min.js" type="text/javascript"></script>
<script src="js/jsrender.min.js" type="text/javascript"></script>
<script type="text/javascript">
// ループ - forタグ
$(function() {
    // 表示するデータ
    var fruits = [
        { name: "りんご", num: 3 },
        { name: "いちご", num: 5 },
        { name: "バナナ", num: 2 }
    ];

    // テンプレートに名前(ここでは"linkTemplate")をつけて登録する
    $.templates({
        linkTemplate: "#template"
    });

    // テンプレート"linkTemplate"に変数fruitsを渡し、
    // レンダリング結果を表示
    $('#result').html($.render.linkTemplate(fruits));
});
</script>

<!-- テンプレート -->
<script id="template" type="text/x-jsrender">
{{for #data}}
    <p>{{>name}}{{>num}}個あります</p>
{{/for}}
</script>
</body>
</html>

説明

プログラミング言語と同様、JsRenderにもfor文があります。ただし、配列に対してのみ有効です。構文はforタグを使って以下のようになります。

    {{for [配列]}}
         :
    {{/for}}

JSFiddleで動作を見る

参照

[]JsRenderチュートリアル - テンプレートでの条件分岐

JavaScript製でjQuery非依存なテンプレートエンジンであるJsRender/JsViewsを使ったチュートリアルを書いてみようと思います。

以前に書いたエントリJsRender入門 - Do You PHP はてなも参照してください。

今回やること

テンプレート内でifタグを使って条件分岐する

コード

<html>
<body>

<!-- レンダリング結果を表示するスペース -->
<div id="result"></div>

<script src="https://code.jquery.com/jquery-1.11.1.min.js" type="text/javascript"></script>
<script src="http://www.jsviews.com/download/jsviews.min.js" type="text/javascript"></script>
<script type="text/javascript">
// 条件分岐 - ifタグ
$(function() {
    // 表示するデータ(配列)
    var fruits = [
            { name: "りんご", num: 3 },
            { name: "いちご", num: 5 },
            { name: "バナナ", num: 2, unit: '本' }
        ];

    // テンプレートに名前(ここでは"linkTemplate")をつけて登録する
    $.templates({
        linkTemplate: "#template"
    });

    // テンプレート"linkTemplate"に変数fruitsを渡し、
    // レンダリング結果を表示
    $('#result').html($.render.linkTemplate(fruits));
});
</script>

<!-- テンプレート -->
<script id="template" type="text/x-jsrender">
    <p>
        {{>name}}{{>num}}

        {{if unit}}
            {{>unit}}
        {{else}}

        {{/if}}

        あります
    </p>
</script>
</body>
</html>

説明

プログラミング言語と同様、JsRenderにもif文があります。構文はifタグを使って以下のようになります。

    {{if [条件1]}}
         :
    {{else [条件2]}}
         :
    {{else}}
         :
    {{/if}}

JSFiddleで動作を見る

参照

[]JsRenderチュートリアル - 他のテンプレートを読み込む際にコンテンツを渡す

JavaScript製でjQuery非依存なテンプレートエンジンであるJsRender/JsViewsを使ったチュートリアルを書いてみようと思います。

以前に書いたエントリJsRender入門 - Do You PHP はてなも参照してください。

今回やること

他のテンプレートを読み込む際にコンテンツを渡す

コード

<html>
<body>

<!-- レンダリング結果を表示するスペース -->
<div id="result"></div>

<script src="https://code.jquery.com/jquery-1.11.1.min.js" type="text/javascript"></script>
<script src="http://www.jsviews.com/download/jsviews.min.js" type="text/javascript"></script>
<script type="text/javascript">
// テンプレートのinclude - コンテンツとして値を渡す
$(function() {
    // 表示するデータ(オブジェクト)
    var fruits = { name: "りんご", num: 3 };

    // テンプレートに変数fruitsを渡し、レンダリング結果を表示
    $('#result').html(
        $('#template').render(fruits)
    );
});
</script>

<!-- テンプレート -->
<script id="template" type="text/x-jsrender">
    <p>{{:name}}{{:num}}個あります</p>
    {{include tmpl="#template_child"}}
        <i>{{>name}}</i>が<i>{{>num}}</i>個ありますよん
    {{/include}}
</script>
<script id="template_child" type="text/x-jsrender">
    <p>template_child内</p>
    {{include tmpl=#content/}}
</script>
</body>
</html>

説明

他のテンプレートには変数の他にコンテンツをそのまま渡すこともできます。この場合、includeタグの値としてコンテンツを指定します。

    {{include tmpl="#template_child"}}
        <i>{{>name}}</i>が<i>{{>num}}</i>個ありますよん
    {{/include}}

テンプレートでは、テンプレート名に"#content"を指定してコンテンツをincludeします。

    {{include tmpl=#content/}}

JSFiddleで動作を見る

参照

[]JsRenderチュートリアル - 他のテンプレートを読み込む際に変数を渡す

JavaScript製でjQuery非依存なテンプレートエンジンであるJsRender/JsViewsを使ったチュートリアルを書いてみようと思います。

以前に書いたエントリJsRender入門 - Do You PHP はてなも参照してください。

今回やること

他のテンプレートを読み込む際に変数を渡す

コード

<html>
<body>

<!-- レンダリング結果を表示するスペース -->
<div id="result"></div>

<script src="https://code.jquery.com/jquery-1.11.1.min.js" type="text/javascript"></script>
<script src="http://www.jsviews.com/download/jsviews.min.js" type="text/javascript"></script>
<script type="text/javascript">
// テンプレートのinclude - 変数を渡す
$(function() {
    // 表示するデータ(オブジェクト)
    var fruits = { name: "りんご", num: 3 };

    // テンプレートに変数fruitsを渡し、レンダリング結果を表示
    $('#result').html(
        $('#template').render(fruits)
    );
});
</script>

<!-- テンプレート -->
<script id="template" type="text/x-jsrender">
    <p>{{>name}}{{>num}}個あります</p>
    {{include tmpl="#template_child" ~item_name=name ~item_num=num/}}
</script>
<script id="template_child" type="text/x-jsrender">
    <p>template_childです</p>
    <p>{{>~item_name}}{{>~item_num}}個あります</p>
</script>
</body>
</html>

説明

他のテンプレートをincludeする際に現在のコンテキストの変数を明示的に渡すことができます。この場合、書式は次のようになります。

~[子テンプレートでの変数名]=[現在のコンテキストでの変数名]

一方、子テンプレートでは

~[子テンプレートでの変数名]

で値を参照できます。

コード例の場合、「name」「num」という変数の値を、子テンプレートでの変数「item_name」「item_num」として参照できるようにしています。

    {{include tmpl="#template_child" ~item_name=name ~item_num=num/}}
            :
    <p>{{>~item_name}}が{{>~item_num}}個あります</p>

JSFiddleで動作を見る

参照

[]JsRenderチュートリアル - 他のテンプレートを読み込む

JavaScript製でjQuery非依存なテンプレートエンジンであるJsRender/JsViewsを使ったチュートリアルを書いてみようと思います。

以前に書いたエントリJsRender入門 - Do You PHP はてなも参照してください。

今回やること

他のテンプレートを読み込んで値を表示する

コード

<html>
<body>

<!-- レンダリング結果を表示するスペース -->
<div id="result"></div>

<script src="https://code.jquery.com/jquery-1.11.1.min.js" type="text/javascript"></script>
<script src="http://www.jsviews.com/download/jsviews.min.js" type="text/javascript"></script>
<script type="text/javascript">
// テンプレートのinclude
$(function() {
    // 表示するデータ(オブジェクト)
    var fruits = { name: "りんご", num: 3 };

    // テンプレートに変数fruitsを渡し、レンダリング結果を表示
    $('#result').html(
        $('#template').render(fruits)
    );
});
</script>

<!-- テンプレート -->
<script id="template" type="text/x-jsrender">
    <p>{{>name}}{{>num}}個あります</p>
    {{include tmpl="#template_child"/}}
</script>
<script id="template_child" type="text/x-jsrender">
    <p>template_child内</p>
    <p>{{>name}}{{>num}}個あります</p>
</script>
</body>
</html>

説明

テンプレートから他のテンプレートを読み込むには、includeタグを使用します。その際、tmpl属性テンプレートへのセレクタを指定します。

    {{include tmpl="#template_child"/}}

読み込まれた子テンプレート内では、親テンプレートでincludeした場所と同等のコンテキストとなります。前述のコード例の場合、#templateと#template_childでそれぞれnameやnumなどのプロパティの値にアクセスできます。

JSFiddleで動作を見る

参照