連絡先管理アプリケーション
Spine.jsで連絡先管理アプリケーションを作ってみる。
HTML
<script src="https://raw.github.com/maccman/book-assets/master/ch11/spine.contacts/lib/spine.js"></script>
<script src="https://raw.github.com/maccman/book-assets/master/ch11/spine.contacts/lib/spine.list.js"></script>
<script src="https://raw.github.com/maccman/book-assets/master/ch11/spine.contacts/lib/spine.model.local.js"></script>
<script src="https://raw.github.com/maccman/book-assets/master/ch11/spine.contacts/lib/jquery.tmpl.js"></script>
<script type="text/x-jquery-tmpl" id="contactsTemplate">
<li class="item">
{{if fullName()}}
<div>${fullName()}</div>
{{else}}
<div>名前なし</div>
{{/if}}
</li>
</script>
<script type="text/x-jquery-tmpl" id="contactTemplate">
<dl>
<dt>名前</dt>
<dd>${first_name} ${last_name}</dd>
<dt>メールアドレス</dt>
{{if email}}
<dd>${email}</dd>
{{else}}
<dd>なし</dd>
{{/if}}
</dl>
</script>
<script type="text/x-jquery-tmpl" id="editContactTemplate">
<dl>
<dt>ファーストネーム</dt>
<dd><input type="text" name="first_name" value="${first_name}" autofocus></dd>
<dt>ラストネーム</dt>
<dd><input type="text" name="last_name" value="${last_name}"></dd>
<dt>メールアドレス</dt>
<dd><input type="text" name="email" value="${email}"></dd>
</dl>
</script>
<div id="sidebar">
<ul class="items"></ul>
<footer>
<button>新規連絡先</button>
</footer>
</div>
<div id="contacts">
<div class="show">
<ul class="options">
<li class="optEdit">連絡先の編集</li>
</ul>
<div class="content"></div>
</div>
<div class="edit">
<ul class="options">
<li class="optSave default">連絡先の保存</li>
<li class="optDestroy">連絡先の削除</li>
</ul>
<div class="content"></div>
</div>
</div>
CSS
body{
line-height:2;
}
#sidebar{
width:20%;
float:left;
}
#sidebar .current{
background:#000;
color:#fff;
}
#contacts{
width:75%;
float:right;
}
#contacts dt{
background:#efefef;
}
#contacts .options{
margin-bottom:1em;
overflow:hidden;
}
#contacts .options li{
width:10em;
margin-right:1em;
float:left;
background:#000;
color:#fff;
text-align:center;
}
JavaScript
(function($, window, document, undefined){
// ユーティリティ用のメソッドを定義
$.extend($.fn, {
// 要素に紐付けられたモデルデータを返す
item: function(){
// 紐付けられたモデルデータを取得
var item = $(this).tmplItem().data;
// モデルデータを返す(reloadで再取得してから)
// http://spinejs.com/api/models内のreloadAPI参照
return ($.isFunction(item.reload) ? item.reload() : null);
},
// 渡されたモデルデータを持つ要素を返す
forItem: function(item){
return this.filter(function(){
// 紐付けられたもモデルデータを代入
var compare = $(this).tmplItem().data;
// モデルデータがあり、モデルデータと一致すればその要素を返す
// http://spinejs.com/api/models内のeqlAPI参照
if (item.eql && item.eql(compare) || item === compare) return true;
});
},
// 指定された要素内の配列を返す
serializeForm: function(){
// 返り値用にオブジェクトを生成
var result = {};
// 指定された要素をシリアライズし、配列を返す
$.each($(this).find('input, textarea').serializeArray(), function(i, item){
result[item.name] = item.value;
});
// JSONオブジェクトを返す(e.x.{ email: '...', first_name: '...', last_name: '...' })
return result;
}
});
// Contactモデル
// Spineの最新版だと設定方法は変更されているので注意
var Contact = Spine.Model.setup('Contact', ['first_name', 'last_name', 'email']);
// ローカルストレージを利用するのでLocalを継承(要local.js)
Contact.extend(Spine.Model.Local);
// テンプレート内で使用するためにインスタンスメソッドを追加
Contact.include({
fullName: function(){
// ファーストネーム、ラストネームが設定されていない場合はfalseを返す
if (!this.first_name && !this.last_name) return;
return (this.first_name + ' ' + this.last_name);
}
});
// Sidebarコントローラー
var Sidebar = Spine.Controller.create({
// インスタンス変数を追加
elements: {
'.items': 'items'
},
// buttonをclickするとcreateメソッドを叩く
events: {
...