// Generated by CoffeeScript 1.3.3 /* knockback.js 0.15.2 (c) 2011 Kevin Malakoff. Knockback.js is freely distributable under the MIT license. See the following for full license details: https://github.com/kmalakoff/knockback/blob/master/LICENSE Dependencies: Knockout.js, Backbone.js, and Underscore.js. Optional dependency: Backbone.ModelRef.js. */ var Backbone, Knockback, kb, ko, _; if (typeof exports !== 'undefined') { Knockback = kb = exports; } else { this.Knockback = this.kb = {}; } Knockback.VERSION = '0.15.2'; _ = !this._ && (typeof require !== 'undefined') ? require('underscore') : this._; Backbone = !this.Backbone && (typeof require !== 'undefined') ? require('backbone') : this.Backbone; ko = !this.ko && (typeof require !== 'undefined') ? require('knockout') : this.ko; Knockback.locale_manager; Knockback.stats = { collection_observables: 0, view_models: 0 }; Knockback.stats_on = false; Knockback.utils = {}; Knockback.utils.legacyWarning = function(identifier, remove_version, message) { var _base; kb._legacy_warnings || (kb._legacy_warnings = {}); (_base = kb._legacy_warnings)[identifier] || (_base[identifier] = 0); kb._legacy_warnings[identifier]++; return console.warn("Legacy warning! '" + identifier + "' has been deprecated (will be removed in Knockback " + remove_version + "). " + message + "."); }; Knockback.utils.wrappedObservable = function(instance, observable) { if (arguments.length === 1) { if (!(instance && instance.__kb && instance.__kb.observable)) { throw new Error('Knockback: instance is not wrapping an observable'); } return instance.__kb.observable; } if (!instance) { throw new Error('Knockback: no instance for wrapping a observable'); } instance.__kb || (instance.__kb = {}); if (instance.__kb.observable && instance.__kb.observable.__kb) { instance.__kb.observable.__kb.instance = null; } instance.__kb.observable = observable; if (observable) { observable.__kb || (observable.__kb = {}); observable.__kb.instance = instance; } return observable; }; Knockback.wrappedObservable = function(instance) { kb.utils.legacyWarning('kb.wrappedObservable', '0.16.0', 'Please use kb.utils.wrappedObservable instead'); return kb.utils.wrappedObservable(instance); }; Knockback.utils.observableInstanceOf = function(observable, type) { if (!observable) { return false; } if (!(observable.__kb && observable.__kb.instance)) { return false; } return observable.__kb.instance instanceof type; }; Knockback.utils.wrappedModel = function(view_model, model) { if (arguments.length === 1) { if (view_model && view_model.__kb && view_model.__kb.hasOwnProperty('model')) { return view_model.__kb.model; } else { return view_model; } } if (!view_model) { throw new Error('Knockback: no view_model for wrapping a model'); } view_model.__kb || (view_model.__kb = {}); view_model.__kb.model = model; return model; }; Knockback.viewModelGetModel = Knockback.vmModel = function(view_model) { kb.utils.legacyWarning('kb.vmModel', '0.16.0', 'Please use kb.utils.wrappedModel instead'); return kb.utils.wrappedModel(view_model); }; Knockback.utils.setToDefault = function(obj) { var key, observable, _results; if (!obj) { return; } if (ko.isObservable(obj)) { return typeof obj.setToDefault === "function" ? obj.setToDefault() : void 0; } else if (_.isObject(obj)) { _results = []; for (key in obj) { observable = obj[key]; _results.push(observable && (key !== '__kb') ? kb.utils.setToDefault(observable) : void 0); } return _results; } }; Knockback.vmSetToDefault = function(view_model) { kb.utils.legacyWarning('kb.vmSetToDefault', '0.16.0', 'Please use kb.utils.release instead'); return kb.utils.setToDefault(view_model); }; Knockback.utils.release = function(obj) { var key, value; if (!obj) { return false; } if (ko.isObservable(obj) || (obj instanceof kb.Observables) || (typeof obj.release === 'function') || (typeof obj.destroy === 'function')) { if (obj.release) { obj.release(); } else if (obj.destroy) { obj.destroy(); } else if (obj.dispose) { obj.dispose(); } return true; } else if (_.isObject(obj) && !(typeof obj === 'function')) { for (key in obj) { value = obj[key]; if (!value || (key === '__kb')) { continue; } if (kb.utils.release(value)) { obj[key] = null; } } return true; } return false; }; Knockback.vmRelease = function(view_model) { kb.utils.legacyWarning('kb.vmRelease', '0.16.0', 'Please use kb.utils.release instead'); return kb.utils.release(view_model); }; Knockback.vmReleaseObservable = function(observable) { kb.utils.legacyWarning('kb.vmReleaseObservable', '0.16.0', 'Please use kb.utils.release instead'); return kb.utils.release(observable); }; kb.utils.optionsCreateClear = function(options) { delete options['create']; delete options['children']; delete options['view_model']; return delete options['view_model_create']; }; kb.utils.optionsCreateOverride = function(options, create_options) { kb.utils.optionsCreateClear(options); return _.extend(options, create_options); }; // Generated by CoffeeScript 1.3.3 /* knockback_ref_countable.js (c) 2012 Kevin Malakoff. Knockback.RefCountable is freely distributable under the MIT license. See the following for full license details: https://github.com/kmalakoff/knockback/blob/master/LICENSE */ Knockback.RefCountable = (function() { RefCountable.extend = Backbone.Model.extend; function RefCountable() { this.__kb || (this.__kb = {}); this.__kb.ref_count = 1; } RefCountable.prototype.__destroy = function() {}; RefCountable.prototype.retain = function() { if (this.__kb.ref_count <= 0) { throw new Error("RefCountable: ref_count is corrupt: " + this.__kb.ref_count); } this.__kb.ref_count++; return this; }; RefCountable.prototype.release = function() { if (this.__kb.ref_count <= 0) { throw new Error("RefCountable: ref_count is corrupt: " + this.__kb.ref_count); } this.__kb.ref_count--; if (!this.__kb.ref_count) { this.__destroy(); } return this; }; RefCountable.prototype.refCount = function() { return this.__kb.ref_count; }; return RefCountable; })(); // Generated by CoffeeScript 1.3.3 /* knockback_store.js (c) 2012 Kevin Malakoff. Knockback.Store is freely distributable under the MIT license. See the following for full license details: https://github.com/kmalakoff/knockback/blob/master/LICENSE */ Knockback.Store = (function() { function Store() { this.keys = []; this.values = []; } Store.prototype.destroy = function() { var index, value, _ref, _ref1; this.keys = null; _ref = this.values; for (index in _ref) { value = _ref[index]; if (!kb.utils.observableInstanceOf(value, kb.CollectionObservable)) { continue; } this.values[index] = null; while (value.refCount() > 0) { value.release(); } } _ref1 = this.values; for (index in _ref1) { value = _ref1[index]; if (!value) { continue; } this.values[index] = null; if (value instanceof kb.RefCountable) { while (value.refCount() > 0) { value.release(); } } else { kb.utils.release(value); } } return this.values = null; }; Store.prototype.registerValue = function(key, value) { var index; if (value instanceof kb.RefCountable) { value.retain(); } index = _.indexOf(this.keys, key); if (index >= 0) { this.values[index] = value; } else { this.keys.push(key); this.values.push(value); } return value; }; Store.prototype.resolveValue = function(key, create_fn, args) { var index, value; index = _.indexOf(this.keys, key); if (index >= 0) { if (this.values[index]) { if ((this.values[index] instanceof kb.RefCountable) && (this.values[index].refCount() <= 0)) { this.values[index] = null; } else { if (this.values[index] instanceof kb.RefCountable) { return this.values[index].retain(); } else { return this.values[index]; } } } } else { index = this.keys.length; this.keys.push(key); this.values.push(void 0); } value = create_fn.apply(null, Array.prototype.slice.call(arguments, 2)); if (this.keys[index] !== key) { this.registerValue(key, value); } else if (!this.values[index]) { if (value instanceof kb.RefCountable) { value.retain(); } this.values[index] = value; } return value; }; Store.prototype.releaseValue = function(value) { var index; if (!(value instanceof kb.RefCountable)) { return; } value.release(); if (value.refCount() > 0) { return; } index = _.indexOf(this.values, value); if (!(index >= 0)) { return; } return this.values[index] = 0; }; Store.prototype.addResolverToOptions = function(options, key) { return _.extend(options, { store: this, store_key: key }); }; Store.resolveFromOptions = function(options, value) { if (!(options.store && options.store_key)) { return; } return options.store.registerValue(options.store_key, value); }; return Store; })(); // Generated by CoffeeScript 1.3.3 /* knockback_collection_observable.js (c) 2011 Kevin Malakoff. Knockback.CollectionObservable is freely distributable under the MIT license. See the following for full license details: https://github.com/kmalakoff/knockback/blob/master/LICENSE */ var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Knockback.CollectionObservable = (function(_super) { __extends(CollectionObservable, _super); function CollectionObservable(collection, options) { var bind_model_changes, observable, _this = this; if (options == null) { options = {}; } if (!collection) { throw new Error('CollectionObservable: collection is missing'); } CollectionObservable.__super__.constructor.apply(this, arguments); if (Knockback.stats_on) { kb.stats.collection_observables++; } if (ko.isObservable(options) && options.hasOwnProperty('indexOf')) { kb.utils.legacyWarning('kb.collectionObservable with an external ko.observableArray', '0.16.0', 'Please use the kb.collectionObservable directly instead of passing a ko.observableArray'); observable = kb.utils.wrappedObservable(this, options); options = arguments[2] || {}; bind_model_changes = true; } else { observable = kb.utils.wrappedObservable(this, ko.observableArray([])); } if (!options.store_skip_resolve) { kb.Store.resolveFromOptions(options, kb.utils.wrappedObservable(this)); } if (options.store) { this.__kb.store = options.store; } else { this.__kb.store = new kb.Store(); this.__kb.store_is_owned = true; } if (options.hasOwnProperty('view_model')) { if (!options.view_model) { throw new Error('Knockback.CollectionObservable: options.view_model is empty'); } this.view_model_create_fn = options.view_model; this.view_model_create_with_new = true; } else if (options.hasOwnProperty('view_model_constructor')) { if (!options.view_model_constructor) { throw new Error('Knockback.CollectionObservable: options.view_model_constructor is empty'); } kb.utils.legacyWarning('kb.collectionObservable option view_model_constructor', '0.16.0', 'Please use view_model option instead'); this.view_model_create_fn = options.view_model_constructor; this.view_model_create_with_new = true; } else if (options.hasOwnProperty('view_model_create')) { if (!options.view_model_create) { throw new Error('Knockback.CollectionObservable: options.view_model_create is empty'); } this.view_model_create_fn = options.view_model_create; } else if (options.hasOwnProperty('create')) { if (!options.create) { throw new Error('Knockback.CollectionObservable: options.create is empty'); } this.view_model_create_fn = options.create; } this.sort_attribute = options.sort_attribute; this.sorted_index = options.sorted_index; this.__kb._onCollectionReset = _.bind(this._onCollectionReset, this); this.__kb._onCollectionResort = _.bind(this._onCollectionResort, this); this.__kb._onModelAdd = _.bind(this._onModelAdd, this); this.__kb._onModelRemove = _.bind(this._onModelRemove, this); this.__kb._onModelChange = _.bind(this._onModelChange, this); if (bind_model_changes && collection) { collection.bind('change', function() { return kb.utils.wrappedObservable(_this).valueHasMutated(); }); } observable.retain = _.bind(this.retain, this); observable.refCount = _.bind(this.refCount, this); observable.release = _.bind(this.release, this); observable.collection = _.bind(this.collection, this); observable.viewModelByModel = _.bind(this.viewModelByModel, this); observable.sortedIndex = _.bind(this.sortedIndex, this); observable.sortAttribute = _.bind(this.sortAttribute, this); observable.hasViewModels = _.bind(this.hasViewModels, this); observable.bind = _.bind(this.bind, this); observable.unbind = _.bind(this.unbind, this); observable.trigger = _.bind(this.trigger, this); this.collection(collection, { silent: true, defer: options.defer }); return observable; } CollectionObservable.prototype.__destroy = function() { this.collection(null); if (this.hasViewModels() && this.__kb.store_is_owned) { this.__kb.store.destroy(); this.__kb.store = null; } this.view_model_create_fn = null; this.__kb.collection = null; kb.utils.wrappedObservable(this, null); CollectionObservable.__super__.__destroy.apply(this, arguments); if (Knockback.stats_on) { return kb.stats.collection_observables--; } }; CollectionObservable.prototype.retain = function() { CollectionObservable.__super__.retain.apply(this, arguments); return kb.utils.wrappedObservable(this); }; CollectionObservable.prototype.release = function() { var observable; observable = kb.utils.wrappedObservable(this); CollectionObservable.__super__.release.apply(this, arguments); return observable; }; CollectionObservable.prototype.collection = function(collection, options) { var observable, _base, _base1; observable = kb.utils.wrappedObservable(this); if (arguments.length === 0) { observable(); return this.__kb.collection; } if (collection === this.__kb.collection) { return; } if (this.__kb.collection) { this._clear(); this._collectionUnbind(this.__kb.collection); if (typeof (_base = this.__kb.collection).release === "function") { _base.release(); } this.__kb.collection = null; } this.__kb.collection = collection; if (this.__kb.collection) { if (typeof (_base1 = this.__kb.collection).retain === "function") { _base1.retain(); } this._collectionBind(this.__kb.collection); return this.sortedIndex(this.sorted_index, this.sort_attribute, options); } }; CollectionObservable.prototype.sortedIndex = function(sorted_index, sort_attribute, options) { var _resync, _this = this; if (options == null) { options = {}; } if (sorted_index) { this.sorted_index = sorted_index; this.sort_attribute = sort_attribute; } else if (sort_attribute) { this.sort_attribute = sort_attribute; this.sorted_index = this._sortAttributeFn(sort_attribute); } else { this.sort_attribute = null; this.sorted_index = null; } _resync = function() { var observable; observable = kb.utils.wrappedObservable(_this); if ((_this.__kb.collection.models.length === 0) && (observable().length === 0)) { return; } _this._collectionResync(true); if (!options.silent) { return _this.trigger('resort', observable()); } }; if (options.defer) { _.defer(_resync); } else { _resync(); } return this; }; CollectionObservable.prototype.sortAttribute = function(sort_attribute, sorted_index, silent) { return this.sortedIndex(sorted_index, sort_attribute, silent); }; CollectionObservable.prototype.viewModelByModel = function(model) { var id_attribute, observable; if (!this.hasViewModels()) { return null; } observable = kb.utils.wrappedObservable(this); id_attribute = model.hasOwnProperty(model.idAttribute) ? model.idAttribute : 'cid'; return _.find(observable(), function(test) { return test.__kb.model[id_attribute] === model[id_attribute]; }); }; CollectionObservable.prototype.hasViewModels = function() { return !!this.view_model_create_fn; }; CollectionObservable.prototype._collectionBind = function(collection) { var event, _i, _j, _len, _len1, _ref, _ref1; if (!collection) { return; } collection.bind('reset', this.__kb._onCollectionReset); if (!this.sorted_index) { collection.bind('resort', this.__kb._onCollectionResort); } _ref = ['new', 'add']; for (_i = 0, _len = _ref.length; _i < _len; _i++) { event = _ref[_i]; collection.bind(event, this.__kb._onModelAdd); } _ref1 = ['remove', 'destroy']; for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { event = _ref1[_j]; collection.bind(event, this.__kb._onModelRemove); } return collection.bind('change', this.__kb._onModelChange); }; CollectionObservable.prototype._collectionUnbind = function(collection) { var event, _i, _j, _len, _len1, _ref, _ref1; if (!collection) { return; } collection.unbind('reset', this.__kb._onCollectionReset); if (!this.sorted_index) { collection.unbind('resort', this.__kb._onCollectionResort); } _ref = ['new', 'add']; for (_i = 0, _len = _ref.length; _i < _len; _i++) { event = _ref[_i]; collection.unbind(event, this.__kb._onModelAdd); } _ref1 = ['remove', 'destroy']; for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { event = _ref1[_j]; collection.unbind(event, this.__kb._onModelRemove); } return collection.unbind('change', this.__kb._onModelChange); }; CollectionObservable.prototype._onCollectionReset = function() { return this._collectionResync(); }; CollectionObservable.prototype._onCollectionResort = function(model_or_models) { var observable; if (this.sorted_index) { throw new Error("CollectionObservable: collection sorted_index unexpected"); } if (_.isArray(model_or_models)) { observable = kb.utils.wrappedObservable(this); return this.trigger('resort', observable()); } else { return this._onModelResort(model_or_models); } }; CollectionObservable.prototype._onModelAdd = function(model) { var add_index, observable, target; target = this.hasViewModels() ? this._createTarget(model) : model; observable = kb.utils.wrappedObservable(this); if (this.sorted_index) { add_index = this.sorted_index(observable(), target); } else { add_index = this.__kb.collection.indexOf(model); } observable.splice(add_index, 0, target); return this.trigger('add', target, observable()); }; CollectionObservable.prototype._onModelRemove = function(model) { var observable, target; target = this.hasViewModels() ? this.viewModelByModel(model) : model; if (!target) { return; } observable = kb.utils.wrappedObservable(this); observable.remove(target); this.trigger('remove', target, observable); if (this.hasViewModels()) { return this.__kb.store.releaseValue(target); } }; CollectionObservable.prototype._onModelChange = function(model) { if (this.sorted_index && (!this.sort_attribute || model.hasChanged(this.sort_attribute))) { return this._onModelResort(model); } }; CollectionObservable.prototype._onModelResort = function(model) { var new_index, observable, previous_index, sorted_targets, target; observable = kb.utils.wrappedObservable(this); target = this.hasViewModels() ? this.viewModelByModel(model) : model; previous_index = observable.indexOf(target); if (this.sorted_index) { sorted_targets = _.clone(observable()); sorted_targets.splice(previous_index, 1); new_index = this.sorted_index(sorted_targets, target); } else { new_index = this.__kb.collection.indexOf(model); } if (previous_index === new_index) { return; } observable.splice(previous_index, 1); observable.splice(new_index, 0, target); return this.trigger('resort', target, observable(), new_index); }; CollectionObservable.prototype._clear = function(silent) { var observable, target, targets, _i, _len, _results; observable = kb.utils.wrappedObservable(this); if (!silent) { this.trigger('remove', observable()); } targets = observable.removeAll(); if (this.hasViewModels()) { _results = []; for (_i = 0, _len = targets.length; _i < _len; _i++) { target = targets[_i]; _results.push(this.__kb.store.releaseValue(target)); } return _results; } }; CollectionObservable.prototype._collectionResync = function(silent) { var add_index, model, observable, target, targets, _i, _len, _ref, _this = this; this._clear(silent); observable = kb.utils.wrappedObservable(this); if (this.sorted_index) { targets = []; _ref = this.__kb.collection.models; for (_i = 0, _len = _ref.length; _i < _len; _i++) { model = _ref[_i]; target = this._createTarget(model); add_index = this.sorted_index(targets, target); targets.splice(add_index, 0, target); } } else { targets = this.hasViewModels() ? _.map(this.__kb.collection.models, function(model) { return _this._createTarget(model); }) : _.clone(this.__kb.collection.models); } observable(targets); if (!silent) { return this.trigger('add', observable()); } }; CollectionObservable.prototype._sortAttributeFn = function(sort_attribute) { if (this.hasViewModels()) { return function(view_models, model) { return _.sortedIndex(view_models, model, function(test) { return kb.utils.wrappedModel(test).get(sort_attribute); }); }; } else { return function(models, model) { return _.sortedIndex(models, model, function(test) { return test.get(sort_attribute); }); }; } }; CollectionObservable.prototype._createTarget = function(model) { var create_fn, _this = this; create_fn = function() { var observable, options, view_model; options = _this.__kb.store.addResolverToOptions({}, model); observable = kb.utils.wrappedObservable(_this); view_model = _this.view_model_create_with_new ? new _this.view_model_create_fn(model, options, observable) : _this.view_model_create_fn(model, options, observable); kb.utils.wrappedModel(view_model, model); return view_model; }; if (this.hasViewModels()) { return this.__kb.store.resolveValue(model, create_fn); } else { return model; } }; return CollectionObservable; })(kb.RefCountable); __extends(Knockback.CollectionObservable.prototype, Backbone.Events); Knockback.collectionObservable = function(collection, options, legacy) { return new Knockback.CollectionObservable(collection, options, legacy); }; Knockback.sortedIndexWrapAttr = Knockback.siwa = function(attribute_name, wrapper_constructor) { return function(models, model) { return _.sortedIndex(models, model, function(test) { return new wrapper_constructor(kb.utils.wrappedModel(test).get(attribute_name)); }); }; }; // Generated by CoffeeScript 1.3.3 /* knockback_default_wrapper.js (c) 2011 Kevin Malakoff. Knockback.DefaultWrapper is freely distributable under the MIT license. See the following for full license details: https://github.com/kmalakoff/knockback/blob/master/LICENSE */ if (!this.Knockback) { throw new Error('Knockback: Dependency alert! knockback_core.js must be included before this file'); } Knockback.DefaultWrapper = (function() { function DefaultWrapper(target_observable, default_value_observable) { var observable, _this = this; this.default_value_observable = default_value_observable; this.__kb = {}; observable = kb.utils.wrappedObservable(this, ko.dependentObservable({ read: function() { var current_default, current_target; current_target = ko.utils.unwrapObservable(target_observable()); current_default = ko.utils.unwrapObservable(_this.default_value_observable); if (!current_target) { return current_default; } else { return current_target; } }, write: function(value) { return target_observable(value); } })); observable.destroy = _.bind(this.destroy, this); observable.setToDefault = _.bind(this.setToDefault, this); return observable; } DefaultWrapper.prototype.destroy = function() { kb.utils.wrappedObservable(this, null); return this.default_value = null; }; DefaultWrapper.prototype.setToDefault = function() { var observable; observable = kb.utils.wrappedObservable(this); return observable(this.default_value_observable); }; return DefaultWrapper; })(); Knockback.defaultWrapper = function(target, default_value) { return new Knockback.DefaultWrapper(target, default_value); }; // Generated by CoffeeScript 1.3.3 /* knockback_formatted_observable.js (c) 2011 Kevin Malakoff. Knockback.FormattedObservable is freely distributable under the MIT license. See the following for full license details: https://github.com/kmalakoff/knockback/blob/master/LICENSE */ Knockback.toFormattedString = function(format) { var arg, args, index, parameter_index, result, value; result = format.slice(); args = Array.prototype.slice.call(arguments, 1); for (index in args) { arg = args[index]; value = ko.utils.unwrapObservable(arg); if (!value) { value = ''; } parameter_index = format.indexOf("\{" + index + "\}"); while (parameter_index >= 0) { result = result.replace("{" + index + "}", value); parameter_index = format.indexOf("\{" + index + "\}", parameter_index + 1); } } return result; }; Knockback.parseFormattedString = function(string, format) { var count, format_indices_to_matched_indices, index, match_index, matches, parameter_count, parameter_index, positions, regex, regex_string, results, sorted_positions, _i, _results; regex_string = format.slice(); index = 0; parameter_count = 0; positions = {}; while (regex_string.search("\\{" + index + "\\}") >= 0) { parameter_index = format.indexOf("\{" + index + "\}"); while (parameter_index >= 0) { regex_string = regex_string.replace("\{" + index + "\}", '(.*)'); positions[parameter_index] = index; parameter_count++; parameter_index = format.indexOf("\{" + index + "\}", parameter_index + 1); } index++; } count = index; regex = new RegExp(regex_string); matches = regex.exec(string); if (matches) { matches.shift(); } if (!matches || (matches.length !== parameter_count)) { return _.map((function() { _results = []; for (var _i = 1; 1 <= count ? _i <= count : _i >= count; 1 <= count ? _i++ : _i--){ _results.push(_i); } return _results; }).apply(this), function() { return ''; }); } sorted_positions = _.sortBy(_.keys(positions), function(parameter_index, format_index) { return parseInt(parameter_index, 10); }); format_indices_to_matched_indices = {}; for (match_index in sorted_positions) { parameter_index = sorted_positions[match_index]; index = positions[parameter_index]; if (format_indices_to_matched_indices.hasOwnProperty(index)) { continue; } format_indices_to_matched_indices[index] = match_index; } results = []; index = 0; while (index < count) { results.push(matches[format_indices_to_matched_indices[index]]); index++; } return results; }; Knockback.FormattedObservable = (function() { function FormattedObservable(format, args) { var observable, observable_args; this.__kb = {}; if (_.isArray(args)) { format = format; observable_args = args; } else { observable_args = Array.prototype.slice.call(arguments, 1); } observable = kb.utils.wrappedObservable(this, ko.dependentObservable({ read: function() { var arg, _i, _len; args = [ko.utils.unwrapObservable(format)]; for (_i = 0, _len = observable_args.length; _i < _len; _i++) { arg = observable_args[_i]; args.push(ko.utils.unwrapObservable(arg)); } return kb.toFormattedString.apply(null, args); }, write: function(value) { var index, matches, max_count, _results; matches = kb.parseFormattedString(value, ko.utils.unwrapObservable(format)); max_count = Math.min(observable_args.length, matches.length); index = 0; _results = []; while (index < max_count) { observable_args[index](matches[index]); _results.push(index++); } return _results; } })); return observable; } FormattedObservable.prototype.destroy = function() { return kb.utils.wrappedObservable(this, null); }; return FormattedObservable; })(); Knockback.formattedObservable = function(format, args) { return new Knockback.FormattedObservable(format, Array.prototype.slice.call(arguments, 1)); }; // Generated by CoffeeScript 1.3.3 /* knockback_localized_observable.js (c) 2011 Kevin Malakoff. Knockback.LocalizedObservable is freely distributable under the MIT license. See the following for full license details: https://github.com/kmalakoff/knockback/blob/master/LICENSE */ Knockback.LocalizedObservable = (function() { LocalizedObservable.extend = Backbone.Model.extend; function LocalizedObservable(value, options, view_model) { var observable; this.value = value; this.options = options != null ? options : {}; this.view_model = view_model != null ? view_model : {}; if (!(this.options.read || this.read)) { throw new Error('LocalizedObservable: options.read is missing'); } if (this.options.read && this.read) { throw new Error('LocalizedObservable: options.read and read class function exist. You need to choose one.'); } if (this.options.write && this.write) { throw new Error('LocalizedObservable: options.write and write class function exist. You need to choose one.'); } if (!kb.locale_manager) { throw new Error('LocalizedObservable: Knockback.locale_manager is not defined'); } this.__kb = {}; this.__kb._onLocaleChange = _.bind(this._onLocaleChange, this); if (this.value) { value = ko.utils.unwrapObservable(this.value); } this.__kb.value_observable = ko.observable(!value ? this._getDefaultValue() : this.read.call(this, value, null)); if (this.write && !(typeof this.write === 'function')) { throw new Error('LocalizedObservable: options.write is not a function for read_write model attribute'); } observable = kb.utils.wrappedObservable(this, ko.dependentObservable({ read: _.bind(this._onGetValue, this), write: this.write ? _.bind(this._onSetValue, this) : (function() { throw new Error("Knockback.LocalizedObservable: value is read only"); }), owner: this.view_model })); observable.destroy = _.bind(this.destroy, this); observable.observedValue = _.bind(this.observedValue, this); observable.setToDefault = _.bind(this.setToDefault, this); observable.resetToCurrent = _.bind(this.resetToCurrent, this); kb.locale_manager.bind('change', this.__kb._onLocaleChange); return observable; } LocalizedObservable.prototype.destroy = function() { kb.locale_manager.unbind('change', this.__kb._onLocaleChange); this.__kb.value_observable = null; kb.utils.wrappedObservable(this).dispose(); kb.utils.wrappedObservable(this, null); this.options = {}; this.view_model = null; return this.__kb = null; }; LocalizedObservable.prototype.setToDefault = function() { var current_value, default_value; if (!this["default"]) { return; } default_value = this._getDefaultValue(); current_value = this.__kb.value_observable(); if (current_value !== default_value) { return this._onSetValue(default_value); } else { return this.__kb.value_observable.valueHasMutated(); } }; LocalizedObservable.prototype.resetToCurrent = function() { this.__kb.value_observable(null); return this._onSetValue(this._getCurrentValue()); }; LocalizedObservable.prototype.observedValue = function(value) { if (arguments.length === 0) { return this.value; } this.value = value; this._onLocaleChange(); return this; }; LocalizedObservable.prototype._getDefaultValue = function() { if (!this["default"]) { return ''; } if (typeof this["default"] === 'function') { return this["default"](); } else { return this["default"]; } }; LocalizedObservable.prototype._getCurrentValue = function() { var observable; observable = kb.utils.wrappedObservable(this); if (!(this.value && observable)) { return this._getDefaultValue(); } return this.read.call(this, ko.utils.unwrapObservable(this.value)); }; LocalizedObservable.prototype._onGetValue = function() { if (this.value) { ko.utils.unwrapObservable(this.value); } return this.__kb.value_observable(); }; LocalizedObservable.prototype._onSetValue = function(value) { this.write.call(this, value, ko.utils.unwrapObservable(this.value)); value = this.read.call(this, ko.utils.unwrapObservable(this.value)); this.__kb.value_observable(value); if (this.options.onChange) { return this.options.onChange(value); } }; LocalizedObservable.prototype._onLocaleChange = function() { var value; value = this.read.call(this, ko.utils.unwrapObservable(this.value)); this.__kb.value_observable(value); if (this.options.onChange) { return this.options.onChange(value); } }; return LocalizedObservable; })(); Knockback.localizedObservable = function(value, options, view_model) { return new Knockback.LocalizedObservable(value, options, view_model); }; // Generated by CoffeeScript 1.3.3 /* knockback_observable.js (c) 2011 Kevin Malakoff. Knockback.Observable is freely distributable under the MIT license. See the following for full license details: https://github.com/kmalakoff/knockback/blob/master/LICENSE */ Knockback.Observable = (function() { function Observable(model, mapping_info, view_model) { var observable, _this = this; this.model = model; this.mapping_info = mapping_info; this.view_model = view_model != null ? view_model : {}; if (!this.model) { throw new Error('Observable: model is missing'); } if (!this.mapping_info) { throw new Error('Observable: mapping_info is missing'); } if (_.isString(this.mapping_info) || ko.isObservable(this.mapping_info)) { this.mapping_info = { key: this.mapping_info }; } if (!this.mapping_info.key) { throw new Error('Observable: mapping_info.key is missing'); } this.__kb = {}; this.__kb._onModelChange = _.bind(this._onModelChange, this); this.__kb._onModelLoaded = _.bind(this._onModelLoaded, this); this.__kb._onModelUnloaded = _.bind(this._onModelUnloaded, this); if (this.mapping_info.hasOwnProperty('write') && _.isBoolean(this.mapping_info.write)) { this.mapping_info = _.clone(this.mapping_info); this.mapping_info.read_only = !this.mapping_info.write; } if (Backbone.ModelRef && (this.model instanceof Backbone.ModelRef)) { this.model_ref = this.model; this.model_ref.retain(); this.model_ref.bind('loaded', this.__kb._onModelLoaded); this.model_ref.bind('unloaded', this.__kb._onModelUnloaded); this.model = this.model_ref.getModel(); } this.__kb.value_observable = ko.observable(); if (this.mapping_info.localizer) { this.__kb.localizer = new this.mapping_info.localizer(this._getCurrentValue()); } observable = kb.utils.wrappedObservable(this, ko.dependentObservable({ read: _.bind(this._onGetValue, this), write: this.mapping_info.read_only ? (function() { throw new Error("Knockback.Observable: " + _this.mapping_info.key + " is read only"); }) : _.bind(this._onSetValue, this), owner: this.view_model })); observable.destroy = _.bind(this.destroy, this); observable.setToDefault = _.bind(this.setToDefault, this); if (!this.model_ref || this.model_ref.isLoaded()) { this.model.bind('change', this.__kb._onModelChange); } return observable; } Observable.prototype.destroy = function() { this.__kb.value_observable = null; kb.utils.wrappedObservable(this).dispose(); kb.utils.wrappedObservable(this, null); if (this.model) { this.__kb._onModelUnloaded(this.model); } if (this.model_ref) { this.model_ref.unbind('loaded', this.__kb._onModelLoaded); this.model_ref.unbind('unloaded', this.__kb._onModelUnloaded); this.model_ref.release(); this.model_ref = null; } this.mapping_info = null; this.view_model = null; return this.__kb = null; }; Observable.prototype.setToDefault = function() { var value; value = this._getDefaultValue(); if (this.__kb.localizer) { this.__kb.localizer.observedValue(value); value = this.__kb.localizer(); } return this.__kb.value_observable(value); }; Observable.prototype._getDefaultValue = function() { if (!this.mapping_info.hasOwnProperty('default')) { return ''; } if (typeof this.mapping_info["default"] === 'function') { return this.mapping_info["default"](); } else { return this.mapping_info["default"]; } }; Observable.prototype._getCurrentValue = function() { var arg, args, key, _i, _len, _ref; if (!this.model) { return this._getDefaultValue(); } key = ko.utils.unwrapObservable(this.mapping_info.key); args = [key]; if (!_.isUndefined(this.mapping_info.args)) { if (_.isArray(this.mapping_info.args)) { _ref = this.mapping_info.args; for (_i = 0, _len = _ref.length; _i < _len; _i++) { arg = _ref[_i]; args.push(ko.utils.unwrapObservable(arg)); } } else { args.push(ko.utils.unwrapObservable(this.mapping_info.args)); } } if (this.mapping_info.read) { return this.mapping_info.read.apply(this.view_model, args); } else { return this.model.get.apply(this.model, args); } }; Observable.prototype._onGetValue = function() { var arg, value, _i, _len, _ref; this.__kb.value_observable(); ko.utils.unwrapObservable(this.mapping_info.key); if (!_.isUndefined(this.mapping_info.args)) { if (_.isArray(this.mapping_info.args)) { _ref = this.mapping_info.args; for (_i = 0, _len = _ref.length; _i < _len; _i++) { arg = _ref[_i]; ko.utils.unwrapObservable(arg); } } else { ko.utils.unwrapObservable(this.mapping_info.args); } } value = this._getCurrentValue(); if (this.__kb.localizer) { this.__kb.localizer.observedValue(value); value = this.__kb.localizer(); } return value; }; Observable.prototype._onSetValue = function(value) { var arg, args, set_info, _i, _len, _ref; if (this.__kb.localizer) { this.__kb.localizer(value); value = this.__kb.localizer.observedValue(); } if (this.model) { set_info = {}; set_info[ko.utils.unwrapObservable(this.mapping_info.key)] = value; args = typeof this.mapping_info.write === 'function' ? [value] : [set_info]; if (!_.isUndefined(this.mapping_info.args)) { if (_.isArray(this.mapping_info.args)) { _ref = this.mapping_info.args; for (_i = 0, _len = _ref.length; _i < _len; _i++) { arg = _ref[_i]; args.push(ko.utils.unwrapObservable(arg)); } } else { args.push(ko.utils.unwrapObservable(this.mapping_info.args)); } } if (typeof this.mapping_info.write === 'function') { this.mapping_info.write.apply(this.view_model, args); } else { this.model.set.apply(this.model, args); } } if (this.__kb.localizer) { return this.__kb.value_observable(this.__kb.localizer()); } else { return this.__kb.value_observable(value); } }; Observable.prototype._modelBind = function(model) { if (!model) { return; } model.bind('change', this.__kb._onModelChange); if (Backbone.RelationalModel && (model instanceof Backbone.RelationalModel)) { model.bind('add', this.__kb._onModelChange); model.bind('remove', this.__kb._onModelChange); return model.bind('update', this.__kb._onModelChange); } }; Observable.prototype._modelUnbind = function(model) { if (!model) { return; } model.unbind('change', this.__kb._onModelChange); if (Backbone.RelationalModel && (model instanceof Backbone.RelationalModel)) { model.unbind('add', this.__kb._onModelChange); model.unbind('remove', this.__kb._onModelChange); return model.unbind('update', this.__kb._onModelChange); } }; Observable.prototype._onModelLoaded = function(model) { this.model = model; this._modelBind(model); return this._updateValue(); }; Observable.prototype._onModelUnloaded = function(model) { if (this.__kb.localizer && this.__kb.localizer.destroy) { this.__kb.localizer.destroy(); this.__kb.localizer = null; } this._modelUnbind(model); return this.model = null; }; Observable.prototype._onModelChange = function() { if ((this.model && this.model.hasChanged) && !this.model.hasChanged(ko.utils.unwrapObservable(this.mapping_info.key))) { return; } return this._updateValue(); }; Observable.prototype._updateValue = function() { var value; value = this._getCurrentValue(); if (this.__kb.localizer) { this.__kb.localizer.observedValue(value); value = this.__kb.localizer(); } return this.__kb.value_observable(value); }; return Observable; })(); Knockback.observable = function(model, mapping_info, view_model) { return new Knockback.Observable(model, mapping_info, view_model); }; // Generated by CoffeeScript 1.3.3 /* knockback_observables.js (c) 2011 Kevin Malakoff. Knockback.Observables is freely distributable under the MIT license. See the following for full license details: https://github.com/kmalakoff/knockback/blob/master/LICENSE */ Knockback.Observables = (function() { function Observables(model, mappings_info, view_model, options_or_read_only) { var is_string, mapping_info, property_name, read_only, _ref, _ref1; if (!model) { throw new Error('Observables: model is missing'); } if (!mappings_info || !_.isObject(mappings_info)) { throw new Error('Observables: mappings_info is missing'); } this.__kb || (this.__kb = {}); this.__kb.model = model; this.__kb.mappings_info = mappings_info; this.__kb.view_model = _.isUndefined(view_model) ? this : view_model; if (!_.isUndefined(options_or_read_only) && options_or_read_only.hasOwnProperty('write')) { kb.utils.legacyWarning('Knockback.Observables option.write', '0.16.0', 'Now default is writable so only supply read_only as required'); options_or_read_only.read_only = !options_or_read_only.write; delete options_or_read_only['write']; } if (!_.isUndefined(options_or_read_only)) { read_only = _.isBoolean(options_or_read_only) ? options_or_read_only : options_or_read_only.read_only; _ref = this.__kb.mappings_info; for (property_name in _ref) { mapping_info = _ref[property_name]; is_string = _.isString(mapping_info); if (is_string) { mapping_info = !_.isUndefined(read_only) ? { key: mapping_info, read_only: read_only } : { key: mapping_info }; } else if (!_.isUndefined(read_only) && !(mapping_info.hasOwnProperty('read_only') || mapping_info.hasOwnProperty('write'))) { mapping_info.read_only = read_only; } if (!mapping_info.hasOwnProperty('key')) { mapping_info.key = property_name; } this[property_name] = this.__kb.view_model[property_name] = kb.observable(this.__kb.model, mapping_info, this.__kb.view_model); } } else { _ref1 = this.__kb.mappings_info; for (property_name in _ref1) { mapping_info = _ref1[property_name]; if (mapping_info.hasOwnProperty('write')) { kb.utils.legacyWarning('Knockback.Observables option.write', '0.16.0', 'Now default is writable so only supply read_only as required'); } if (!mapping_info.hasOwnProperty('key')) { mapping_info.key = property_name; } this[property_name] = this.__kb.view_model[property_name] = kb.observable(this.__kb.model, mapping_info, this.__kb.view_model); } } } Observables.prototype.destroy = function() { var mapping_info, property_name, _ref; _ref = this.__kb.mappings_info; for (property_name in _ref) { mapping_info = _ref[property_name]; if (this.__kb.view_model[property_name]) { this.__kb.view_model[property_name].destroy(); } this.__kb.view_model[property_name] = null; this[property_name] = null; } this.__kb.view_model = null; this.__kb.mappings_info = null; return this.__kb.model = null; }; Observables.prototype.setToDefault = function() { var mapping_info, property_name, _ref, _results; _ref = this.__kb.mappings_info; _results = []; for (property_name in _ref) { mapping_info = _ref[property_name]; _results.push(this.__kb.view_model[property_name].setToDefault()); } return _results; }; return Observables; })(); Knockback.observables = function(model, mappings_info, view_model, options) { return new Knockback.Observables(model, mappings_info, view_model, options); }; // Generated by CoffeeScript 1.3.3 /* knockback_triggered_observable.js (c) 2011 Kevin Malakoff. Knockback.Observable is freely distributable under the MIT license. See the following for full license details: https://github.com/kmalakoff/knockback/blob/master/LICENSE */ Knockback.TriggeredObservable = (function() { function TriggeredObservable(model, event_name) { var observable; this.model = model; this.event_name = event_name; if (!this.model) { throw new Error('Observable: model is missing'); } if (!this.event_name) { throw new Error('Observable: event_name is missing'); } this.__kb = {}; this.__kb._onValueChange = _.bind(this._onValueChange, this); this.__kb._onModelLoaded = _.bind(this._onModelLoaded, this); this.__kb._onModelUnloaded = _.bind(this._onModelUnloaded, this); if (Backbone.ModelRef && (this.model instanceof Backbone.ModelRef)) { this.model_ref = this.model; this.model_ref.retain(); this.model_ref.bind('loaded', this.__kb._onModelLoaded); this.model_ref.bind('unloaded', this.__kb._onModelUnloaded); this.model = this.model_ref.getModel(); } this.__kb.value_observable = ko.observable(); observable = kb.utils.wrappedObservable(this, ko.dependentObservable(_.bind(this._onGetValue, this))); observable.destroy = _.bind(this.destroy, this); if (!this.model_ref || this.model_ref.isLoaded()) { this._onModelLoaded(this.model); } return observable; } TriggeredObservable.prototype.destroy = function() { kb.utils.wrappedObservable(this).dispose(); kb.utils.wrappedObservable(this, null); this.__kb.value_observable = null; if (this.model) { this._onModelUnloaded(this.model); } if (this.model_ref) { this.model_ref.unbind('loaded', this.__kb._onModelLoaded); this.model_ref.unbind('unloaded', this.__kb._onModelUnloaded); this.model_ref.release(); this.model_ref = null; } this.options = null; this.view_model = null; return this.__kb = null; }; TriggeredObservable.prototype._onGetValue = function() { return this.__kb.value_observable(); }; TriggeredObservable.prototype._onModelLoaded = function(model) { this.model = model; this.model.bind(this.event_name, this.__kb._onValueChange); return this._onValueChange(); }; TriggeredObservable.prototype._onModelUnloaded = function() { if (this.__kb.localizer && this.__kb.localizer.destroy) { this.__kb.localizer.destroy(); this.__kb.localizer = null; } this.model.unbind(this.event_name, this.__kb._onValueChange); return this.model = null; }; TriggeredObservable.prototype._onValueChange = function() { var current_value; current_value = this.__kb.value_observable(); if (current_value !== this.model) { return this.__kb.value_observable(this.model); } else { return this.__kb.value_observable.valueHasMutated(); } }; return TriggeredObservable; })(); Knockback.triggeredObservable = function(model, event_name) { return new Knockback.TriggeredObservable(model, event_name); }; // Generated by CoffeeScript 1.3.3 /* knockback_attribute_connectors.js (c) 2012 Kevin Malakoff. Knockback.AttributeConnector is freely distributable under the MIT license. See the following for full license details: https://github.com/kmalakoff/knockback/blob/master/LICENSE */ var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Knockback.AttributeConnector = (function() { function AttributeConnector(model, key, options) { var observable; this.key = key; this.options = options != null ? options : {}; kb.utils.wrappedModel(this, model); this.options = _.clone(this.options); this.__kb.value_observable = ko.observable(); observable = kb.utils.wrappedObservable(this, ko.dependentObservable({ read: _.bind(this.read, this), write: _.bind(this.write, this) })); observable.destroy = _.bind(this.destroy, this); observable.model = _.bind(this.model, this); observable.update = _.bind(this.update, this); this.__kb.initializing = true; this.update(); this.__kb.initializing = false; return observable; } AttributeConnector.prototype.destroy = function() { this.__kb.value_observable = null; kb.utils.wrappedObservable(this).dispose(); return kb.utils.wrappedObservable(this, null); }; AttributeConnector.prototype.read = function() { return this.__kb.value_observable(); }; AttributeConnector.prototype.write = function(value) { var model, set_info; model = kb.utils.wrappedModel(this); if (!model) { return; } if (this.options.read_only) { if (!this.__kb.initializing) { throw "Cannot write a value to a dependentObservable unless you specify a 'write' option. If you wish to read the current value, don't pass any parameters."; } } else { set_info = {}; set_info[this.key] = value; return model.set(set_info); } }; AttributeConnector.prototype.model = function(new_model) { var model; model = kb.utils.wrappedModel(this); if (arguments.length === 0) { return model; } if (model === new_model) { return; } kb.utils.wrappedModel(this, new_model); return this.update(); }; AttributeConnector.inferType = function(model, key) { var relation, value; value = model.get(key); if (!value) { if (!(Backbone.RelationalModel && (model instanceof Backbone.RelationalModel))) { return 'simple'; } relation = _.find(model.getRelations(), function(test) { return test.key === key; }); if (!relation) { return 'simple'; } if (relation.collectionKey) { return 'collection'; } else { return 'model'; } } if (value instanceof Backbone.Collection) { return 'collection'; } if ((value instanceof Backbone.Model) || (Backbone.ModelRef && (value instanceof Backbone.ModelRef))) { return 'model'; } return 'simple'; }; AttributeConnector.createByType = function(type, model, key, options) { var attribute_options; switch (type) { case 'collection': attribute_options = options ? _.clone(options) : {}; if (!(options.view_model || options.view_model_create || options.children || options.create)) { attribute_options.view_model = kb.ViewModel; } if (options.store) { options.store.addResolverToOptions(attribute_options, model.get(key)); } return kb.collectionAttributeConnector(model, key, attribute_options); case 'model': attribute_options = options ? _.clone(options) : {}; if (!attribute_options.options) { attribute_options.options = {}; } if (!(options.view_model || options.view_model_create || options.children || options.create)) { attribute_options.view_model = kb.ViewModel; } if (options.store) { options.store.addResolverToOptions(attribute_options.options, model.get(key)); } return kb.viewModelAttributeConnector(model, key, attribute_options); default: return kb.simpleAttributeConnector(model, key, options); } }; AttributeConnector.createOrUpdate = function(attribute_connector, model, key, options) { var attribute_options, value; if (attribute_connector) { if (kb.utils.observableInstanceOf(attribute_connector, kb.AttributeConnector)) { if (attribute_connector.model() !== model) { attribute_connector.model(model); } else { attribute_connector.update(); } } return attribute_connector; } if (!model) { return kb.simpleAttributeConnector(model, key, options); } if (options.hasOwnProperty('create')) { if (!options.create) { throw new Error('Knockback.AttributeConnector: options.create is empty'); } return options.create(model, key, options.options || {}); } value = model.get(key); if (options.hasOwnProperty('view_model')) { if (!options.view_model) { throw new Error('Knockback.AttributeConnector: options.view_model is empty'); } return new options.view_model(value, options.options || {}); } else if (options.hasOwnProperty('view_model_create')) { if (!options.view_model_create) { throw new Error('Knockback.AttributeConnector: options.view_model_create is empty'); } return options.view_model_create(value, options.options || {}); } else if (options.hasOwnProperty('children')) { if (!options.children) { throw new Error('Knockback.AttributeConnector: options.children is empty'); } if (typeof options.children === 'function') { attribute_options = { view_model: options.children }; } else { attribute_options = options.children || {}; } return kb.collectionAttributeConnector(model, key, attribute_options); } return this.createByType(this.inferType(model, key), model, key, options); }; return AttributeConnector; })(); Knockback.SimpleAttributeConnector = (function(_super) { __extends(SimpleAttributeConnector, _super); function SimpleAttributeConnector() { SimpleAttributeConnector.__super__.constructor.apply(this, arguments); return kb.utils.wrappedObservable(this); } SimpleAttributeConnector.prototype.destroy = function() { this.current_value = null; return SimpleAttributeConnector.__super__.destroy.apply(this, arguments); }; SimpleAttributeConnector.prototype.update = function() { var current_value, model, value; model = kb.utils.wrappedModel(this); if (!model) { return; } value = model.get(this.key); current_value = this.__kb.value_observable(); if (!_.isEqual(current_value, value)) { return this.__kb.value_observable(value); } }; SimpleAttributeConnector.prototype.write = function(value) { var model; model = kb.utils.wrappedModel(this); if (!model) { this.__kb.value_observable(value); return; } return SimpleAttributeConnector.__super__.write.apply(this, arguments); }; return SimpleAttributeConnector; })(Knockback.AttributeConnector); Knockback.simpleAttributeConnector = function(model, key, options) { return new Knockback.SimpleAttributeConnector(model, key, options); }; Knockback.CollectionAttributeConnector = (function(_super) { __extends(CollectionAttributeConnector, _super); function CollectionAttributeConnector() { CollectionAttributeConnector.__super__.constructor.apply(this, arguments); return kb.utils.wrappedObservable(this); } CollectionAttributeConnector.prototype.destroy = function() { var current_value; current_value = this.__kb.value_observable(); if (current_value && (typeof current_value.refCount === 'function') && (current_value.refCount() > 0)) { current_value.release(); } return CollectionAttributeConnector.__super__.destroy.apply(this, arguments); }; CollectionAttributeConnector.prototype.update = function() { var current_value, model, value, _this = this; model = kb.utils.wrappedModel(this); if (!model) { return; } value = model.get(this.key); current_value = this.__kb.value_observable(); if (!current_value) { if (this.options.store) { return this.__kb.value_observable(this.options.store.resolveValue(value, function() { return kb.collectionObservable(value, _this.options); })); } else { return this.__kb.value_observable(kb.collectionObservable(value, this.options)); } } else { if (current_value.collection() !== value) { current_value.collection(value); return this.__kb.value_observable.valueHasMutated(); } } }; CollectionAttributeConnector.prototype.read = function() { var current_value; current_value = this.__kb.value_observable(); if (current_value) { return current_value(); } else { return void 0; } }; return CollectionAttributeConnector; })(Knockback.AttributeConnector); Knockback.collectionAttributeConnector = function(model, key, options) { return new Knockback.CollectionAttributeConnector(model, key, options); }; Knockback.ViewModelAttributeConnector = (function(_super) { __extends(ViewModelAttributeConnector, _super); function ViewModelAttributeConnector() { ViewModelAttributeConnector.__super__.constructor.apply(this, arguments); return kb.utils.wrappedObservable(this); } ViewModelAttributeConnector.prototype.destroy = function() { var current_value; current_value = this.__kb.value_observable(); if (current_value && (typeof current_value.refCount === 'function') && (current_value.refCount() > 0)) { current_value.release(); } return ViewModelAttributeConnector.__super__.destroy.apply(this, arguments); }; ViewModelAttributeConnector.prototype.update = function() { var current_value, model, value, view_model_options, _this = this; model = kb.utils.wrappedModel(this); if (!model) { return; } value = model.get(this.key); current_value = this.__kb.value_observable(); if (!current_value) { view_model_options = this.options.options ? _.clone(this.options.options) : {}; if (view_model_options.store) { return this.__kb.value_observable(view_model_options.store.resolveValue(value, function() { if (_this.options.view_model) { return new _this.options.view_model(value, view_model_options); } else { return _this.options.view_model_create(value, view_model_options); } })); } else { return this.__kb.value_observable(this.options.view_model ? new this.options.view_model(value, view_model_options) : this.options.view_model_create(value, view_model_options)); } } else { if (!(current_value.model && (typeof current_value.model === 'function'))) { throw new Error("Knockback.viewModelAttributeConnector: unknown how to model a view model"); } if (current_value.model() !== value) { current_value.model(value); return this.__kb.value_observable.valueHasMutated(); } } }; return ViewModelAttributeConnector; })(Knockback.AttributeConnector); Knockback.viewModelAttributeConnector = function(model, key, options) { return new Knockback.ViewModelAttributeConnector(model, key, options); }; // Generated by CoffeeScript 1.3.3 /* knockback_view_model.js (c) 2011 Kevin Malakoff. Knockback.Observable is freely distributable under the MIT license. See the following for full license details: https://github.com/kmalakoff/knockback/blob/master/LICENSE */ var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Knockback.ViewModel_RCBase = (function(_super) { __extends(ViewModel_RCBase, _super); function ViewModel_RCBase() { return ViewModel_RCBase.__super__.constructor.apply(this, arguments); } ViewModel_RCBase.prototype.__destroy = function() { var key, value, _results; _results = []; for (key in this) { value = this[key]; if (!value || (key === '__kb')) { continue; } if (kb.utils.release(value)) { _results.push(this[key] = null); } else { _results.push(void 0); } } return _results; }; return ViewModel_RCBase; })(Knockback.RefCountable); Knockback.ViewModel = (function(_super) { __extends(ViewModel, _super); function ViewModel(model, options) { var key, missing, _i, _len; if (options == null) { options = {}; } ViewModel.__super__.constructor.apply(this, arguments); if (Knockback.stats_on) { kb.stats.view_models++; } if (!options.store_skip_resolve) { kb.Store.resolveFromOptions(options, this); } if (options.store) { this.__kb.store = options.store; } else { this.__kb.store = new kb.Store(); this.__kb.store_is_owned = true; } this.__kb._onModelChange = _.bind(this._onModelChange, this); this.__kb._onModelLoaded = _.bind(this._onModelLoaded, this); this.__kb._onModelUnloaded = _.bind(this._onModelUnloaded, this); this.__kb.internals = options.internals; this.__kb.requires = options.requires; this.__kb.children = options.children; this.__kb.create = options.create; this.__kb.read_only = options.read_only; kb.utils.wrappedModel(this, model); if (Backbone.ModelRef && (model instanceof Backbone.ModelRef)) { this.__kb.model_ref = model; this.__kb.model_ref.retain(); kb.utils.wrappedModel(this, this.__kb.model_ref.getModel()); this.__kb.model_ref.bind('loaded', this.__kb._onModelLoaded); this.__kb.model_ref.bind('unloaded', this.__kb._onModelUnloaded); } if (this.__kb.model) { this._onModelLoaded(this.__kb.model); } if (!this.__kb.internals && !this.__kb.requires) { return this; } missing = _.union((this.__kb.internals ? this.__kb.internals : []), (this.__kb.requires ? this.__kb.requires : [])); if (!this.__kb.model_ref || this.__kb.model_ref.isLoaded()) { missing = _.difference(missing, _.keys(this.__kb.model.attributes)); } for (_i = 0, _len = missing.length; _i < _len; _i++) { key = missing[_i]; this._updateAttributeConnector(this.__kb.model, key); } } ViewModel.prototype.__destroy = function() { var model; model = this.__kb.model; kb.utils.wrappedModel(this, null); this._modelUnbind(model); if (this.__kb.store_is_owned) { this.__kb.store.destroy(); } this.__kb.store = null; ViewModel.__super__.__destroy.apply(this, arguments); if (Knockback.stats_on) { return kb.stats.view_models--; } }; ViewModel.prototype.model = function(new_model) { var model; model = kb.utils.wrappedModel(this); if (arguments.length === 0) { return model; } if (new_model === model) { return; } if (model) { this._onModelUnloaded(model); } if (new_model) { return this._onModelLoaded(new_model); } }; ViewModel.prototype._modelBind = function(model) { if (!model) { return; } model.bind('change', this.__kb._onModelChange); if (Backbone.RelationalModel && (model instanceof Backbone.RelationalModel)) { model.bind('add', this.__kb._onModelChange); model.bind('remove', this.__kb._onModelChange); return model.bind('update', this.__kb._onModelChange); } }; ViewModel.prototype._modelUnbind = function(model) { if (!model) { return; } model.unbind('change', this.__kb._onModelChange); if (Backbone.RelationalModel && (model instanceof Backbone.RelationalModel)) { model.unbind('add', this.__kb._onModelChange); model.unbind('remove', this.__kb._onModelChange); return model.unbind('update', this.__kb._onModelChange); } }; ViewModel.prototype._onModelLoaded = function(model) { var key, _results; kb.utils.wrappedModel(this, model); this._modelBind(model); _results = []; for (key in this.__kb.model.attributes) { _results.push(this._updateAttributeConnector(this.__kb.model, key)); } return _results; }; ViewModel.prototype._onModelUnloaded = function(model) { var key, _results; this._modelUnbind(model); kb.utils.wrappedModel(this, null); _results = []; for (key in model.attributes) { _results.push(this._updateAttributeConnector(null, key)); } return _results; }; ViewModel.prototype._onModelChange = function() { var key, _results, _results1; if (this.__kb.model._changed) { _results = []; for (key in this.__kb.model.attributes) { _results.push(this.__kb.model.hasChanged(key) ? this._updateAttributeConnector(this.__kb.model, key) : void 0); } return _results; } else if (this.__kb.model.changed) { _results1 = []; for (key in this.__kb.model.changed) { _results1.push(this._updateAttributeConnector(this.__kb.model, key)); } return _results1; } }; ViewModel.prototype._updateAttributeConnector = function(model, key) { var vm_key; vm_key = this.__kb.internals && _.contains(this.__kb.internals, key) ? '_' + key : key; return this[vm_key] = kb.AttributeConnector.createOrUpdate(this[vm_key], model, key, this._createOptions(key)); }; ViewModel.prototype._createOptions = function(key) { var options; if (this.__kb.children) { if (this.__kb.children.hasOwnProperty(key)) { options = this.__kb.children[key]; if (typeof options === 'function') { options = { view_model: options }; } options.options = { read_only: this.__kb.read_only, store: this.__kb.store }; return options; } else if (this.__kb.children.hasOwnProperty('create')) { return { create: this.__kb.children.create, options: { read_only: this.__kb.read_only, store: this.__kb.store } }; } } else if (this.__kb.create) { return { create: this.__kb.create, options: { read_only: this.__kb.read_only, store: this.__kb.store } }; } return { read_only: this.__kb.read_only, store: this.__kb.store }; }; return ViewModel; })(Knockback.ViewModel_RCBase); Knockback.viewModel = function(model, options) { return new Knockback.ViewModel(model, options); };