Backbone Template

Standard fiddle

by Andy Novocin

HTML

<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.5.2/underscore-min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/backbone.js/1.1.0/backbone-min.js"></script>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.0.3/css/bootstrap.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.0.3/js/bootstrap.js"></script>
<div id="page"></div>

<script type="text/template" id="todo-template">
  <div class="row">
    <div class="col-xs-6">
        <div class="input-group">
            <input type="text" class="todo-input form-control" placeholder="Enter item">
            </input>
            <span class="input-group-btn">
              <button type="button" class="btn btn-success todo-adder">
                 <span class="glyphicon glyphicon-plus"></span>
              </button>
           </span>
        </div>
    </div>
  </div>
  <hr/>
  <ul class="todo-list list-group">
  </ul>
</script>

<script type="text/template" id="item-template">
    <span class="up glyphicon glyphicon-arrow-up"></span>
    <span class="down glyphicon glyphicon-arrow-down"></span>
    <strong><%= desc %></strong>
    <span class="remove glyphicon glyphicon-remove"></span>
</script>

CSS

.remove {
   color : red;
}

.up,.down {
   color : green;   
}

.edit {
    color: blue;
}

JavaScript

TodoItem = Backbone.Model.extend({ 
    defaults: { 
        desc: "A todo item"
    }
});

TodoList = Backbone.Collection.extend({
    model : TodoItem
});

TodoView = Backbone.View.extend({
    el : "#page",
    
    className : "todo-list",
    
    renderAll : function(){
       _.each(this.collection.models, this.renderOne);
       this.listenTo(this.collection, "add", this.renderOne, this);
    },
    
    renderOne : function(model){
        var myview = new ItemView({model : model});
        var myIndex = this.collection.indexOf(model);
        if (myIndex == this.collection.length - 1){
         this.$el.find('.todo-list').append(myview.render().el);
        } 
        else {
         this.$el.find('.todo-list').find('.todo-item').eq(myIndex).before(myview.render().el);
        }
        myview.listenTo(this, 'destroy', myview.remove);
    },
    
    events : {
        "click .todo-adder" : "createItem"  
    },
    
    createItem : function(){
        var inputBox = this.$el.find(".todo-input");
        this.collection.add({desc: inputBox.val()});
        inputBox.val('');
    },
    
    render : function(){
     this.$el.html($("#todo-template").html()); 
     this.renderAll();
    }
});

ItemView = Backbone.View.extend({
    tagName : "li",
    
    className : "todo-item list-group-item",
    
    initialize : function(){
      this.listenTo(this.model, 'change', this.render);
      this.listenTo(this.model, 'destroy', this.remove);
      this.listenTo(this.model, 'remove', this.remove);
    },
    
    events: {
        "click .remove" : "remover",
        "click .up" : "move_up",
        "click .down" : "move_down"
    },
    
    move_up : function() {
        var myCollection = this.model.collection;
        var myModel = this.model;
        var thisIndex = myCollection.indexOf(myModel);
        var targetIndex = Math.max(0, thisIndex - 1);
        if (targetIndex != thisIndex){
            myCollection.remove(myModel);
           ...