Do You PHP はてブロ

Do You PHPはてなからはてブロに移動しました

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

JavaScript製でjQuery非依存なテンプレートエンジンであるJsRender/JsViewsを使ったチュートリアルを書いてみようと思います。
以前に書いたエントリJsViews入門 - 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で動作を見る

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を使ったチュートリアルを書いてみようと思います。
以前に書いたエントリJsViews入門 - 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で動作を見る

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で動作を見る

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 テンプレートに関する情報を格納したオブジェクト
#type Viewの種類
#views 現在のViewにネストされた子Viewオブジェクト

最初のチュートリアルから「テンプレートに渡されたデータは#dataで参照できる」と書いてきましたが、実際はViewオブジェクトのプロパティを参照していた、ということです。
また、JsRenderチュートリアル - テンプレートでループのインデックスを取得する - Do You PHP はてなで使った#indexも同様で、JsRenderチュートリアル - ループ内のタグブロック内でインデックスが取得できない - Do You PHP はてなで出てきた#getIndex()は#indexが取得できない場合のみ定義されるViewオブジェクトのメソッドになります。

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

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

JSFiddleで動作を見る