Todoアプリ復習(編集ボタン追加)

復習用。

by FiNGAHOLiC

HTML

<script src="https://raw.github.com/jquery/jquery-tmpl/master/jquery.tmpl.min.js"></script>
<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 type="text/x-jquery-tmpl" id="mod-tmpl-list">
    <div class="item">
        <div class="mod-task">
            <span>${task}</span><button class="delete">delete</button><button class="edit">edit</button>
        </div>
        <div class="mod-edit">
            <input type="text" value="${task}"><button class="save">save</button>
        </div>
    </div>
</script>

<div id="mod-app">
    <header>
        <h1>Todoアプリ</h1>
    </header>
    <div id="mod-regist">
        <input type="text" placeholder="例:宿題をやる"><button>create</button>
    </div>
    <div id="mod-tasks">
        <div class="items"></div>
    </div>
</div>

CSS

#mod-tasks{}
#mod-tasks .items{}
#mod-tasks .items .item{}
#mod-tasks .items .item .mod-task{ display:block; }
#mod-tasks .items .item .mod-edit{ display:none; }
#mod-tasks .items .item.editing .mod-task{ display:none; }
#mod-tasks .items .item.editing .mod-edit{ display:block; }

JavaScript

(function($, window, document, undefined){

    // Taksモデル
    var Task = Spine.Model.sub();
    Task.configure('Task', 'task');
    Task.extend(Spine.Model.Local);
    
    // Tasksコントローラ
    var Tasks = Spine.Controller.sub({
        // 18. 要素を設定
        elements: {
            '.mod-edit input': 'input'
        },
        // 9. 初期生成要素のtag名を設定
        // 22. 不要なので削除
        // tag: 'li',
        // 14. イベントを登録
        events: {
            'click .delete': 'delete',
            'click .edit': 'edit',
            'click .save': 'save'
        },
        init: function(){
            // 16. レコードが削除されれば要素を削除する
            this.item.bind('destroy', this.release);
            // 24. レコードが更新されれば要素を再レンダリングする
            this.item.bind('update', this.proxy(this.render));
        },
        delete: function(){
            // 15. レコードを削除
            this.item.destroy();
        },
        edit: function(){
            // 17. elのli要素にクラスを付与
            this.el.addClass('editing');
        },
        save: function(){
            // 19. elのli要素からクラスを削除
            this.el.removeClass('editing');
            // 20. レコードを更新
            this.item.updateAttributes({
                task: this.input.val()
            });
        },
        render: function(){
            // 10. テンプレートとレコードを元にhtmlを生成しel要素に挿入
            // this.el.html($('#mod-tmpl-list').tmpl(this.item));
            // 21. elementsを再走査出来るのでreplaceに差し替え
            this.replace($('#mod-tmpl-list').tmpl(this.item));
            return this;
        }
    });
    
    // Appコントローラ
    var App = Spine.Controller.sub({
        // 3. 要素を設定
        elements: {
            '#mod-regist input': 'input',
            // 23. ulからdivへ変更
            '#mod-tasks .items': 'lists'
        },
        // 2. イベントを登録
        events: {
            'click button': 'create'
        },
        init: function(){
            // 6. 新規レコードが作成されればaddメソッドを叩く
            Task.bind('create', this.proxy(this.add));
            // 12....