model-list-debug.js revision d561b35ed5a1899db0e91d791e606b951a3c1180
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav GlassYUI.add('model-list', function(Y) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass/**
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav GlassProvides an API for managing an ordered list of Model instances.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove@submodule model-list
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove@since 3.4.0
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove**/
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove/**
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan GroveProvides an API for managing an ordered list of Model instances.
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan GroveIn addition to providing convenient `add`, `create`, `reset`, and `remove`
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glassmethods for managing the models in the list, ModelLists are also bubble targets
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glassfor events on the model instances they contain. This means, for example, that
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glassyou can add several models to a list, and then subscribe to the `*:change` event
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glasson the list to be notified whenever any model in the list changes.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav GlassModelLists also maintain sort order efficiently as models are added and removed,
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glassbased on a custom `comparator` function you may define (if no comparator is
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glassdefined, models are sorted in insertion order).
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass@class ModelList
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove@extends Base
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass@uses ArrayList
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove@constructor
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove@since 3.4.0
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass**/
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grovevar AttrProto = Y.Attribute.prototype,
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove Lang = Y.Lang,
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove YArray = Y.Array,
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass Fired when a model is added to the list.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass Listen to the `on` phase of this event to be notified before a model is
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass added to the list. Calling `e.preventDefault()` during the `on` phase will
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass prevent the model from being added.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass Listen to the `after` phase of this event to be notified after a model has
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass been added to the list.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @event add
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @param {Model} model The model being added.
d3e7704f3fd45efa522b537b83189cd8a511e67fRyan Grove @param {Number} index The index at which the model will be added.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @preventable _defAddFn
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass **/
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass EVT_ADD = 'add',
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
d3e7704f3fd45efa522b537b83189cd8a511e67fRyan Grove /**
d3e7704f3fd45efa522b537b83189cd8a511e67fRyan Grove Fired when an error occurs, such as when an attempt is made to add a
d3e7704f3fd45efa522b537b83189cd8a511e67fRyan Grove duplicate model to the list, or when a sync layer response can't be parsed.
d3e7704f3fd45efa522b537b83189cd8a511e67fRyan Grove
d3e7704f3fd45efa522b537b83189cd8a511e67fRyan Grove @event error
d3e7704f3fd45efa522b537b83189cd8a511e67fRyan Grove @param {Any} error Error message, object, or exception generated by the
d3e7704f3fd45efa522b537b83189cd8a511e67fRyan Grove error. Calling `toString()` on this should result in a meaningful error
d3e7704f3fd45efa522b537b83189cd8a511e67fRyan Grove message.
d3e7704f3fd45efa522b537b83189cd8a511e67fRyan Grove @param {String} src Source of the error. May be one of the following (or any
d3e7704f3fd45efa522b537b83189cd8a511e67fRyan Grove custom error source defined by a ModelList subclass):
d3e7704f3fd45efa522b537b83189cd8a511e67fRyan Grove
d3e7704f3fd45efa522b537b83189cd8a511e67fRyan Grove * `add`: Error while adding a model (probably because it's already in the
d3e7704f3fd45efa522b537b83189cd8a511e67fRyan Grove list and can't be added again). The model in question will be provided
d3e7704f3fd45efa522b537b83189cd8a511e67fRyan Grove as the `model` property on the event facade.
d3e7704f3fd45efa522b537b83189cd8a511e67fRyan Grove * `parse`: An error parsing a JSON response. The response in question will
d3e7704f3fd45efa522b537b83189cd8a511e67fRyan Grove be provided as the `response` property on the event facade.
d3e7704f3fd45efa522b537b83189cd8a511e67fRyan Grove * `remove`: Error while removing a model (probably because it isn't in the
d3e7704f3fd45efa522b537b83189cd8a511e67fRyan Grove list and can't be removed). The model in question will be provided as
d3e7704f3fd45efa522b537b83189cd8a511e67fRyan Grove the `model` property on the event facade.
d3e7704f3fd45efa522b537b83189cd8a511e67fRyan Grove **/
d561b35ed5a1899db0e91d791e606b951a3c1180Ryan Grove EVT_ERROR = 'error',
d3e7704f3fd45efa522b537b83189cd8a511e67fRyan Grove
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove Fired when the list is completely reset via the `reset()` method or sorted
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove via the `sort()` method.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass Listen to the `on` phase of this event to be notified before the list is
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove reset. Calling `e.preventDefault()` during the `on` phase will prevent
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove the list from being reset.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass Listen to the `after` phase of this event to be notified after the list has
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove been reset.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove @event reset
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove @param {Model[]} models Array of the list's new models after the reset.
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove @param {String} src Source of the event. May be either `'reset'` or
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass `'sort'`.
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove @preventable _defResetFn
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass **/
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove EVT_RESET = 'reset',
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass Fired when a model is removed from the list.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass Listen to the `on` phase of this event to be notified before a model is
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass removed from the list. Calling `e.preventDefault()` during the `on` phase
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass will prevent the model from being removed.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass Listen to the `after` phase of this event to be notified after a model has
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass been removed from the list.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @event remove
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @param {Model} model The model being removed.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @param {int} index The index of the model being removed.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @preventable _defRemoveFn
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass **/
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass EVT_REMOVE = 'remove';
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glassfunction ModelList() {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass ModelList.superclass.constructor.apply(this, arguments);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass}
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav GlassY.ModelList = Y.extend(ModelList, Y.Base, {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass // -- Public Properties ----------------------------------------------------
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass The `Model` class or subclass of the models in this list.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass This property is `null` by default, and is intended to be overridden in a
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass subclass or specified as a config property at instantiation time. It will be
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass used to create model instances automatically based on attribute hashes
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove passed to the `add()`, `create()`, and `reset()` methods.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @property model
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @type Model
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @default `null`
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass **/
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass model: null,
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass // -- Lifecycle Methods ----------------------------------------------------
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass initializer: function (config) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass config || (config = {});
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass var model = this.model = config.model || this.model;
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove this.publish(EVT_ADD, {defaultFn: this._defAddFn});
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove this.publish(EVT_RESET, {defaultFn: this._defResetFn});
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove this.publish(EVT_REMOVE, {defaultFn: this._defRemoveFn});
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass if (model) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass this.after('*:idChange', this._afterIdChange);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass } else {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass Y.log('No model class specified.', 'warn', 'model-list');
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass this._clear();
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass destructor: function () {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass YArray.each(this._items, this._detachList, this);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass // -- Public Methods -------------------------------------------------------
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass Adds the specified model or array of models to this list.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @example
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass // Add a single model instance.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass list.add(new Model({foo: 'bar'}));
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass // Add a single model, creating a new instance automatically.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass list.add({foo: 'bar'});
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass // Add multiple models, creating new instances automatically.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass list.add([
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass {foo: 'bar'},
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass {baz: 'quux'}
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass ]);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @method add
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @param {Model|Model[]|Object|Object[]} models Models to add. May be existing
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass model instances or hashes of model attributes, in which case new model
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass instances will be created from the hashes.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @param {Object} [options] Data to be mixed into the event facade of the
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass `add` event(s) for the added models.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @param {Boolean} [options.silent=false] If `true`, no `add` event(s) will
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass be fired.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @return {Model|Model[]} Added model or array of added models.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass **/
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass add: function (models, options) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass if (Lang.isArray(models)) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass return YArray.map(models, function (model) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass return this._add(model, options);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }, this);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass } else {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass return this._add(models, options);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass Define this method to provide a function that takes a model as a parameter
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass and returns a value by which that model should be sorted relative to other
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass models in this list.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass By default, no comparator is defined, meaning that models will not be sorted
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass (they'll be stored in the order they're added).
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @example
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass var list = new Y.ModelList({model: Y.Model});
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass list.comparator = function (model) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass return model.get('id'); // Sort models by id.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass };
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @method comparator
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @param {Model} model Model being sorted.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @return {Number|String} Value by which the model should be sorted relative
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass to other models in this list.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass **/
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass // comparator is not defined by default
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass Creates or updates the specified model on the server, then adds it to this
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass list if the server indicates success.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @method create
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @param {Model|Object} model Model to create. May be an existing model
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass instance or a hash of model attributes, in which case a new model instance
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass will be created from the hash.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @param {Object} [options] Options to be passed to the model's `sync()` and
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass `set()` methods and mixed into the `add` event when the model is added
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass to the list.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @param {Boolean} [options.silent=false] If `true`, no `add` event(s) will
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass be fired.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @param {callback} [callback] Called when the sync operation finishes.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @param {Error} callback.err If an error occurred, this parameter will
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass contain the error. If the sync operation succeeded, _err_ will be
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass falsy.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @param {mixed} callback.response The server's response.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @return {Model} Created model.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass **/
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass create: function (model, options, callback) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass var self = this;
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass // Allow callback as second arg.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass if (typeof options === 'function') {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass callback = options;
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass options = {};
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass if (!(model instanceof Y.Model)) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass model = new this.model(model);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass return model.save(options, function (err) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass if (!err) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass self.add(model, options);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass callback && callback.apply(null, arguments);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass });
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove /**
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove If _name_ refers to an attribute on this ModelList instance, returns the
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove value of that attribute. Otherwise, returns an array containing the values
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove of the specified attribute from each model in this list.
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove @method get
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove @param {String} name Attribute name or object property path.
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove @return {Any|Array} Attribute value or array of attribute values.
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove @see Model.get()
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove **/
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove get: function (name) {
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove if (this.attrAdded(name)) {
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove return AttrProto.get.apply(this, arguments);
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove }
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove return this.invoke('get', name);
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove },
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove /**
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove If _name_ refers to an attribute on this ModelList instance, returns the
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove HTML-escaped value of that attribute. Otherwise, returns an array containing
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove the HTML-escaped values of the specified attribute from each model in this
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove list.
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove The values are escaped using `Escape.html()`.
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove @method getAsHTML
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove @param {String} name Attribute name or object property path.
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove @return {String|String[]} HTML-escaped value or array of HTML-escaped
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove values.
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove @see Model.getAsHTML()
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove **/
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove getAsHTML: function (name) {
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove if (this.attrAdded(name)) {
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove return Y.Escape.html(AttrProto.get.apply(this, arguments));
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove }
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove return this.invoke('getAsHTML', name);
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove },
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove /**
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove If _name_ refers to an attribute on this ModelList instance, returns the
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove URL-encoded value of that attribute. Otherwise, returns an array containing
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove the URL-encoded values of the specified attribute from each model in this
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove list.
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove The values are encoded using the native `encodeURIComponent()` function.
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove @method getAsURL
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove @param {String} name Attribute name or object property path.
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove @return {String|String[]} URL-encoded value or array of URL-encoded values.
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove @see Model.getAsURL()
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove **/
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove getAsURL: function (name) {
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove if (this.attrAdded(name)) {
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove return encodeURIComponent(AttrProto.get.apply(this, arguments));
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove }
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove return this.invoke('getAsURL', name);
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove },
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass Returns the model with the specified _clientId_, or `null` if not found.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @method getByClientId
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @param {String} clientId Client id.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @return {Model} Model, or `null` if not found.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass **/
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass getByClientId: function (clientId) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass return this._clientIdMap[clientId] || null;
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass Returns the model with the specified _id_, or `null` if not found.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass Note that models aren't expected to have an id until they're saved, so if
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass you're working with unsaved models, it may be safer to call
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass `getByClientId()`.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @method getById
d561b35ed5a1899db0e91d791e606b951a3c1180Ryan Grove @param {String|Number} id Model id.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @return {Model} Model, or `null` if not found.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass **/
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass getById: function (id) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass return this._idMap[id] || null;
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass Calls the named method on every model in the list. Any arguments provided
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass after _name_ will be passed on to the invoked method.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @method invoke
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @param {String} name Name of the method to call on each model.
a7bf61fe73568ec8f3615c238acbe69d5986e21dRyan Grove @param {Any} [args*] Zero or more arguments to pass to the invoked method.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @return {Array} Array of return values, indexed according to the index of
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass the model on which the method was called.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass **/
d3e7704f3fd45efa522b537b83189cd8a511e67fRyan Grove invoke: function (name /*, args* */) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass var args = [this._items, name].concat(YArray(arguments, 1, true));
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass return YArray.invoke.apply(YArray, args);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass Returns the model at the specified _index_.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @method item
d561b35ed5a1899db0e91d791e606b951a3c1180Ryan Grove @param {Number} index Index of the model to fetch.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @return {Model} The model at the specified index, or `undefined` if there
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass isn't a model there.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass **/
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass // item() is inherited from ArrayList.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass Loads this list of models from the server.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass This method delegates to the `sync()` method to perform the actual load
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass operation, which is an asynchronous action. Specify a _callback_ function to
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass be notified of success or failure.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove If the load operation succeeds, a `reset` event will be fired.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @method load
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @param {Object} [options] Options to be passed to `sync()` and to
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove `reset()` when adding the loaded models. It's up to the custom sync
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass implementation to determine what options it supports or requires, if any.
d561b35ed5a1899db0e91d791e606b951a3c1180Ryan Grove @param {Function} [callback] Called when the sync operation finishes.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @param {Error} callback.err If an error occurred, this parameter will
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass contain the error. If the sync operation succeeded, _err_ will be
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass falsy.
d561b35ed5a1899db0e91d791e606b951a3c1180Ryan Grove @param {Any} callback.response The server's response. This value will
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass be passed to the `parse()` method, which is expected to parse it and
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass return an array of model attribute hashes.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @chainable
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass **/
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass load: function (options, callback) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass var self = this;
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass // Allow callback as only arg.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass if (typeof options === 'function') {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass callback = options;
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass options = {};
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass this.sync('read', options, function (err, response) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass if (!err) {
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove self.reset(self.parse(response), options);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass callback && callback.apply(null, arguments);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass });
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass return this;
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass Executes the specified function on each model in this list and returns an
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass array of the function's collected return values.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @method map
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @param {Function} fn Function to execute on each model.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @param {Model} fn.model Current model being iterated.
d561b35ed5a1899db0e91d791e606b951a3c1180Ryan Grove @param {Number} fn.index Index of the current model in the list.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @param {Model[]} fn.models Array of models being iterated.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @param {Object} [thisObj] `this` object to use when calling _fn_.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @return {Array} Array of return values from _fn_.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass **/
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass map: function (fn, thisObj) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass return YArray.map(this._items, fn, thisObj);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass Called to parse the _response_ when the list is loaded from the server.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass This method receives a server _response_ and is expected to return an array
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass of model attribute hashes.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass The default implementation assumes that _response_ is either an array of
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass attribute hashes or a JSON string that can be parsed into an array of
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass attribute hashes. If _response_ is a JSON string and either `Y.JSON` or the
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass native `JSON` object are available, it will be parsed automatically. If a
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass parse error occurs, an `error` event will be fired and the model will not be
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass updated.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass You may override this method to implement custom parsing logic if necessary.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @method parse
d561b35ed5a1899db0e91d791e606b951a3c1180Ryan Grove @param {Any} response Server response.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @return {Object[]} Array of model attribute hashes.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass **/
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass parse: function (response) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass if (typeof response === 'string') {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass try {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass return Y.JSON.parse(response) || [];
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass } catch (ex) {
d3e7704f3fd45efa522b537b83189cd8a511e67fRyan Grove this.fire(EVT_ERROR, {
d3e7704f3fd45efa522b537b83189cd8a511e67fRyan Grove error : ex,
d3e7704f3fd45efa522b537b83189cd8a511e67fRyan Grove response: response,
d3e7704f3fd45efa522b537b83189cd8a511e67fRyan Grove src : 'parse'
d3e7704f3fd45efa522b537b83189cd8a511e67fRyan Grove });
d3e7704f3fd45efa522b537b83189cd8a511e67fRyan Grove
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass return null;
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass return response || [];
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove /**
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove Removes the specified model or array of models from this list.
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove @method remove
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove @param {Model|Model[]} models Models to remove.
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove @param {Object} [options] Data to be mixed into the event facade of the
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove `remove` event(s) for the removed models.
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove @param {Boolean} [options.silent=false] If `true`, no `remove` event(s)
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove will be fired.
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove @return {Model|Model[]} Removed model or array of removed models.
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove **/
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove remove: function (models, options) {
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove if (Lang.isArray(models)) {
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove return YArray.map(models, function (model) {
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove return this._remove(model, options);
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove }, this);
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove } else {
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove return this._remove(models, options);
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove }
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove },
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass Completely replaces all models in the list with those specified, and fires a
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove single `reset` event.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove Use `reset` when you want to add or remove a large number of items at once
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass without firing `add` or `remove` events for each one.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove @method reset
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove @param {Model[]|Object[]} [models] Models to add. May be existing model
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass instances or hashes of model attributes, in which case new model instances
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove will be created from the hashes. Calling `reset()` without passing in any
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove models will clear the list.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @param {Object} [options] Data to be mixed into the event facade of the
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove `reset` event.
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove @param {Boolean} [options.silent=false] If `true`, no `reset` event will
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass be fired.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @chainable
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass **/
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove reset: function (models, options) {
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove models || (models = []);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass options || (options = {});
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass var facade = Y.merge(options, {
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove src : 'reset',
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass models: YArray.map(models, function (model) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass return model instanceof Y.Model ? model :
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass new this.model(model);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }, this)
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass });
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove // Sort the models in the facade before firing the reset event.
05077064e34396660f0e2b4e2ce06098b0edf077Ryan Grove if (this.comparator) {
05077064e34396660f0e2b4e2ce06098b0edf077Ryan Grove facade.models.sort(Y.bind(this._sort, this));
05077064e34396660f0e2b4e2ce06098b0edf077Ryan Grove }
05077064e34396660f0e2b4e2ce06098b0edf077Ryan Grove
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove options.silent ? this._defResetFn(facade) :
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove this.fire(EVT_RESET, facade);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass return this;
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass Forcibly re-sorts the list.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass Usually it shouldn't be necessary to call this method since the list
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass maintains its sort order when items are added and removed, but if you change
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass the `comparator` function after items are already in the list, you'll need
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass to re-sort.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @method sort
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @param {Object} [options] Data to be mixed into the event facade of the
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove `reset` event.
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove @param {Boolean} [options.silent=false] If `true`, no `reset` event will
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass be fired.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @chainable
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass **/
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass sort: function (options) {
05077064e34396660f0e2b4e2ce06098b0edf077Ryan Grove var models = this._items.concat(),
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass facade;
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
05077064e34396660f0e2b4e2ce06098b0edf077Ryan Grove if (!this.comparator) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass return this;
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass options || (options = {});
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
05077064e34396660f0e2b4e2ce06098b0edf077Ryan Grove models.sort(Y.bind(this._sort, this));
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass facade = Y.merge(options, {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass models: models,
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass src : 'sort'
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass });
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove options.silent ? this._defResetFn(facade) :
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove this.fire(EVT_RESET, facade);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass return this;
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass Override this method to provide a custom persistence implementation for this
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass list. The default method just calls the callback without actually doing
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass anything.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass This method is called internally by `load()`.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @method sync
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @param {String} action Sync action to perform. May be one of the following:
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * `create`: Store a list of newly-created models for the first time.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * `delete`: Delete a list of existing models.
fbb8b3b8c5a0aad2d7eb5f62e4507a20696adb43Ryan Grove * `read` : Load a list of existing models.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass * `update`: Update a list of existing models.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass Currently, model lists only make use of the `read` action, but other
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass actions may be used in future versions.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @param {Object} [options] Sync options. It's up to the custom sync
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass implementation to determine what options it supports or requires, if any.
d561b35ed5a1899db0e91d791e606b951a3c1180Ryan Grove @param {Function} [callback] Called when the sync operation finishes.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @param {Error} callback.err If an error occurred, this parameter will
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass contain the error. If the sync operation succeeded, _err_ will be
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass falsy.
d561b35ed5a1899db0e91d791e606b951a3c1180Ryan Grove @param {Any} [callback.response] The server's response. This value will
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass be passed to the `parse()` method, which is expected to parse it and
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass return an array of model attribute hashes.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass **/
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass sync: function (/* action, options, callback */) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass var callback = YArray(arguments, 0, true).pop();
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass if (typeof callback === 'function') {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass callback();
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass Returns an array containing the models in this list.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @method toArray
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @return {Array} Array containing the models in this list.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass **/
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass toArray: function () {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass return this._items.concat();
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass Returns an array containing attribute hashes for each model in this list,
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass suitable for being passed to `Y.JSON.stringify()`.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass Under the hood, this method calls `toJSON()` on each model in the list and
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass pushes the results into an array.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @method toJSON
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @return {Object[]} Array of model attribute hashes.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @see Model.toJSON()
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass **/
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass toJSON: function () {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass return this.map(function (model) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass return model.toJSON();
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass });
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass // -- Protected Methods ----------------------------------------------------
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass Adds the specified _model_ if it isn't already in this list.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @method _add
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @param {Model|Object} model Model or object to add.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @param {Object} [options] Data to be mixed into the event facade of the
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass `add` event for the added model.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @param {Boolean} [options.silent=false] If `true`, no `add` event will be
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass fired.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @return {Model} The added model.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @protected
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass **/
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass _add: function (model, options) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass var facade;
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass options || (options = {});
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass if (!(model instanceof Y.Model)) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass model = new this.model(model);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass if (this._clientIdMap[model.get('clientId')]) {
d3e7704f3fd45efa522b537b83189cd8a511e67fRyan Grove this.fire(EVT_ERROR, {
d3e7704f3fd45efa522b537b83189cd8a511e67fRyan Grove error: 'Model is already in the list.',
d3e7704f3fd45efa522b537b83189cd8a511e67fRyan Grove model: model,
d3e7704f3fd45efa522b537b83189cd8a511e67fRyan Grove src : 'add'
d3e7704f3fd45efa522b537b83189cd8a511e67fRyan Grove });
d3e7704f3fd45efa522b537b83189cd8a511e67fRyan Grove
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass return;
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass facade = Y.merge(options, {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass index: this._findIndex(model),
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass model: model
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass });
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass options.silent ? this._defAddFn(facade) : this.fire(EVT_ADD, facade);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass return model;
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass Adds this list as a bubble target for the specified model's events.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @method _attachList
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @param {Model} model Model to attach to this list.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @protected
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass **/
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass _attachList: function (model) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass // Attach this list and make it a bubble target for the model.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass model.lists.push(this);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass model.addTarget(this);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass Clears all internal state and the internal list of models, returning this
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass list to an empty state. Automatically detaches all models in the list.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @method _clear
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @protected
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass **/
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass _clear: function () {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass YArray.each(this._items, this._detachList, this);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass this._clientIdMap = {};
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass this._idMap = {};
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass this._items = [];
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass Removes this list as a bubble target for the specified model's events.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @method _detachList
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @param {Model} model Model to detach.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @protected
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass **/
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass _detachList: function (model) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass var index = YArray.indexOf(model.lists, this);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass if (index > -1) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass model.lists.splice(index, 1);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass model.removeTarget(this);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass Returns the index at which the given _model_ should be inserted to maintain
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass the sort order of the list.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @method _findIndex
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @param {Model} model The model being inserted.
d561b35ed5a1899db0e91d791e606b951a3c1180Ryan Grove @return {Number} Index at which the model should be inserted.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @protected
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass **/
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass _findIndex: function (model) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass var comparator = this.comparator,
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass items = this._items,
05077064e34396660f0e2b4e2ce06098b0edf077Ryan Grove max = items.length,
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass min = 0,
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass item, middle, needle;
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass if (!comparator || !items.length) { return items.length; }
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass needle = comparator(model);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass // Perform an iterative binary search to determine the correct position
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass // based on the return value of the `comparator` function.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass while (min < max) {
05077064e34396660f0e2b4e2ce06098b0edf077Ryan Grove middle = (min + max) >> 1; // Divide by two and discard remainder.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass item = items[middle];
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
05077064e34396660f0e2b4e2ce06098b0edf077Ryan Grove if (comparator(item) < needle) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass min = middle + 1;
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass } else {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass max = middle;
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass return min;
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass Removes the specified _model_ if it's in this list.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @method _remove
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @param {Model} model Model to remove.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @param {Object} [options] Data to be mixed into the event facade of the
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass `remove` event for the removed model.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @param {Boolean} [options.silent=false] If `true`, no `remove` event will
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass be fired.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @return {Model} Removed model.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @protected
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass **/
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass _remove: function (model, options) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass var index = this.indexOf(model),
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass facade;
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass options || (options = {});
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass if (index === -1) {
d3e7704f3fd45efa522b537b83189cd8a511e67fRyan Grove this.fire(EVT_ERROR, {
d3e7704f3fd45efa522b537b83189cd8a511e67fRyan Grove error: 'Model is not in the list.',
d3e7704f3fd45efa522b537b83189cd8a511e67fRyan Grove model: model,
d3e7704f3fd45efa522b537b83189cd8a511e67fRyan Grove src : 'remove'
d3e7704f3fd45efa522b537b83189cd8a511e67fRyan Grove });
d3e7704f3fd45efa522b537b83189cd8a511e67fRyan Grove
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass return;
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }
307532b5488ffbd7d839996ef17afbc70dc268d3Ryan Grove
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass facade = Y.merge(options, {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass index: index,
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass model: model
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass });
307532b5488ffbd7d839996ef17afbc70dc268d3Ryan Grove
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass options.silent ? this._defRemoveFn(facade) :
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass this.fire(EVT_REMOVE, facade);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass return model;
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
05077064e34396660f0e2b4e2ce06098b0edf077Ryan Grove /**
05077064e34396660f0e2b4e2ce06098b0edf077Ryan Grove Array sort function used by `sort()` to re-sort the models in the list.
05077064e34396660f0e2b4e2ce06098b0edf077Ryan Grove
05077064e34396660f0e2b4e2ce06098b0edf077Ryan Grove @method _sort
05077064e34396660f0e2b4e2ce06098b0edf077Ryan Grove @param {Model} a First model to compare.
05077064e34396660f0e2b4e2ce06098b0edf077Ryan Grove @param {Model} b Second model to compare.
05077064e34396660f0e2b4e2ce06098b0edf077Ryan Grove @return {Number} `-1` if _a_ is less than _b_, `0` if equal, `1` if greater.
05077064e34396660f0e2b4e2ce06098b0edf077Ryan Grove @protected
05077064e34396660f0e2b4e2ce06098b0edf077Ryan Grove **/
05077064e34396660f0e2b4e2ce06098b0edf077Ryan Grove _sort: function (a, b) {
05077064e34396660f0e2b4e2ce06098b0edf077Ryan Grove var aValue = this.comparator(a),
05077064e34396660f0e2b4e2ce06098b0edf077Ryan Grove bValue = this.comparator(b);
05077064e34396660f0e2b4e2ce06098b0edf077Ryan Grove
05077064e34396660f0e2b4e2ce06098b0edf077Ryan Grove return aValue < bValue ? -1 : (aValue > bValue ? 1 : 0);
05077064e34396660f0e2b4e2ce06098b0edf077Ryan Grove },
05077064e34396660f0e2b4e2ce06098b0edf077Ryan Grove
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass // -- Event Handlers -------------------------------------------------------
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass Updates the model maps when a model's `id` attribute changes.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @method _afterIdChange
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @param {EventFacade} e
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @protected
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass **/
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass _afterIdChange: function (e) {
d561b35ed5a1899db0e91d791e606b951a3c1180Ryan Grove Lang.isValue(e.prevVal) && delete this._idMap[e.prevVal];
d561b35ed5a1899db0e91d791e606b951a3c1180Ryan Grove Lang.isValue(e.newVal) && (this._idMap[e.newVal] = e.target);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass // -- Default Event Handlers -----------------------------------------------
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass Default event handler for `add` events.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @method _defAddFn
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @param {EventFacade} e
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @protected
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass **/
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass _defAddFn: function (e) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass var model = e.model,
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass id = model.get('id');
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass this._clientIdMap[model.get('clientId')] = model;
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
d561b35ed5a1899db0e91d791e606b951a3c1180Ryan Grove if (Lang.isValue(id)) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass this._idMap[id] = model;
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass this._attachList(model);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass this._items.splice(e.index, 0, model);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass },
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass /**
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass Default event handler for `remove` events.
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @method _defRemoveFn
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @param {EventFacade} e
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass @protected
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass **/
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass _defRemoveFn: function (e) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass var model = e.model,
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass id = model.get('id');
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass this._detachList(model);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass delete this._clientIdMap[model.get('clientId')];
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
d561b35ed5a1899db0e91d791e606b951a3c1180Ryan Grove if (Lang.isValue(id)) {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass delete this._idMap[id];
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass this._items.splice(e.index, 1);
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove },
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove /**
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove Default event handler for `reset` events.
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove @method _defResetFn
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove @param {EventFacade} e
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove @protected
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove **/
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove _defResetFn: function (e) {
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove // When fired from the `sort` method, we don't need to clear the list or
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove // add any models, since the existing models are sorted in place.
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove if (e.src === 'sort') {
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove this._items = e.models.concat();
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove return;
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove }
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove this._clear();
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove if (e.models.length) {
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove this.add(e.models, {silent: true});
213abf076aeae2f3b6b834155b0a5b7dbae72d7cRyan Grove }
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass }
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass}, {
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass NAME: 'modelList'
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass});
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav GlassY.augment(ModelList, Y.ArrayList);
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
76ca635d61eb3f9fb7c9d788a44fa8b1690aa138Dav Glass
abe38d7e07e114761db3feb3c22ef22fce3ecccaRyan Grove}, '@VERSION@' ,{requires:['array-extras', 'array-invoke', 'arraylist', 'base-build', 'escape', 'json-parse', 'model']});