連絡先管理アプリ
さらに復習用。
by FiNGAHOLiC
HTML
<script src="https://raw.github.com/maccman/spine/master/lib/spine.js"></script>
<script src="https://raw.github.com/maccman/spine/master/lib/local.js"></script>
<script src="https://raw.github.com/maccman/spine/master/lib/manager.js"></script>
<script src="https://raw.github.com/maccman/spine/master/lib/route.js"></script>
<script src="https://raw.github.com/jquery/jquery-tmpl/master/jquery.tmpl.min.js"></script>
<header id="mod-header"><h1>Spine Contacts</h1></header>
<article id="mod-article"></article>
<script type="text/x-jquery-tmpl" id="mod-tmpl-item">
<div class="item">
{{if username}}
${username}
{{else}}
<i>No Name</i>
{{/if}}
</div>
</script>
<script type="text/x-jquery-tmpl" id="mod-tmpl-sidebar">
<header>
<input type="search" placeholder="search" results="0" incremental="true" autofocus>
</header>
<div class="items"></div>
<footer>
<button>New Contact</button>
</footer>
</script>
<script type="text/x-jquery-tmpl" id="mod-tmpl-show">
<header>
<a class="edit">Edit</a>
</header>
<div class="content">
<p>${username}</p>
<p>${email}</p>
</div>
</script>
<script type="text/x-jquery-tmpl" id="mod-tmpl-edit">
<header>
<a class="save">Save</a>
<a class="delete">Delete</a>
</header>
<div class="content">
<form>
<label>
<span>Username</span>
<input type="text" name="username" value="${username}">
</label>
<label>
<span>Email</span>
<input type="email" name="email" value="${email}">
</label>
</form>
</div>
</script>
CSS
#mod-header{
margin-bottom:1px;
padding:10px;
background:#000;
color:#fff;
}
.contacts{
overflow:hidden;
}
.sidebar{
width:150px;
float:left;
}
.sidebar header{
padding:10px;
background:#999;
text-align:center;
}
.sidebar header a{
margin-right:1px;
padding:5px 10px;
display:inline-block;
background:#fff;
}
.sidebar header input{
width:128px;
}
.sidebar footer{
padding:10px;
background:#999;
text-align:center;
}
.sidebar .items{
margin-top:1px;
}
.sidebar .item{
margin-bottom:1px;
padding:5px 10px;
background:#efefef;
cursor:pointer;
}
.sidebar .active{
background:#c00;
color:#fff;
}
.main{
margin-left:151px;
}
.main header{
overflow:hidden;
background:#efefef;
}
.main header a{
margin-right:1px;
padding:5px 10px;
display:block;
float:left;
background:#999;
color:#fff;
cursor:pointer;
}
.main .content{
padding:10px;
}
.main p{
margin-bottom:5px;
}
.main label{
margin-bottom:5px;
display:block;
}
.main label span{
width:100px;
display:inline-block;
}
.stack > *:not(.active){
display:none;
}
JavaScript
(function($, window, document, undefined){
$.extend($.fn, {
item: function(){
var item = $(this).tmplItem().data;
return ($.isFunction(item.reload) ? item.reload() : null);
},
forItem: function(item){
return this.filter(function(){
var compare = $(this).tmplItem().data;
// Returns a boolean indicating
// if the other record is equal (i.e. same class and ID) as
// the current instance.
// http://spinejs.com/api/models
if(item.eql && item.eql(compare) || item === compare) return true;
});
}
});
var Contact = Spine.Model.sub();
Contact.configure('Contact', 'username', 'email');
Contact.extend(Spine.Model.Local);
Contact.extend({
filter: function(query){
if(!query) return this.all();
var query = query.toLowerCase();
return this.select(function(item){
var _ref, _ref1;
return ((_ref = item.username) != null ? _ref.toLowerCase().indexOf(query) : void 0) !== -1 || ((_ref1 = item.email) != null ? _ref1.toLowerCase().indexOf(query) : void 0) !== -1;
});
}
});
var Item = Spine.Controller.sub({
events: {
'click .item': 'click'
},
selectFirst: true,
init: function(){
this.bind('change', this.change);
},
template: function(items){
return $('#mod-tmpl-item').tmpl(items);
},
change: function(item){
this.current = item;
if(!this.current){
this.children().removeClass('active');
return;
};
this.children().removeClass('active');
this.children().forItem(this.current).addClass('active');
},
render: function(items){
if(items){
this.items =...