Backbone.js Todo Example

by pmn4

HTML

<script src="https://rawgithub.com/jashkenas/underscore/1.5.2/underscore-min.js"></script>
<script src="https://rawgithub.com/jashkenas/backbone/1.0.0/backbone-min.js"></script>
<form>
<input />
<p>click a button to populate the input</p>
</form>
<p><strong>Which entity in Backbone should control this interaction?</strong></p>
<p>Have an answer for me?: <a href="http://stackoverflow.com/questions/22638431/backbone-events-scope" target="_blank">stackoverflow.com</a></p>

CSS

button { padding: 10px 30px; float: left; }
form:before, form:after { content: " "; display: table; }
form:after { clear: both; }

JavaScript

var Button = Backbone.Model.extend({
    defaults: {
        val: ""
    }
});
var ButtonView = Backbone.View.extend({
    model: Button,
    template: _.template('<button value="<%= val %>"><%= val %></button>'),
	events: {
		'click': 'selectDate'
	},
    initialize: function(options) {
        this.fnOnClick = options.fnOnClick;
    },
    render: function() {
        this.$el.html(this.template(this.model.attributes));
		return this;
	},
    selectDate: function(e) {
        e.preventDefault();
        /* I could simply do this:
         *    $("input").val(this.model.get("val"));
         * however, this View should have no
         * understanding of the world outside
         * of itself
         */
        
        // Instead, I went the callback route.
        if(typeof(this.fnOnClick) === "function") {
			this.fnOnClick(this.model.attributes);
        }
    }
});
var ButtonList = Backbone.Collection.extend({
    model: Button
});
var ButtonListView = Backbone.View.extend({
    className: "button-set",
    initialize: function(options) {
        this.fnOnClick = options.fnOnClick;
    },
    render: function() {
		var container = document.createDocumentFragment();
		this.collection.each(function(model) {
			var view = new ButtonView({
				model: model,
                fnOnClick: this.fnOnClick
			});
			container.appendChild(view.render().el);
		}, this);

		this.$el.empty().append(container);
		return this;
    }
});


var buttonSet = new ButtonListView({
    collection: new ButtonList([
        new Button({val: "A"}),
        new Button({val: "B"}),
        new Button({val: "C"})
    ]),
    fnOnClick: function(btn) {
        $("input").val(btn.val);
    }
});

$("form").append(buttonSet.render().el);