Backbone Collection Bindable properties using Object.defineProperty

http://stackoverflow.com/questions/9027418/

by BarDev

HTML

<script src="https://raw.github.com/documentcloud/underscore/1.1.7/underscore.js"></script>
<script src="https://raw.github.com/documentcloud/backbone/0.5.3/backbone.js"></script>
<!--
This example will no execute to in IE8 since IE8 does not support
Object.defineProperty
-->

<div id="output">
    <ul></ul>
</div>

JavaScript

var log = {};
_.extend(log, Backbone.Events);

Backbone.Collection.prototype.bindableProperty = function(key, val){
    var self = this;
    Object.defineProperty(this, key,{
        configurable: false,
        get: function(){return val;},
        set: function(v){
            val = v;
            self.trigger("change:"+key, val)
        }
    })
};

var Car = Backbone.Model.extend({});
var Cars = Backbone.Collection.extend({
    model: Car,
    url: "scripts/data/Cars.json",

    initialize: function () {
        this.bindableProperty("isValid", false);
        
        this.bind("add", this.modelAdded, this);
        this.bind("reset", this.modelsAdded, this)
        this.bind("Car:_validate", this._validate, this);

        if (this.length > 0) {
            //Model passed in though the constructor will not be binded
            //so call modelsAdded
            this.modelsAdded(this);
        }
    },

   modelsAdded: function (collection) {
        this._isPending = true
        log.trigger("log", ["modelsAdded: " + collection.length]);
        collection.each(this.modelAdded, this); //Do nut remove "this" param.  It need when modelAdded gets called
        this._isPending = false
        this.trigger("Car:_validate")
    },

    modelAdded: function (model) {
        log.trigger("log", ["modelAdded: " + model.get("Model") + "; IsLocked: " + model.get("IsLocked")]);
        model.bind("change:IsLocked", this.modelIsLockedChanged, this);
        if (this._isPending == false) {
            this.trigger("Car:_validate")
        }
    },
    
    modelIsLockedChanged: function (model) {
        var _this = this
        log.trigger("log", ["modelIsLockedChanged:" + model.get("Model") + "; IsLocked: " + model.get("IsLocked")]);
        _this.trigger("Car:_validate")
    },

    _validate: function () {
        var isValid = true;
        this.each(function (model) {
            if (model.get("IsLocked") == false) {
                isValid = false
            }
 ...