model-list.js revision 0804d9bfe6beb380217cc70ac79d976a1c21eb88
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen DesaiYUI.add('model-list', function (Y) {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai/**
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai@module model-list
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai@class ModelList
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai@constructor
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai@uses ArrayList
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai@uses Base
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai**/
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desaivar JSON = Y.JSON || JSON,
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai Lang = Y.Lang,
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai YArray = Y.Array,
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai /**
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai Fired when a model is added to the list.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai Listen to the `on` phase of this event to be notified before a model is
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai added to the list. Calling `e.preventDefault()` during the `on` phase will
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai prevent the model from being added.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai Listen to the `after` phase of this event to be notified after a model has
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai been added to the list.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @event add
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {Model} model The model being added.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {int} index The index at which the model will be added.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @preventable _defAddFn
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai **/
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai EVT_ADD = 'add',
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai /**
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai Fired when the list is completely refreshed via the `refresh()` method or
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai sorted via the `sort()` method.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai Listen to the `on` phase of this event to be notified before the list is
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai refreshed. Calling `e.preventDefault()` during the `on` phase will prevent
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai the list from being refreshed.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai Listen to the `after` phase of this event to be notified after the list has
d2fe481f82326b03c9a545af61f3379ac5d7fef1Satyen Desai been refreshed.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @event refresh
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {Model[]} models Array of the list's new models after the refresh.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {String} src Source of the event. May be either `'refresh'` or
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai `'sort'`.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @preventable _defRefreshFn
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai **/
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai EVT_REFRESH = 'refresh';
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai /**
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai Fired when a model is removed from the list.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai Listen to the `on` phase of this event to be notified before a model is
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai removed from the list. Calling `e.preventDefault()` during the `on` phase
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai will prevent the model from being removed.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai Listen to the `after` phase of this event to be notified after a model has
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai been removed from the list.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @event remove
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {Model} model The model being removed.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {int} index The index of the model being removed.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @preventable _defRemoveFn
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai **/
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai EVT_REMOVE = 'remove';
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desaifunction ModelList() {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai ModelList.superclass.constructor.apply(this, arguments);
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai}
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen DesaiY.ModelList = Y.extend(ModelList, Y.Base, {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai // -- Public Properties ----------------------------------------------------
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai /**
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai The `Model` class or subclass of the models in this list.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai This property is `null` by default, and is intended to be overridden in a
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai subclass or specified as a config property at instantiation time. It will be
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai used to create model instances automatically based on attribute hashes
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai passed to the `add()`, `create()`, and `remove()` methods.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @property model
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @type Model
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @default `null`
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai **/
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai model: null,
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai // -- Lifecycle Methods ----------------------------------------------------
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai initializer: function (config) {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai var model = this.model = config.model || this.model;
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai this.publish(EVT_ADD, {defaultFn: this._defAddFn});
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai this.publish(EVT_REFRESH, {defaultFn: this._defRefreshFn});
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai this.publish(EVT_REMOVE, {defaultFn: this._defRemoveFn});
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai if (model) {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai this.after(model.NAME + ':idChange', this._afterIdChange);
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai } else {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai Y.log('No model class specified.', 'warn', 'model-list');
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai }
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai this._clear();
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai },
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai // TODO: destructor?
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai // -- Public Methods -------------------------------------------------------
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai /**
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai Adds the specified model or array of models to this list.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @example
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai // Add a single model instance.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai list.add(new Model({foo: 'bar'}));
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai // Add a single model, creating a new instance automatically.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai list.add({foo: 'bar'});
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai // Add multiple models, creating new instances automatically.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai list.add([
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai {foo: 'bar'},
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai {baz: 'quux'}
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai ]);
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @method add
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {Model|Model[]|Object|Object[]} models Models to add. May be existing
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai model instances or hashes of model attributes, in which case new model
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai instances will be created from the hashes.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {Object} [options] Data to be mixed into the event facade of the
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai `add` event(s) for the added models.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {Boolean} [options.silent=false] If `true`, no `add` event(s) will
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai be fired.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @return {Model|Model[]} Added model or array of added models.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai **/
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai add: function (models, options) {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai var added, i, len;
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai if (Lang.isArray(models)) {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai added = [];
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai for (i = 0, len = models.length; i < len; ++i) {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai added.push(this._add(models[i], options));
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai }
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai return added;
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai } else {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai return this._add(model, options);
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai }
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai },
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai /**
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai Define this method to provide a function that takes a model as a parameter
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai and returns a value by which that model should be sorted relative to other
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai models in this list.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai By default, no comparator is defined, meaning that models will not be sorted
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai (they'll be stored in the order they're added).
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @example
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai var list = new Y.ModelList;
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai list.comparator = function (model) {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai return model.get('id'); // Sort models by id.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai };
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @method comparator
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {Model} model Model being sorted.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @return {Number|String} Value by which the model should be sorted relative
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai to other models in this list.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai **/
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai // comparator is not defined by default
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai /**
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai Creates or updates the specified model on the server, then adds it to this
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai list if the server indicates success.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @method create
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {Model|Object} model Model to create. May be an existing model
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai instance or a hash of model attributes, in which case a new model instance
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai will be created from the hash.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {Object} [options] Options to be passed to the model's `sync()` and
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai `set()` methods and mixed into the `add` event when the model is added
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai to the list.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {Boolean} [options.silent=false] If `true`, no `add` event(s) will
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai be fired.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {callback} [callback] Called when the sync operation finishes.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {Error|null} callback.err If an error occurred, this parameter will
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai contain the error. If the sync operation succeeded, _err_ will be
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai `null`.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {mixed} callback.response The server's response.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @return {Model} Created model.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai **/
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai create: function (model, options, callback) {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai var self = this;
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai // Allow callback as second arg.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai if (typeof options === 'function') {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai callback = options;
a921e6e9afbab09541d3bbbd297d0bb07c413d90Satyen Desai options = {};
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai }
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai if (!(model instanceof Y.Model)) {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai model = new this.model(model);
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai }
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai return model.save(options, function (err) {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai if (!err) {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai self.add(model, options);
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai }
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai callback && callback.apply(null, arguments);
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai });
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai },
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai /**
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai Returns the model with the specified _clientId_, or `null` if not found.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @method getByClientId
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {String} clientId Client id.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @return {Model} Model, or `null` if not found.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai **/
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai getByClientId: function (clientId) {
a921e6e9afbab09541d3bbbd297d0bb07c413d90Satyen Desai return this._clientIdMap[clientId] || null;
a921e6e9afbab09541d3bbbd297d0bb07c413d90Satyen Desai },
a921e6e9afbab09541d3bbbd297d0bb07c413d90Satyen Desai
a921e6e9afbab09541d3bbbd297d0bb07c413d90Satyen Desai /**
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai Returns the model with the specified _id_, or `null` if not found.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai Note that models aren't expected to have an id until they're saved, so if
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai you're working with unsaved models, it may be safer to call
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai `getByClientId()`.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @method getById
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {String} id Model id.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @return {Model} Model, or `null` if not found.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai **/
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai getById: function (id) {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai return this._idMap[id] || null;
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai },
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai /**
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai Calls the named method on every model in the list. Any arguments provided
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai after _name_ will be passed on to the invoked method.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @method invoke
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {String} name Name of the method to call on each model.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {*any} [args] Zero or more arguments to pass to the invoked method.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @return {Array} Array of return values, indexed according to the index of
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai the model on which the method was called.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai **/
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai invoke: function (name /*, *args */) {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai return YArray.invoke(this._items, name, YArray(arguments, 1, true));
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai },
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai /**
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai Returns the model at the specified _index_.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @method item
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {int} index Index of the model to fetch.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @return {Model} The model at the specified index, or `undefined` if there
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai isn't a model there.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai **/
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai // item() is inherited from ArrayList.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai /**
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai Loads this list of models from the server.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai This method delegates to the `sync()` method to perform the actual load
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai operation, which is an asynchronous action. Specify a _callback_ function to
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai be notified of success or failure.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai If the load operation succeeds, a `refresh` event will be fired.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @method load
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {Object} [options] Options to be passed to `sync()` and to
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai `refresh()` when adding the loaded models. It's up to the custom sync
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai implementation to determine what options it supports or requires, if any.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {callback} [callback] Called when the sync operation finishes.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {Error|null} callback.err If an error occurred, this parameter will
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai contain the error. If the sync operation succeeded, _err_ will be
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai `null`.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {mixed} callback.response The server's response. This value will
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai be passed to the `parse()` method, which is expected to parse it and
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai return an array of model attribute hashes.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @chainable
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai **/
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai load: function (options, callback) {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai var self = this;
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai // Allow callback as only arg.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai if (typeof options === 'function') {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai callback = options;
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai options = {};
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai }
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai this.sync('read', options, function (err, response) {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai if (!err) {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai self.refresh(self.parse(response), options);
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai }
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai callback && callback.apply(null, arguments);
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai });
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai return this;
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai },
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai /**
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai Executes the specified function on each model in this list and returns an
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai array of the function's collected return values.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @method map
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {Function} fn Function to execute on each model.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {Model} fn.model Current model being iterated.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {int} fn.index Index of the current model in the list.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {Model[]} fn.models Array of models being iterated.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {Object} [thisObj] `this` object to use when calling _fn_.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @return {Array} Array of return values from _fn_.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai **/
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai map: function (fn, thisObj) {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai return YArray.map(this._items, fn, thisObj);
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai },
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai /**
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai Called to parse the _response_ when the list is loaded from the server.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai This method receives a server _response_ and is expected to return an array
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai of model attribute hashes.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai The default implementation assumes that _response_ is either an array of
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai attribute hashes or a JSON string that can be parsed into an array of
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai attribute hashes. If _response_ is a JSON string and either `Y.JSON` or the
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai native `JSON` object are available, it will be parsed automatically. If a
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai parse error occurs, an `error` event will be fired and the model will not be
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai updated.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai You may override this method to implement custom parsing logic if necessary.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @method parse
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {mixed} response Server response.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @return {Object[]} Array of model attribute hashes.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai **/
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai parse: function (response) {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai if (typeof response === 'string') {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai if (JSON) {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai try {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai return JSON.parse(response);
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai } catch (ex) {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai Y.error('Failed to parse JSON response.');
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai return null;
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai }
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai } else {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai Y.error("Can't parse JSON response because the json-parse "
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai + "module isn't loaded.");
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai return null;
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai }
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai }
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai return response;
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai },
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai /**
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai Completely replaces all models in the list with those specified, and fires a
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai single `refresh` event.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai Use `refresh` when you want to add or remove a large number of items at once
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai without firing `add` or `remove` events for each one.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @method refresh
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {Model|Model[]|Object|Object[]} models Models to add. May be existing
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai model instances or hashes of model attributes, in which case new model
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai instances will be created from the hashes.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {Object} [options] Data to be mixed into the event facade of the
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai `refresh` event.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {Boolean} [options.silent=false] If `true`, no `refresh` event will
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai be fired.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @chainable
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai **/
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai refresh: function (models, options) {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai options || (options = {});
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai var facade = Y.merge(options, {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai src : 'refresh',
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai models: YArray.map(models, function (model) {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai return model instanceof Y.Model ? model :
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai new this.model(model);
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai }, this)
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai });
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai options.silent ? this._defRefreshFn(facade) :
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai this.fire(EVT_REFRESH, facade);
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai return this;
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai },
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai /**
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai Removes the specified model or array of models from this list.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @method remove
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {Model|Model[]} models Models to remove.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {Object} [options] Data to be mixed into the event facade of the
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai `remove` event(s) for the removed models.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {Boolean} [options.silent=false] If `true`, no `remove` event(s)
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai will be fired.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @return {Model|Model[]} Removed model or array of removed models.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai **/
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai remove: function (models, options) {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai var i, len, removed;
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
2b7125b1271732c191ab0b73be768534afd62fc5Dav Glass if (Lang.isArray(models)) {
2b7125b1271732c191ab0b73be768534afd62fc5Dav Glass removed = [];
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai for (i = 0, len = models.length; i < len; ++i) {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai removed.push(this._remove(models[i], options));
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai }
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai return removed;
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai } else {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai return this._remove(models[i], options);
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai }
d2fe481f82326b03c9a545af61f3379ac5d7fef1Satyen Desai },
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai /**
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai Forcibly re-sorts the list.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai Usually it shouldn't be necessary to call this method since the list
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai maintains its sort order when items are added and removed, but if you change
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai the `comparator` function after items are already in the list, you'll need
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai to re-sort.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @method sort
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {Object} [options] Data to be mixed into the event facade of the
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai `refresh` event.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {Boolean} [options.silent=false] If `true`, no `refresh` event will
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai be fired.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @chainable
d2fe481f82326b03c9a545af61f3379ac5d7fef1Satyen Desai **/
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai sort: function (options) {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai var comparator = this.comparator,
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai models = this._items.concat(),
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai facade;
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai if (!comparator) {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai return this;
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai }
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai options || (options = {});
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai models.sort(function (a, b) {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai var aValue = comparator(a),
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai bValue = comparator(b);
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai return a < b ? -1 : (a > b ? 1 : 0);
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai });
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai facade = Y.merge(options, {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai models: models,
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai src : 'sort'
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai });
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai options.silent ? this._defRefreshFn(facade) :
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai this.fire(EVT_REFRESH, facade);
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai return this;
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai },
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai /**
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai Override this method to provide a custom persistence implementation for this
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai list. The default method is a noop and doesn't actually do anything.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai This method is called internally by `load()`.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @method sync
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {String} action Sync action to perform. May be one of the following:
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai - `create`: Store a list of newly-created models for the first time.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai - `delete`: Delete a list of existing models.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai - 'read' : Load a list of existing models.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai - `update`: Update a list of existing models.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai Currently, model lists only make use of the `read` action, but other
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai actions may be used in future versions.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {Object} [options] Sync options. It's up to the custom sync
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai implementation to determine what options it supports or requires, if any.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {callback} [callback] Called when the sync operation finishes.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {Error|null} callback.err If an error occurred, this parameter will
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai contain the error. If the sync operation succeeded, _err_ will be
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai `null`.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {mixed} [callback.response] The server's response. This value will
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai be passed to the `parse()` method, which is expected to parse it and
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai return an array of model attribute hashes.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai **/
d2fe481f82326b03c9a545af61f3379ac5d7fef1Satyen Desai sync: function (/* action, options, callback */) {},
d2fe481f82326b03c9a545af61f3379ac5d7fef1Satyen Desai
d2fe481f82326b03c9a545af61f3379ac5d7fef1Satyen Desai /**
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai Returns an array containing the models in this list.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @method toArray
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @return {Array} Array containing the models in this list.
d2fe481f82326b03c9a545af61f3379ac5d7fef1Satyen Desai **/
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai toArray: function () {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai return this._items.concat();
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai },
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai /**
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai Override this method to return a URL corresponding to this list's location
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai on the server. The default implementation simply returns an empty string.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai The URL returned by this method will be used to make requests to the server
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai or other persistence layer when this list is loaded.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
d2fe481f82326b03c9a545af61f3379ac5d7fef1Satyen Desai @method url
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @return {String} URL for this list.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai **/
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai url: function () { return ''; },
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai // -- Protected Methods ----------------------------------------------------
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai /**
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai Adds the specified _model_ if it isn't already in this list.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @method _add
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {Model|Object} model Model or object to add.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {Object} [options] Data to be mixed into the event facade of the
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai `add` event for the added model.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {Boolean} [options.silent=false] If `true`, no `add` event will be
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai fired.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @return {Model} The added model.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @protected
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai **/
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai _add: function (model, options) {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai var facade;
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai options || (options = {});
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai if (!(model instanceof Y.Model)) {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai model = new this.model(model);
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai }
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai if (this._clientIdMap[model.get('clientId')]) {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai Y.error('Model already in list.');
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai return;
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai }
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai facade = Y.merge(options, {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai index: this._findIndex(model),
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai model: model
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai });
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai options.silent ? this._defAddFn(facade) : this.fire(EVT_ADD, facade);
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai return model;
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai },
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai /**
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai Sets the specified model's `list` attribute to point to this list and adds
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai this list as a bubble target for the model's events. Also removes the model
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai from any other list it's currently in.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @method _attachList
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {Model} model Model to attach to this list.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @protected
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai **/
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai _attachList: function (model) {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai // If the model is already attached to a list, remove it from that list.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai if (model.list) {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai model.list.remove(model);
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai }
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai // Attach this list and make it a bubble target for the model.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai model.list = this;
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai model.addTarget(this);
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai },
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai /**
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai Unsets the specified model's `list` attribute and removes this list as a
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai bubble target for the model's events.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @method _detachList
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {Model} model Model to detach.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @protected
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai **/
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai _detachList: function (model) {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai delete model.list;
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai model.removeTarget(this);
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai },
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai /**
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai Clears all internal state and the internal list of models, returning this
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai list to an empty state. Automatically detaches all models in the list.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @method _clear
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @protected
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai **/
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai _clear: function () {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai YArray.each(this._items, this._detachList, this);
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai this._clientIdMap = {};
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai this._idMap = {};
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai this._items = [];
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai },
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai /**
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai Returns the index at which the given _model_ should be inserted to maintain
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai the sort order of the list.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @method _findIndex
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {Model} model The model being inserted.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @return {int} Index at which the model should be inserted.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @protected
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai **/
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai _findIndex: function (model) {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai if (!this._items.length) { return 0; }
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai if (!this.comparator) { return this._items.length; }
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai var comparator = this.comparator,
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai items = this._items,
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai max = items.length,
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai min = 0,
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai needle = comparator(model),
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai middle;
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai // Perform an iterative binary search to determine the correct position
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai // based on the return value of the `comparator` function.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai while (min < max) {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai middle = (min + max) / 2;
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai if (comparator(items[middle]) < needle) {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai min = middle + 1;
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai } else {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai max = middle;
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai }
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai }
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai return min;
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai },
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai /**
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai Removes the specified _model_ if it's in this list.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @method _remove
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {Model} model Model to remove.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {Object} [options] Data to be mixed into the event facade of the
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai `remove` event for the removed model.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @param {Boolean} [options.silent=false] If `true`, no `remove` event will
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai be fired.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @return {Model} Removed model.
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai @protected
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai **/
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai _remove: function (model, options) {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai var index = this.indexOf(model),
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai facade;
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai options || (options = {});
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai if (index === -1) {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai Y.error('Model not in list.');
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai return;
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai }
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai facade = Y.merge(options, {
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai index: index,
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai model: model
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai });
fdaf522f78615dc3145b1771f6f8daba2df06bb6Satyen Desai
2b7125b1271732c191ab0b73be768534afd62fc5Dav Glass options.silent ? this._defRemoveFn(facade) :
this.fire(EVT_REMOVE, facade);
return model;
},
// -- Event Handlers -------------------------------------------------------
/**
Updates the model maps when a model's `id` attribute changes.
@method _afterIdChange
@param {EventFacade} e
@protected
**/
_afterIdChange: function (e) {
// TODO: is e.target always guaranteed to be the model that changed?
e.prevVal && delete this._idMap[e.prevVal];
e.newVal && (this._idMap[newVal] = e.target);
},
// -- Default Event Handlers -----------------------------------------------
/**
Default event handler for `add` events.
@method _defAddFn
@param {EventFacade} e
@protected
**/
_defAddFn: function (e) {
var model = e.model,
id = model.get('id');
this._clientIdMap[model.get('clientId')] = model;
if (id) {
this._idMap[id] = model;
}
this._attachList(model);
this._items.splice(e.index, 0, model);
},
/**
Default event handler for `refresh` events.
@method _defRefreshFn
@param {EventFacade} e
@protected
**/
_defRefreshFn: function (e) {
// When fired from the `sort` method, we don't need to clear the list or
// add any models, since the existing models are sorted in place.
if (e.src === 'sort') {
this._items = e.models.concat();
return;
}
this._clear();
if (e.models.length) {
this.add(e.models, {silent: true});
}
},
/**
Default event handler for `remove` events.
@method _defRemoveFn
@param {EventFacade} e
@protected
**/
_defRemoveFn: function (e) {
var model = e.model,
id = model.get('id');
this._detachList(model);
delete this._clientIdMap[model.get('clientId')];
if (id) {
delete this._idMap[id];
}
this._items.splice(e.index, 1);
}
}, {
NAME: 'modelList'
});
Y.augment(ModelList, Y.ArrayList);
/**
Returns an array containing the values of the specified attribute from each
model in this list.
@method get
@param {String} name Attribute name or object property path.
@return {Array} Array of attribute values.
@see Model.get()
**/
/**
Returns an array containing the HTML-escaped versions of the values of the
specified string attributes from each model in this list. The values are escaped
using `Y.Escape.html()`.
@method getAsHTML
@param {String} name Attribute name or object property path.
@return {String[]} Array of HTML-escaped attribute values.
@see Model.getAsHTML()
**/
/**
Returns an array containing the URL-encoded versions of the values of the
specified string attributes from each model in this list. The values are encoded
using the native `encodeURIComponent()` function.
@method getAsURL
@param {String} name Attribute name or object property path.
@return {String[]} Array of URL-encoded attribute values.
@see Model.getAsURL()
**/
/**
Returns an array containing copies of the attributes of each model in this list,
suitable for being passed to `Y.JSON.stringify()`.
@method toJSON
@return {Object[]} Array of attribute hashes.
@see Model.toJSON()
**/
Y.ArrayList.addMethod(ModelList.prototype, [
'get', 'getAsHTML', 'getAsURL', 'toJSON'
]);
}, '@VERSION@', {
requires: [
'array-extras', 'array-invoke', 'arraylist', 'base-build', 'model'
]
});