model.js revision 87b4846e2d395d3f76f87f727e1d9dc280a0935d
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncAttribute-based data model with APIs for getting, setting, validating, and
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncsyncing attribute values, as well as events for being notified of model changes.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync@submodule model
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync@since 3.4.0
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncAttribute-based data model with APIs for getting, setting, validating, and
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncsyncing attribute values, as well as events for being notified of model changes.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncIn most cases, you'll want to create your own subclass of `Y.Model` and
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsynccustomize it to meet your needs. In particular, the `sync()` and `validate()`
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncmethods are meant to be overridden by custom implementations. You may also want
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncto override the `parse()` method to parse non-generic server responses.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync@class Model
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync@constructor
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync@extends Base
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync@since 3.4.0
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Fired when one or more attributes on this model are changed.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @event change
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {Object} changed Hash of change information for each attribute that
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync changed. Each item in the hash has the following properties:
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {Any} changed.newVal New value of the attribute.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {Any} changed.prevVal Previous value of the attribute.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {String|null} changed.src Source of the change event, if any.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Fired when an error occurs, such as when the model doesn't validate or when
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync a sync layer response can't be parsed.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @event error
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {Any} error Error message, object, or exception generated by the
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync error. Calling `toString()` on this should result in a meaningful error
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {String} src Source of the error. May be one of the following (or any
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync custom error source defined by a Model subclass):
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * `load`: An error loading the model from a sync layer. The sync layer's
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync response (if any) will be provided as the `response` property on the
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync event facade.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * `parse`: An error parsing a JSON response. The response in question will
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync be provided as the `response` property on the event facade.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * `save`: An error saving the model to a sync layer. The sync layer's
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync response (if any) will be provided as the `response` property on the
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync event facade.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * `validate`: The model failed to validate. The attributes being validated
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync will be provided as the `attributes` property on the event facade.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Fired after model attributes are loaded from a sync layer.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @event load
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {Object} parsed The parsed version of the sync layer's response to
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync the load request.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {any} response The sync layer's raw, unparsed response to the load
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @since 3.5.0
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Fired after model attributes are saved to a sync layer.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @event save
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {Object} [parsed] The parsed version of the sync layer's response to
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync the save request, if there was a response.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {any} [response] The sync layer's raw, unparsed response to the save
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync request, if there was one.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @since 3.5.0
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Model.superclass.constructor.apply(this, arguments);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // -- Public Properties ----------------------------------------------------
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Hash of attributes that have changed since the last time this model was
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @property changed
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @type Object
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @default {}
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Name of the attribute to use as the unique id (or primary key) for this
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync The default is `id`, but if your persistence layer uses a different name for
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync the primary key (such as `_id` or `uid`), you can specify that here.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync The built-in `id` attribute will always be an alias for whatever attribute
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync name you specify here, so getting and setting `id` will always behave the
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync same as getting and setting your custom id attribute.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @property idAttribute
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @type String
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @default `'id'`
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Hash of attributes that were changed in the last `change` event. Each item
b025d5f11836934ade517ff53604078b5aff12e5vboxsync in this hash is an object with the following properties:
b025d5f11836934ade517ff53604078b5aff12e5vboxsync * `newVal`: The new value of the attribute after it changed.
b025d5f11836934ade517ff53604078b5aff12e5vboxsync * `prevVal`: The old value of the attribute before it changed.
b025d5f11836934ade517ff53604078b5aff12e5vboxsync * `src`: The source of the change, or `null` if no source was specified.
b025d5f11836934ade517ff53604078b5aff12e5vboxsync @property lastChange
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @type Object
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @default {}
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Array of `ModelList` instances that contain this model.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync When a model is in one or more lists, the model's events will bubble up to
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync those lists. You can subscribe to a model event on a list to be notified
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync when any model in the list fires that event.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync This property is updated automatically when this model is added to or
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync removed from a `ModelList` instance. You shouldn't alter it manually. When
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync working with models in a list, you should always add and remove models using
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync the list's `add()` and `remove()` methods.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @example Subscribing to model events on a list:
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // Assuming `list` is an existing Y.ModelList instance.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync list.on('*:change', function (e) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // This function will be called whenever any model in the list
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // fires a `change` event.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // `e.target` will refer to the model instance that fired the
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @property lists
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @type ModelList[]
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @default `[]`
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // -- Protected Properties -------------------------------------------------
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync This tells `Y.Base` that it should create ad-hoc attributes for config
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync properties passed to Model's constructor. This makes it possible to
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync instantiate a model and set a bunch of attributes without having to subclass
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync `Y.Model` and declare all those attributes first.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @property _allowAdHocAttrs
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @type Boolean
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @default true
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @since 3.5.0
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Total hack to allow us to identify Model instances without using
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync `instanceof`, which won't work when the instance was created in another
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync window or YUI sandbox.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @property _isYUIModel
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @type Boolean
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @default true
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @since 3.5.0
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // -- Lifecycle Methods ----------------------------------------------------
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // -- Public Methods -------------------------------------------------------
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Destroys this model instance and removes it from its containing lists, if
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync The _callback_, if one is provided, will be called after the model is
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync If `options.remove` is `true`, then this method delegates to the `sync()`
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync method to delete the model from the persistence layer, which is an
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync asynchronous action. In this case, the _callback_ (if provided) will be
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync called after the sync layer indicates success or failure of the delete
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @method destroy
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {Object} [options] Sync options. It's up to the custom sync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync implementation to determine what options it supports or requires, if
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {Boolean} [options.remove=false] If `true`, the model will be
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync deleted via the sync layer in addition to the instance being destroyed.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {callback} [callback] Called after the model has been destroyed (and
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync deleted via the sync layer if `options.remove` is `true`).
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {Error|null} callback.err If an error occurred, this parameter will
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync contain the error. Otherwise _err_ will be `null`.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync var self = this;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // Allow callback as only arg.
3268c8aab4681e1f7aff21e300dd0fdef1bb6f7fvboxsync if (options && (options.remove || options['delete'])) {
3a17531e9a12c3582ebe7a0e76f562b70d4875c1vboxsync Returns a clientId string that's unique among all models on the current page
3a17531e9a12c3582ebe7a0e76f562b70d4875c1vboxsync (even models in other YUI instances). Uniqueness across pageviews is
3a17531e9a12c3582ebe7a0e76f562b70d4875c1vboxsync @method generateClientId
3a17531e9a12c3582ebe7a0e76f562b70d4875c1vboxsync @return {String} Unique clientId.
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync generateClientId: function () {
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync return this.constructor.NAME + '_' + (GlobalEnv.lastId += 1);
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync Returns the value of the specified attribute.
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync If the attribute's value is an object, _name_ may use dot notation to
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync specify the path to a specific property within the object, and the value of
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync that property will be returned.
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync // Set the 'foo' attribute to an object.
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync myModel.set('foo', {
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync baz: 'quux'
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync // Get the value of 'foo'.
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync myModel.get('foo');
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync // => {bar: {baz: 'quux'}}
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync // Get the value of 'foo.bar.baz'.
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync myModel.get('foo.bar.baz');
57f59a6f0c871da46b4c8f2e71a0f6a1d0bf772evboxsync // => 'quux'
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync @method get
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync @param {String} name Attribute name or object property path.
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync @return {Any} Attribute value, or `undefined` if the attribute doesn't
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync // get() is defined by Y.Attribute.
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync Returns an HTML-escaped version of the value of the specified string
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync attribute. The value is escaped using `Y.Escape.html()`.
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync @method getAsHTML
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync @param {String} name Attribute name or object property path.
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync @return {String} HTML-escaped attribute value.
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync return Y.Escape.html(Lang.isValue(value) ? String(value) : '');
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync Returns a URL-encoded version of the value of the specified string
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync attribute. The value is encoded using the native `encodeURIComponent()`
57f59a6f0c871da46b4c8f2e71a0f6a1d0bf772evboxsync @method getAsURL
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync @param {String} name Attribute name or object property path.
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync @return {String} URL-encoded attribute value.
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync return encodeURIComponent(Lang.isValue(value) ? String(value) : '');
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync Returns `true` if any attribute of this model has been changed since the
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync model was last saved.
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync New models (models for which `isNew()` returns `true`) are implicitly
cb1b4ee184d6bc409437422b8dbeaf4f0ba5f398vboxsync considered to be "modified" until the first time they're saved.
4084fd2e85cf5edb77bfc0b444c30c3e3a13be03vboxsync @method isModified
4084fd2e85cf5edb77bfc0b444c30c3e3a13be03vboxsync @return {Boolean} `true` if this model has changed since it was last saved,
57f59a6f0c871da46b4c8f2e71a0f6a1d0bf772evboxsync `false` otherwise.
4084fd2e85cf5edb77bfc0b444c30c3e3a13be03vboxsync isModified: function () {
4084fd2e85cf5edb77bfc0b444c30c3e3a13be03vboxsync return this.isNew() || !YObject.isEmpty(this.changed);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Returns `true` if this model is "new", meaning it hasn't been saved since it
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync was created.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Newness is determined by checking whether the model's `id` attribute has
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync been set. An empty id is assumed to indicate a new model, whereas a
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync non-empty id indicates a model that was either loaded or has been saved
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync since it was created.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @method isNew
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @return {Boolean} `true` if this model is new, `false` otherwise.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync isNew: function () {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Loads this model from the server.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync This method delegates to the `sync()` method to perform the actual load
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync operation, which is an asynchronous action. Specify a _callback_ function to
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync be notified of success or failure.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync A successful load operation will fire a `load` event, while an unsuccessful
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync load operation will fire an `error` event with the `src` value "load".
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync If the load operation succeeds and one or more of the loaded attributes
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync differ from this model's current attributes, a `change` event will be fired.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @method load
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {Object} [options] Options to be passed to `sync()` and to `set()`
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync when setting the loaded attributes. It's up to the custom sync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync implementation to determine what options it supports or requires, if any.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {callback} [callback] Called when the sync operation finishes.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {Error|null} callback.err If an error occurred, this parameter will
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync contain the error. If the sync operation succeeded, _err_ will be
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {Any} callback.response The server's response. This value will
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync be passed to the `parse()` method, which is expected to parse it and
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return an attribute hash.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync var self = this;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // Allow callback as only arg.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync self.sync('read', options, function (err, response) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // Lazy publish.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Called to parse the _response_ when the model is loaded from the server.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync This method receives a server _response_ and is expected to return an
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync attribute hash.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync The default implementation assumes that _response_ is either an attribute
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync hash or a JSON string that can be parsed into an attribute hash. If
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync _response_ is a JSON string and either `Y.JSON` or the native `JSON` object
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync are available, it will be parsed automatically. If a parse error occurs, an
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync `error` event will be fired and the model will not be updated.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync You may override this method to implement custom parsing logic if necessary.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @method parse
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {Any} response Server response.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @return {Object} Attribute hash.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync } catch (ex) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return null;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Saves this model to the server.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync This method delegates to the `sync()` method to perform the actual save
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync operation, which is an asynchronous action. Specify a _callback_ function to
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync be notified of success or failure.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync A successful save operation will fire a `save` event, while an unsuccessful
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync save operation will fire an `error` event with the `src` value "save".
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync If the save operation succeeds and one or more of the attributes returned in
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync the server's response differ from this model's current attributes, a
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync `change` event will be fired.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @method save
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {Object} [options] Options to be passed to `sync()` and to `set()`
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync when setting synced attributes. It's up to the custom sync implementation
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync to determine what options it supports or requires, if any.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {Function} [callback] Called when the sync operation finishes.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {Error|null} callback.err If an error occurred or validation
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync failed, this parameter will contain the error. If the sync operation
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync succeeded, _err_ will be `null`.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {Any} callback.response The server's response. This value will
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync be passed to the `parse()` method, which is expected to parse it and
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return an attribute hash.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync var self = this;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // Allow callback as only arg.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync self.sync(self.isNew() ? 'create' : 'update', options, function (err, response) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // Lazy publish.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Sets the value of a single attribute. If model validation fails, the
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync attribute will not be set and an `error` event will be fired.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Use `setAttrs()` to set multiple attributes at once.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync model.set('foo', 'bar');
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @method set
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {String} name Attribute name or object property path.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {any} value Value to set.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {Object} [options] Data to be mixed into the event facade of the
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync `change` event(s) for these attributes.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {Boolean} [options.silent=false] If `true`, no `change` event will
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Sets the values of multiple attributes at once. If model validation fails,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync the attributes will not be set and an `error` event will be fired.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync model.setAttrs({
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync foo: 'bar',
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync baz: 'quux'
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @method setAttrs
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {Object} attributes Hash of attribute names and values to set.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {Object} [options] Data to be mixed into the event facade of the
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync `change` event(s) for these attributes.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {Boolean} [options.silent=false] If `true`, no `change` event will
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // When a custom id attribute is in use, always keep the default `id`
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // attribute in sync.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // So we don't modify someone else's object.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // Lazy publish for the change event.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync this.fire(EVT_CHANGE, Y.merge(options, {changed: lastChange}));
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return this;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Override this method to provide a custom persistence implementation for this
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync model. The default just calls the callback without actually doing anything.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync This method is called internally by `load()`, `save()`, and `destroy()`.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @method sync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {String} action Sync action to perform. May be one of the following:
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * `create`: Store a newly-created model for the first time.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * `delete`: Delete an existing model.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * `read` : Load an existing model.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * `update`: Update an existing model.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {Object} [options] Sync options. It's up to the custom sync
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync implementation to determine what options it supports or requires, if any.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {Function} [callback] Called when the sync operation finishes.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {Error|null} callback.err If an error occurred, this parameter will
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync contain the error. If the sync operation succeeded, _err_ will be
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {Any} [callback.response] The server's response.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Returns a copy of this model's attributes that can be passed to
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync `Y.JSON.stringify()` or used for other nefarious purposes.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync The `clientId` attribute is not included in the returned object.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync If you've specified a custom attribute name in the `idAttribute` property,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync the default `id` attribute will not be included in the returned object.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Note: This method is named `toJSON()`, but it returns an object, not a JSON
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync string. We know that. It's not because we're idiots who are incapable of
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync naming things. It's because the method name "toJSON" and the object return
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync type are specified in the ECMAScript 5 standard. Adhering to this standard
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync allows you to stringify a model by doing `JSON.stringify(model)` if you want
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync to. Please don't file a bug telling us we're idiots. We'll just sigh, cry a
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync little, and mark the bug invalid.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @method toJSON
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @return {Object} Copy of this model's attributes.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync toJSON: function () {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Reverts the last change to the model.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync If an _attrNames_ array is provided, then only the named attributes will be
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync reverted (and only if they were modified in the previous change). If no
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync _attrNames_ array is provided, then all changed attributes will be reverted
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync to their previous values.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Note that only one level of undo is available: from the current state to the
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync previous state. If `undo()` is called when no previous state is available,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync it will simply do nothing.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @method undo
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {Array} [attrNames] Array of specific attribute names to revert. If
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync not specified, all attributes modified in the last change will be
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {Object} [options] Data to be mixed into the event facade of the
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync change event(s) for these attributes.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {Boolean} [options.silent=false] If `true`, no `change` event will
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync attrNames || (attrNames = YObject.keys(lastChange));
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // Don't generate a double change for custom id attributes.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return needUndo ? this.setAttrs(toUndo, options) : this;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Override this method to provide custom validation logic for this model.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync While attribute-specific validators can be used to validate individual
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync attributes, this method gives you a hook to validate a hash of all
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync attributes before the model is saved. This method is called automatically
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync before `save()` takes any action. If validation fails, the `save()` call
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync will be aborted.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync In your validation method, call the provided `callback` function with no
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync arguments to indicate success. To indicate failure, pass a single argument,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync which may contain an error message, an array of error messages, or any other
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync value. This value will be passed along to the `error` event.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync model.validate = function (attrs, callback) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (attrs.pie !== true) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // No pie?! Invalid!
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync callback('Must provide pie.');
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // Success!
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync callback();
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @method validate
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {Object} attrs Attribute hash containing all model attributes to
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync be validated.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {Function} callback Validation callback. Call this function when your
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync validation logic finishes. To trigger a validation failure, pass any
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync value as the first argument to the callback (ideally a meaningful
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync validation error of some kind).
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {Any} [callback.err] Validation error. Don't provide this
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync argument if validation succeeds. If validation fails, set this to an
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync error message or some other meaningful value. It will be passed
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync along to the resulting `error` event.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // -- Protected Methods ----------------------------------------------------
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Duckpunches the `addAttr` method provided by `Y.Attribute` to keep the
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync `id` attribute’s value and a custom id attribute’s (if provided) value
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync in sync when adding the attributes to the model instance object.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Marked as protected to hide it from Model's public API docs, even though
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync this is a public method in Attribute.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @method addAttr
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {String} name The name of the attribute.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {Object} config An object with attribute configuration property/value
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync pairs, specifying the configuration for the attribute.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {Boolean} lazy (optional) Whether or not to add this attribute lazily
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync (on the first call to get/set).
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @return {Object} A reference to the host object.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync idAttrCfg = this._isLazyAttr('id') || this._getAttrCfg('id');
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync id = config.value === config.defaultValue ? null : config.value;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // Hunt for the id value.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync id = idAttrCfg.value === idAttrCfg.defaultValue ? null : idAttrCfg.value;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // No id value provided on construction, check defaults.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // Make sure `id` is in sync.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return Model.superclass.addAttr.apply(this, arguments);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Calls the public, overridable `validate()` method and fires an `error` event
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if validation fails.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @method _validate
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {Object} attributes Attribute hash.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {Function} callback Validation callback.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {Any} [callback.err] Value on failure, non-value on success.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync var self = this;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // Validation failed. Fire an error.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // Backcompat for 3.4.x-style synchronous validate() functions that
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // don't take a callback argument.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // -- Protected Event Handlers ---------------------------------------------
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Duckpunches the `_defAttrChangeFn()` provided by `Y.Attribute` so we can
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync have a single global notification when a change event occurs.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @method _defAttrChangeFn
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @param {EventFacade} e
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync _defAttrChangeFn: function (e) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (!this._setAttrVal(attrName, e.subAttrName, e.prevVal, e.newVal)) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync // Prevent "after" listeners from being invoked since nothing changed.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync A client-only identifier for this model.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Like the `id` attribute, `clientId` may be used to retrieve model
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync instances from lists. Unlike the `id` attribute, `clientId` is
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync automatically generated, and is only intended to be used on the client
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync during the current pageview.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @attribute clientId
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @type String
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync A unique identifier for this model. Among other things, this id may be
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync used to retrieve model instances from lists, so it should be unique.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync If the id is empty, this model instance is assumed to represent a new
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync item that hasn't yet been saved.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync If you would prefer to use a custom attribute as this model's id instead
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync of using the `id` attribute (for example, maybe you'd rather use `_id`
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync or `uid` as the primary id), you may set the `idAttribute` property to
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync the name of your custom id attribute. The `id` attribute will then
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync act as an alias for your custom attribute.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @attribute id
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @type String|Number|null
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync @default `null`
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync}, '@VERSION@' ,{requires:['base-build', 'escape', 'json-parse']});