Meteorのあんちょこ꒰｡･ω･`;꒱ テンプレート編

# 本流

- [Meteorのあんちょこ꒰｡･ω･`;꒱](http://qiita.com/shoko_kb/items/786524ce3a7f20c464ad)

# テンプレート

## 概要

- テンプレートは、Handlebarsで記述する。
- Blazeはレンダリングライブラリらしい。
- レンダリングを、Blazeのかわりに、React.jsやAngular.jsに担当してもいいが、Blazeが最良と書いてあるので、鵜呑みにする。。。

> Blaze is Meteor’s built-in reactive rendering library. Usually, templates are written in Spacebars...
> Blaze is not required to build applications in Meteor—you can also easily use React or Angular to develop your UI (here’s a comparison). However, this particular article will take you through best practices in building an application in Blaze, which is used as the UI engine in all of the other articles.

- Meteorは<template>要素によって定義されたテンプレートを、JavaScriptコードにコンパイルして利用する。
- 開発モードで動作させる場合は、コンパイル処理を実行時に、本番環境ではコンパイル処理は事前に実施する。
- コンパイルで、テンプレートはJavaScriptの関数となる。
- ~~グローバルなTemplateオブジェクトのメンバーとして定義される。~~
- ~~その関数に対しては，Template.テンプレート名でアクセスすることが可能。~~
- 参考文献と異なり、**Template.(テンプレート名）**の場合、テンプレートオブジェクトが参照可。
- **Template.（テンプレート名）.renderFunction().value**で表示内容にアクセス可。
- 経験則的な為、手段として正しいかどうかは、自信なし。

```bash:ブラウザのコンソールからテンプレートを呼び出した例
> Template.mainContent
Template {viewName: "Template.mainContent", renderFunction: function, __helpers: HelperMap, __eventMaps: Array, _callbacks: {created: [], rendered: [], destroyed: []}, …} = $1
> Template.mainContent.renderFunction().value
< "<button id=\"hello\">Hello</button>" = $8
```

## 参考

- [第5回　Handlebarsの使用法:体感！JavaScriptで超速アプリケーション開発 －Meteor完全解説](http://gihyo.jp/dev/serial/01/meteor/0005)

---

## 埋込み用のエスケープ記号

- {{text}}...テキストを埋める場合は２重中括弧で記述
- {{{html}}}...HTMLを埋める場合は３重中括弧で記述

参考：[Insert HTML markup using Meteor@stack overflow](http://stackoverflow.com/questions/14267856/insert-html-markup-using-meteor)

---

## Sample

- template
- blaze

## My first sample

```text:.meteor/packages
blaze-html-templates    # Compile .html files into Meteor Blaze views
```

```html:client/main.html
<head>
  <title>template</title>
</head>

<body>
  <h1>Welcome to Meteor!</h1>

  {{> sample1}}
  {{> sample2}}
  {{> welcome yourname="Shoko" now="2016-07-01"}}
  {{> welcomeja }}

</body>

<template name="sample1">
  <p>This is my first template1...</p>
</template>

<template name="sample2">
  <p>This is my first template2...</p>
</template>

<template name="welcome">
  <p>Hello, {{yourname}}. Now is {{now}}.</p>
</template>

<template name="welcomeja">
  <p>Hello, {{yourname}}. Now is {{now}}.</p>
</template>

<template name="greet" greeting="Hello, <br>Shoko">
  <p>Hello, {{{greeting}}}.</p>
</template>
```

```js:client/main.js
// helpers関数を使って、テンプレート評価できた。
Template.welcomeja.helpers({
  yourname: 'Shoko',
  now: new Date()
});
```
> ようこそ、Shoko. 現在時刻はTue Jul 12 2016 05:27:11 GMT+0900 (JST)
 
----

# Built-in Block Helper （ブロック構造）

## DOM構造

```html:client/main.html
  {{> family}}
    :

<template name="family">
  <p>ようこそ、{{person.name}}.</p>
  {{#with family}}
    <p>苗字は{{lastname}}。</p>
    {{#with mother}}
      <p>母は、{{name}}</p>
      <p>父は、{{../father.name}}</p>
    {{/with}}
  {{/with}}
</template>
```

```js:client/main.js
Template.family.helpers({
	person: { name: 'Shoko JP' },
	family : {
		lastname: 'JP',
		mother: { name:'Hanako' },
		father: { name:'Taro' }
	},
});
```

## 分岐（if） 

```html:client/main.html
  <h2>ifで記述</h2>
  <p>{{> current_time}}</p>

<template name="current_time">
  {{# if oddSeconds}}
    現在時刻は{{dateString}}
  {{else}}
    現在時刻は{{now}}
  {{/if}}
</template>
```

```js:client/main.js
Template.current_time.helpers({
	now: new Date(),
	oddSeconds: function () {
		var date = new Date();
		//console.log(date.getSeconds());
		return date.getSeconds() % 2 === 1;
	},
	dateString: function () {
      var date = new Date();
      var date_ja = date.getFullYear() + '年' + (date.getMonth() + 1) + '月' + date.getDate() + '日 ' +
      	date.getHours() + '時' + date.getMinutes() + '分' + date.getSeconds() + '秒';
      return date_ja;
	}
});
```

```html:client/main.html
  {{> caller_myif}}

<template name="myIf">
  {{#if condition}}
    {{> Template.contentBlock}}
  {{else}}
    {{> Template.elseBlock}}
  {{/if}}
</template>

<template name="caller_myif">
  {{#myIf condition=true}}
    <h1>I'll be rendered!</h1>
  {{else}}
    <h1>I won't be rendered</h1>    
  {{/myIf}}
</template>
```
> I'll be rendered!

## 分岐（unless）

```html:client/main.html
  <h2>unlessで記述</h2>
  <p>{{> current_time_unless}}</p>

<template name="current_time_unless">
  {{# unless oddSeconds}}
    <span style="color:green">現在時刻は{{dateString}}</span>
  {{else}}
    <span style="color:red">現在時刻は{{now}}</span>
  {{/unless}}
</template>
```

> ifで記述
> 現在時刻は2016年7月12日 6時48分55秒

```js:client/main.js
Template.current_time_unless.helpers({
	now: new Date(),
	oddSeconds: function () {
		var date = new Date();
		//console.log(date.getSeconds());
		return date.getSeconds() % 2 === 1;
	},
	dateString: function () {
      var date = new Date();
      var date_ja = date.getFullYear() + '年' + (date.getMonth() + 1) + '月' + date.getDate() + '日 ' +
      	date.getHours() + '時' + date.getMinutes() + '分' + date.getSeconds() + '秒';
      return date_ja;
	}
});
```

> unlessで記述
> 現在時刻はTue Jul 12 2016 06:48:55 GMT+0900 (JST)


## ループ（each） 
```html:client/main.html
  <h2>eachで記述（デフォルトの昇順ループ）</h2>
  {{> fruits }}
<template name="fruits">
  <ul>
    {{ #each fruits }}
      <li>{{this}}</li>
    {{ /each }}
  </ul>
</template>
```

```js:client/main.js
Template.fruits.helpers({
	fruits: ['apple', 'banana', 'orange']
});
```

>eachで記述（デフォルトの昇順ループ）
> * apple
> * banana
> * orange

## 代入（let）
```html:client/main.html
  <h2>letで記述</h2>
  <p>{{> sample_let }}</p>

<template name="sample_let">
  {{#let name=person.bio.firstName color=generateColor}}
    <div>{{name}} gets a {{color}} card!</div>
  {{/let}}
</template>
```

```js:client/main.js
Template.sample_let.helpers({
	person: {
	 	bio: { firstName: 'Shoko' }
	},
	generateColor: 'red'
});
```

> letで記述
> Shoko gets a red card!

## 自作のBlock Helper

- TODO:要調査

----

# テンプレートでのイベント処理

## 参考

- [第6回　Meteorテンプレートをもっと活用する:体感！JavaScriptで超速アプリケーション開発 －Meteor完全解説](http://gihyo.jp/dev/serial/01/meteor/0006)

## Sample 

- template-events

## イベント定義

- イベントマップキーは下記の形式で指定する。

> イベント名[,イベント名...] セレクタ

```html:main.html
<head>
  <title>template-events</title>
</head>

<body>
  <h1>Welcome to Meteor!</h1>

  {{> mainContent}}

</body>

<template name="mainContent">
  <button id="hello">Hello</button>
  <button id="goodMorning">Good Morning</button>
</template>
```

```js:main.js
import { Template } from 'meteor/templating';
import { ReactiveVar } from 'meteor/reactive-var';

import './main.html';

Template.mainContent.helpers({
});

Template.mainContent.events({
  'click button'(event, instance) {
    alert("Button Clicked");
  },
  'click #hello' (event, instance) {
  	alert("Hello");
  },
  'click #goodMorning' (event, instance) {
  	alert("Good Morning");
  }
});
```

----
## テンプレートAPI

- <template>要素はMeteorによってコンパイルされ、グローバル変数Templateに関数オブジェクトとして登録される。

### イベントハンドラ

- Template関数オブジェクトには下記のイベントを常備されている。

- **onCreated**…テンプレートが**生成**時に呼び出されるイベントハンドラ
- **onRendered**…テンプレートの実行結果が**DOM展開**時呼び出されるイベントハンドラ（表示時と考えると分かりやすいが、非表示オブジェクトもあるので、展開としておく。）
- **onDestroyed**…テンプレートが**破棄**された時に呼び出されるイベントハンドラ。

```js:main.js
Template.mainContent.onCreated(function () {
	console.log('created');
});
Template.mainContent.onRendered(function() {
    console.log('rendered');
});
Template.mainContent.onDestroyed(function() {
    console.log('destroyed');
});
```

### 関数

- **events(event map)**…イベントマップ
- **helpers(helpers)**…ヘルパー関数（テンプレートにデータを受け渡す。）
- **preserve(selectors)**…テンプレートの再レンダリングが行われた際、以前のDOMノードの状態を引き継ぎたい要素を、セレクタで指定します。（テンプレートの再レンダリングについては、**ライブHTML**という概念の理解が必要。）

```html:main.html
<head>
  <title>template-events</title>
</head>

<body>
  <h1>Welcome to Meteor!</h1>

  {{> mainContent}}

</body>

<template name="mainContent">
  <button id="hello" class="greetings">Hello</button>
  <button id="goodMorning" class="greetings">Good Morning</button>
  <hr/>
  <input type="text" id="name"/><button id="greet">greet</button>
</template>

```

```js:main.js
import { Template } from 'meteor/templating';
import { ReactiveVar } from 'meteor/reactive-var';

import './main.html';

Template.mainContent.helpers({
});

Template.mainContent.events({
  'click button .greetings'(event, template) {
    alert("Button Clicked");

    console.log(template);

    console.log(template.firstNode);
    console.log(template.lastNode);
    console.log(template.findAll('button'));	// 検索にヒットするすべてのノード
    console.log(template.find('button'));		// 検索にヒットする最初のノード

    console.log(template.$('button'));			// jquery

    // console.log(template.data());					// テンプレートが呼び出された際に渡されたデータ
  },
  'click #hello' (event, template) {
    alert("Hello");
  },
  'click #goodMorning' (event, template) {
    alert("Good Morning");
  },
  'click #greet' (event, template) {
    var name = template.$('input[type=text]').val();      //jquery
    //var name = template.find('input[type=text]').value; //DOM
    console.log(name);
  }
});

Template.mainContent.onCreated(function () {
	console.log('created');

	var template = this;
	console.log(template);
});
Template.mainContent.onRendered(function() {
    console.log('rendered');
});
Template.mainContent.onDestroyed(function() {
    console.log('destroyed');
});
```

----

# JQuery UI Draggableを使用してみた

## Sample

- sample_draggble

## パッケージ追加

- [Atmosphere](https://atmospherejs.com/)でパッケージを検索できる。
- [dbernhard:jquery-ui-draggable](https://atmospherejs.com/dbernhard/jquery-ui-draggable)を導入する。

```bash:console
$ meteor add dbernhard:jquery-ui-draggable
```

## コーディング

```html:main.html
<template name="test">
  <article class="article">Draggable Element</article>
</template>
```

```js:main.js
Template.test.onRendered(function testOnRendered() {
	$article = $(Template.instance().firstNode);
	$article.draggable();
	// console.log($article);
});
```