model.js revision 8307dadbd4aa4ba4079d3c37394493a808c941d3
0fdefaa9ca017edfb76b736c825b34186f33045aTrippAttribute-based data model with APIs for getting, setting, validating, and
0fdefaa9ca017edfb76b736c825b34186f33045aTrippsyncing attribute values, as well as events for being notified of model changes.
0fdefaa9ca017edfb76b736c825b34186f33045aTrippIn most cases, you'll want to create your own subclass of `Y.Model` and
0fdefaa9ca017edfb76b736c825b34186f33045aTrippcustomize it to meet your needs. In particular, the `sync()`, `url()`, and
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp`validate()` methods are meant to be overridden by custom implementations.
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTrippYou may also want to override the `parse()` method to parse non-generic server
828c58761d90445b8b9d20a82d85dc1479317f71Tripp@module model
828c58761d90445b8b9d20a82d85dc1479317f71Tripp@class Model
ed59119d8c00addb07c7ee6c8aefcd1d9cb876f1Tripp@constructor
5ecb8c8b041752f6b716054ff5cfc2c9992365c6Tripp YObject = Y.Object,
66ca16dd76367c074fe4df1dcf7b555489a9bf85Tripp Fired when one or more attributes on this model are changed.
66ca16dd76367c074fe4df1dcf7b555489a9bf85Tripp @event change
66ca16dd76367c074fe4df1dcf7b555489a9bf85Tripp @param {Object} changed Hash of change information for each attribute that
e7c7565d9550eaa87043aef0df77125ada996deaTripp changed. Each item in the hash has the following properties:
e7c7565d9550eaa87043aef0df77125ada996deaTripp @param {mixed} changed.newVal New value of the attribute.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @param {mixed} changed.prevVal Previous value of the attribute.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @param {String|null} changed.src Source of the change event, if any.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp Fired when an error occurs, such as when the model doesn't validate or when
828c58761d90445b8b9d20a82d85dc1479317f71Tripp a server response can't be parsed.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @event error
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @param {String} type Type of error that occurred. May be one of the
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp * `parse`: An error parsing a JSON response.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp * `validate`: The model failed to validate.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @param {mixed} error Error message, object, or exception generated by the
828c58761d90445b8b9d20a82d85dc1479317f71Tripp error. Calling `toString()` on this should result in a meaningful error
828c58761d90445b8b9d20a82d85dc1479317f71Trippfunction Model() {
828c58761d90445b8b9d20a82d85dc1479317f71Tripp // -- Public Properties ----------------------------------------------------
828c58761d90445b8b9d20a82d85dc1479317f71Tripp Hash of attributes that have changed since the last time this model was
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @property changed
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @type Object
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @default {}
828c58761d90445b8b9d20a82d85dc1479317f71Tripp Name of the attribute to use as the unique id (or primary key) for this
828c58761d90445b8b9d20a82d85dc1479317f71Tripp The default is `id`, but if your persistence layer uses a different name for
828c58761d90445b8b9d20a82d85dc1479317f71Tripp the primary key (such as `_id` or `uid`), you can specify that here.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp The built-in `id` attribute will always be an alias for whatever attribute
828c58761d90445b8b9d20a82d85dc1479317f71Tripp name you specify here, so getting and setting `id` will always behave the
828c58761d90445b8b9d20a82d85dc1479317f71Tripp same as getting and setting your custom id attribute.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @property idAttribute
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @type String
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @default `'id'`
828c58761d90445b8b9d20a82d85dc1479317f71Tripp Hash of attributes that were changed in the last `change` event. Each item
828c58761d90445b8b9d20a82d85dc1479317f71Tripp in this hash is an object with the following properties:
828c58761d90445b8b9d20a82d85dc1479317f71Tripp - `newVal`: The new value of the attribute after it changed.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp - `prevVal`: The old value of the attribute before it changed.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp - `src`: The source of the change, or `null` if no source was specified.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @property lastChange
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @type Object
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @default {}
828c58761d90445b8b9d20a82d85dc1479317f71Tripp `ModelList` instance that contains this model, or `null` if this model is
828c58761d90445b8b9d20a82d85dc1479317f71Tripp not contained by a list.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp This property is set automatically when a model is added to or removed from
828c58761d90445b8b9d20a82d85dc1479317f71Tripp a `ModelList` instance. You shouldn't need to set it manually. When working
828c58761d90445b8b9d20a82d85dc1479317f71Tripp with models in a list, you should always add and remove models using the
828c58761d90445b8b9d20a82d85dc1479317f71Tripp lists `add()` and `remove()` methods.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @property list
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @type ModelList
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @default `null`
828c58761d90445b8b9d20a82d85dc1479317f71Tripp // -- Lifecycle Methods ----------------------------------------------------
828c58761d90445b8b9d20a82d85dc1479317f71Tripp // TODO: destructor?
828c58761d90445b8b9d20a82d85dc1479317f71Tripp // -- Public Methods -------------------------------------------------------
828c58761d90445b8b9d20a82d85dc1479317f71Tripp Destroys this model instance and removes it from its containing list, if
828c58761d90445b8b9d20a82d85dc1479317f71Tripp If `options['delete']` is `true`, then this method also delegates to the
828c58761d90445b8b9d20a82d85dc1479317f71Tripp `sync()` method to delete the model from the persistence layer, which is an
828c58761d90445b8b9d20a82d85dc1479317f71Tripp asynchronous action. Provide a _callback_ function to be notified of success
828c58761d90445b8b9d20a82d85dc1479317f71Tripp or failure.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @method destroy
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @param {Object} [options] Sync options. It's up to the custom sync
828c58761d90445b8b9d20a82d85dc1479317f71Tripp implementation to determine what options it supports or requires, if
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @param {Boolean} [options.delete=false] If `true`, the model will be
828c58761d90445b8b9d20a82d85dc1479317f71Tripp deleted via the sync layer in addition to the instance being destroyed.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @param {callback} [callback] Called when the sync operation finishes.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @param {Error|null} callback.err If an error occurred, this parameter will
828c58761d90445b8b9d20a82d85dc1479317f71Tripp contain the error. If the sync operation succeeded, _err_ will be
828c58761d90445b8b9d20a82d85dc1479317f71Tripp var self = this;
828c58761d90445b8b9d20a82d85dc1479317f71Tripp // Allow callback as only arg.
66ca16dd76367c074fe4df1dcf7b555489a9bf85Tripp return this;
828c58761d90445b8b9d20a82d85dc1479317f71Tripp Returns a clientId string that's unique among all models on the current page
828c58761d90445b8b9d20a82d85dc1479317f71Tripp (even models in other YUI instances). Uniqueness across pageviews is
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @method generateClientId
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @return {String} Unique clientId.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp generateClientId: function () {
828c58761d90445b8b9d20a82d85dc1479317f71Tripp Returns the value of the specified attribute.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp If the attribute's value is an object, _name_ may use dot notation to
828c58761d90445b8b9d20a82d85dc1479317f71Tripp specify the path to a specific property within the object, and the value of
828c58761d90445b8b9d20a82d85dc1479317f71Tripp that property will be returned.
66ca16dd76367c074fe4df1dcf7b555489a9bf85Tripp // Set the 'foo' attribute to an object.
66ca16dd76367c074fe4df1dcf7b555489a9bf85Tripp myModel.set('foo', {
828c58761d90445b8b9d20a82d85dc1479317f71Tripp baz: 'quux'
828c58761d90445b8b9d20a82d85dc1479317f71Tripp // Get the value of 'foo'.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp myModel.get('foo');
66ca16dd76367c074fe4df1dcf7b555489a9bf85Tripp // => {bar: {baz: 'quux'}}
828c58761d90445b8b9d20a82d85dc1479317f71Tripp // Get the value of 'foo.bar.baz'.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp myModel.get('foo.bar.baz');
828c58761d90445b8b9d20a82d85dc1479317f71Tripp // => 'quux'
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @method get
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @param {String} name Attribute name or object property path.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @return {mixed} Attribute value, or `undefined` if the attribute doesn't
828c58761d90445b8b9d20a82d85dc1479317f71Tripp // get() is defined by Y.Attribute.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp Returns an HTML-escaped version of the value of the specified string
828c58761d90445b8b9d20a82d85dc1479317f71Tripp attribute. The value is escaped using `Y.Escape.html()`.
66ca16dd76367c074fe4df1dcf7b555489a9bf85Tripp @method getAsHTML
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @param {String} name Attribute name or object property path.
66ca16dd76367c074fe4df1dcf7b555489a9bf85Tripp @return {String} HTML-escaped attribute value.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp return Y.Escape.html(Lang.isValue(value) ? String(value) : '');
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp Returns a URL-encoded version of the value of the specified string
828c58761d90445b8b9d20a82d85dc1479317f71Tripp attribute. The value is encoded using the native `encodeURIComponent()`
0341dba359758fa73cc2f2ae9f6f8ebe9bfa94beTripp @method getAsURL
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @param {String} name Attribute name or object property path.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @return {String} URL-encoded attribute value.
66ca16dd76367c074fe4df1dcf7b555489a9bf85Tripp return encodeURIComponent(Lang.isValue(value) ? String(value) : '');
828c58761d90445b8b9d20a82d85dc1479317f71Tripp Returns `true` if any attribute of this model has been changed since the
828c58761d90445b8b9d20a82d85dc1479317f71Tripp model was last saved.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp New models (models for which `isNew()` returns `true`) are implicitly
080b31a43c2a1d068c28eaa3e243bdd6e8a89ffaTripp considered to be "modified" until the first time they're saved.
080b31a43c2a1d068c28eaa3e243bdd6e8a89ffaTripp @method isModified
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @return {Boolean} `true` if this model has changed since it was last saved,
828c58761d90445b8b9d20a82d85dc1479317f71Tripp `false` otherwise.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp isModified: function () {
828c58761d90445b8b9d20a82d85dc1479317f71Tripp return this.isNew() || !YObject.isEmpty(this.changed);
66ca16dd76367c074fe4df1dcf7b555489a9bf85Tripp Returns `true` if this model is "new", meaning it hasn't been saved since it
828c58761d90445b8b9d20a82d85dc1479317f71Tripp was created.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp Newness is determined by checking whether the model's `id` attribute has
828c58761d90445b8b9d20a82d85dc1479317f71Tripp been set. An empty id is assumed to indicate a new model, whereas a
828c58761d90445b8b9d20a82d85dc1479317f71Tripp non-empty id indicates a model that was either loaded or has been saved
aeee02c921674c7c98f1e3cbfdaa32b7da4a1ad5Tripp since it was created.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @method isNew
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @return {Boolean} `true` if this model is new, `false` otherwise.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp isNew: function () {
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp Loads this model from the server.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp This method delegates to the `sync()` method to perform the actual load
828c58761d90445b8b9d20a82d85dc1479317f71Tripp operation, which is an asynchronous action. Specify a _callback_ function to
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp be notified of success or failure.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp If the load operation succeeds and one or more of the loaded attributes
aeee02c921674c7c98f1e3cbfdaa32b7da4a1ad5Tripp differ from this model's current attributes, a `change` event will be fired.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @method load
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @param {Object} [options] Options to be passed to `sync()` and to `set()`
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp when setting the loaded attributes. It's up to the custom sync
828c58761d90445b8b9d20a82d85dc1479317f71Tripp implementation to determine what options it supports or requires, if any.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @param {callback} [callback] Called when the sync operation finishes.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @param {Error|null} callback.err If an error occurred, this parameter will
828c58761d90445b8b9d20a82d85dc1479317f71Tripp contain the error. If the sync operation succeeded, _err_ will be
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @param {mixed} callback.response The server's response. This value will
828c58761d90445b8b9d20a82d85dc1479317f71Tripp be passed to the `parse()` method, which is expected to parse it and
828c58761d90445b8b9d20a82d85dc1479317f71Tripp return an attribute hash.
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp var self = this;
828c58761d90445b8b9d20a82d85dc1479317f71Tripp // Allow callback as only arg.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp return this;
9cc2c5945426b2b79c0a258026d750be74795924Tripp Called to parse the _response_ when the model is loaded from the server.
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp This method receives a server _response_ and is expected to return an
828c58761d90445b8b9d20a82d85dc1479317f71Tripp attribute hash.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp The default implementation assumes that _response_ is either an attribute
828c58761d90445b8b9d20a82d85dc1479317f71Tripp hash or a JSON string that can be parsed into an attribute hash. If
828c58761d90445b8b9d20a82d85dc1479317f71Tripp _response_ is a JSON string and either `Y.JSON` or the native `JSON` object
828c58761d90445b8b9d20a82d85dc1479317f71Tripp are available, it will be parsed automatically. If a parse error occurs, an
828c58761d90445b8b9d20a82d85dc1479317f71Tripp `error` event will be fired and the model will not be updated.
66ca16dd76367c074fe4df1dcf7b555489a9bf85Tripp You may override this method to implement custom parsing logic if necessary.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @method parse
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @param {mixed} response Server response.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @return {Object} Attribute hash.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp } catch (ex) {
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp return null;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp Y.error("Can't parse JSON response because the json-parse "
828c58761d90445b8b9d20a82d85dc1479317f71Tripp + "module isn't loaded.");
828c58761d90445b8b9d20a82d85dc1479317f71Tripp return null;
6a3585e2672045e8e28e6a45f279f80aef446959Tripp Saves this model to the server.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp This method delegates to the `sync()` method to perform the actual save
ed59119d8c00addb07c7ee6c8aefcd1d9cb876f1Tripp operation, which is an asynchronous action. Specify a _callback_ function to
ed59119d8c00addb07c7ee6c8aefcd1d9cb876f1Tripp be notified of success or failure.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp If the save operation succeeds and one or more of the attributes returned in
6c4ec9d420df654d019b936fd06bef6f769db4cbTripp the server's response differ from this model's current attributes, a
ed59119d8c00addb07c7ee6c8aefcd1d9cb876f1Tripp `change` event will be fired.
ed59119d8c00addb07c7ee6c8aefcd1d9cb876f1Tripp @method save
6c4ec9d420df654d019b936fd06bef6f769db4cbTripp @param {Object} [options] Options to be passed to `sync()` and to `set()`
6c4ec9d420df654d019b936fd06bef6f769db4cbTripp when setting synced attributes. It's up to the custom sync implementation
6c4ec9d420df654d019b936fd06bef6f769db4cbTripp to determine what options it supports or requires, if any.
6a3585e2672045e8e28e6a45f279f80aef446959Tripp @param {callback} [callback] Called when the sync operation finishes.
ed59119d8c00addb07c7ee6c8aefcd1d9cb876f1Tripp @param {Error|null} callback.err If an error occurred, this parameter will
6c4ec9d420df654d019b936fd06bef6f769db4cbTripp contain the error. If the sync operation succeeded, _err_ will be
0fdefaa9ca017edfb76b736c825b34186f33045aTripp @param {mixed} callback.response The server's response. This value will
6c4ec9d420df654d019b936fd06bef6f769db4cbTripp be passed to the `parse()` method, which is expected to parse it and
ed59119d8c00addb07c7ee6c8aefcd1d9cb876f1Tripp return an attribute hash.
ed59119d8c00addb07c7ee6c8aefcd1d9cb876f1Tripp var self = this;
ed59119d8c00addb07c7ee6c8aefcd1d9cb876f1Tripp // Allow callback as only arg.
ed59119d8c00addb07c7ee6c8aefcd1d9cb876f1Tripp this.sync(this.isNew() ? 'create' : 'update', options, function (err, response) {
ed59119d8c00addb07c7ee6c8aefcd1d9cb876f1Tripp return this;
ed59119d8c00addb07c7ee6c8aefcd1d9cb876f1Tripp Sets the value of a single attribute. If model validation fails, the
ed59119d8c00addb07c7ee6c8aefcd1d9cb876f1Tripp attribute will not be set and an `error` event will be fired.
ed59119d8c00addb07c7ee6c8aefcd1d9cb876f1Tripp Use `setAttrs()` to set multiple attributes at once.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp model.set('foo', 'bar');
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @method set
66ca16dd76367c074fe4df1dcf7b555489a9bf85Tripp @param {String} name Attribute name or object property path.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @param {any} value Value to set.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @param {Object} [options] Data to be mixed into the event facade of the
828c58761d90445b8b9d20a82d85dc1479317f71Tripp `change` event(s) for these attributes.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @param {Boolean} [options.silent=false] If `true`, no `change` event will
ed59119d8c00addb07c7ee6c8aefcd1d9cb876f1Tripp Sets the values of multiple attributes at once. If model validation fails,
828c58761d90445b8b9d20a82d85dc1479317f71Tripp the attributes will not be set and an `error` event will be fired.
6a3585e2672045e8e28e6a45f279f80aef446959Tripp model.setAttrs({
828c58761d90445b8b9d20a82d85dc1479317f71Tripp foo: 'bar',
828c58761d90445b8b9d20a82d85dc1479317f71Tripp baz: 'quux'
ed59119d8c00addb07c7ee6c8aefcd1d9cb876f1Tripp @method setAttrs
ed59119d8c00addb07c7ee6c8aefcd1d9cb876f1Tripp @param {Object} attributes Hash of attribute names and values to set.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @param {Object} [options] Data to be mixed into the event facade of the
ed59119d8c00addb07c7ee6c8aefcd1d9cb876f1Tripp `change` event(s) for these attributes.
ed59119d8c00addb07c7ee6c8aefcd1d9cb876f1Tripp @param {Boolean} [options.silent=false] If `true`, no `change` event will
ed59119d8c00addb07c7ee6c8aefcd1d9cb876f1Tripp return this;
ed59119d8c00addb07c7ee6c8aefcd1d9cb876f1Tripp // When a custom id attribute is in use, always keep the default
ed59119d8c00addb07c7ee6c8aefcd1d9cb876f1Tripp // `id` attribute in sync.
66ca16dd76367c074fe4df1dcf7b555489a9bf85Tripp if (!options.silent && !Y.Object.isEmpty(transaction)) {
9cc2c5945426b2b79c0a258026d750be74795924Tripp // Lazy publish for the change event.
9cc2c5945426b2b79c0a258026d750be74795924Tripp return this;
ed59119d8c00addb07c7ee6c8aefcd1d9cb876f1Tripp Override this method to provide a custom persistence implementation for this
ed59119d8c00addb07c7ee6c8aefcd1d9cb876f1Tripp model. The default just calls the callback without actually doing anything.
ed59119d8c00addb07c7ee6c8aefcd1d9cb876f1Tripp This method is called internally by `load()`, `save()`, and `destroy()`.
ed59119d8c00addb07c7ee6c8aefcd1d9cb876f1Tripp @method sync
ed59119d8c00addb07c7ee6c8aefcd1d9cb876f1Tripp @param {String} action Sync action to perform. May be one of the following:
ed59119d8c00addb07c7ee6c8aefcd1d9cb876f1Tripp - `create`: Store a newly-created model for the first time.
ed59119d8c00addb07c7ee6c8aefcd1d9cb876f1Tripp - `delete`: Delete an existing model.
ed59119d8c00addb07c7ee6c8aefcd1d9cb876f1Tripp - 'read' : Load an existing model.
ed59119d8c00addb07c7ee6c8aefcd1d9cb876f1Tripp - `update`: Update an existing model.
ed59119d8c00addb07c7ee6c8aefcd1d9cb876f1Tripp @param {Object} [options] Sync options. It's up to the custom sync
ed59119d8c00addb07c7ee6c8aefcd1d9cb876f1Tripp implementation to determine what options it supports or requires, if any.
ed59119d8c00addb07c7ee6c8aefcd1d9cb876f1Tripp @param {callback} [callback] Called when the sync operation finishes.
ed59119d8c00addb07c7ee6c8aefcd1d9cb876f1Tripp @param {Error|null} callback.err If an error occurred, this parameter will
9cc2c5945426b2b79c0a258026d750be74795924Tripp contain the error. If the sync operation succeeded, _err_ will be
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @param {mixed} [callback.response] The server's response. This value will
828c58761d90445b8b9d20a82d85dc1479317f71Tripp be passed to the `parse()` method, which is expected to parse it and
828c58761d90445b8b9d20a82d85dc1479317f71Tripp return an attribute hash.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp Returns a copy of this model's attributes that can be passed to
828c58761d90445b8b9d20a82d85dc1479317f71Tripp `Y.JSON.stringify()` or used for other nefarious purposes.
66ca16dd76367c074fe4df1dcf7b555489a9bf85Tripp The `clientId` attribute is not included in the returned object.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp If you've specified a custom attribute name in the `idAttribute` property,
828c58761d90445b8b9d20a82d85dc1479317f71Tripp the default `id` attribute will not be included in the returned object.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @method toJSON
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @return {Object} Copy of this model's attributes.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp toJSON: function () {
828c58761d90445b8b9d20a82d85dc1479317f71Tripp Reverts the last change to the model.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp If an _attrNames_ array is provided, then only the named attributes will be
828c58761d90445b8b9d20a82d85dc1479317f71Tripp reverted (and only if they were modified in the previous change). If no
828c58761d90445b8b9d20a82d85dc1479317f71Tripp _attrNames_ array is provided, then all changed attributes will be reverted
828c58761d90445b8b9d20a82d85dc1479317f71Tripp to their previous values.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp Note that only one level of undo is available: from the current state to the
828c58761d90445b8b9d20a82d85dc1479317f71Tripp previous state. If `undo()` is called when no previous state is available,
828c58761d90445b8b9d20a82d85dc1479317f71Tripp it will simply do nothing and return `true`.
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp @method undo
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @param {Array} [attrNames] Array of specific attribute names to rever. If
828c58761d90445b8b9d20a82d85dc1479317f71Tripp not specified, all attributes modified in the last change will be
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp @param {Object} [options] Data to be mixed into the event facade of the
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp change event(s) for these attributes.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @param {Boolean} [options.silent=false] If `true`, no `change` event will
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @return {Boolean} `true` if validation succeeded and the attributes were set
828c58761d90445b8b9d20a82d85dc1479317f71Tripp successfully, `false` otherwise.
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp // Don't generate a double change for custom id attributes.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp return true;
828c58761d90445b8b9d20a82d85dc1479317f71Tripp Override this method to provide custom validation logic for this model.
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp While attribute-specific validators can be used to validate individual
828c58761d90445b8b9d20a82d85dc1479317f71Tripp attributes, this method gives you a hook to validate a hash of attributes
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp when multiple attributes are changed at once. This method is called
828c58761d90445b8b9d20a82d85dc1479317f71Tripp automatically before `set`, `setAttrs`, and `save` take action.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp A call to `validate` that doesn't return anything will be treated as a
828c58761d90445b8b9d20a82d85dc1479317f71Tripp success. If the `validate` method returns a value, it will be treated as a
828c58761d90445b8b9d20a82d85dc1479317f71Tripp failure, and the returned value (which may be a string or an object
828c58761d90445b8b9d20a82d85dc1479317f71Tripp containing information about the failure) will be passed along to the
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp `error` event.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @method validate
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp @param {Object} attributes Attribute hash containing changed attributes.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @return {mixed} Any return value other than `undefined` or `null` will be
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp treated as a validation failure.
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp // -- Protected Methods ----------------------------------------------------
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp Duckpunches the `_getAttrInitVal` method provided by `Y.Attribute` to avoid
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp resetting the value of lazily added id and custom id attributes when a
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp custom id attribute is set at initialization time.
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp @method _getAttrInitVal
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp @param {String} attr The name of the attribute.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @param {Object} cfg The attribute configuration object.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @param {Object} initValues The object with simple and complex attribute
828c58761d90445b8b9d20a82d85dc1479317f71Tripp name/value pairs returned from `_normAttrVals`.
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp @return {mixed} The initial value of the attribute.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp var initVal = Model.superclass._getAttrInitVal.apply(this, arguments),
828c58761d90445b8b9d20a82d85dc1479317f71Tripp return initValues.simple[idAttribute] || initValues.simple.id;
828c58761d90445b8b9d20a82d85dc1479317f71Tripp Calls the public, overridable `validate()` method and fires an `error` event
828c58761d90445b8b9d20a82d85dc1479317f71Tripp if validation fails.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @method _validate
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @param {Object} attributes Attribute hash.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @return {Boolean} `true` if validation succeeded, `false` otherwise.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp // Validation failed. Fire an error.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp return false;
828c58761d90445b8b9d20a82d85dc1479317f71Tripp return true;
828c58761d90445b8b9d20a82d85dc1479317f71Tripp // -- Protected Event Handlers ---------------------------------------------
828c58761d90445b8b9d20a82d85dc1479317f71Tripp Duckpunches the `_defAttrChangeFn()` provided by `Y.Attribute` so we can
828c58761d90445b8b9d20a82d85dc1479317f71Tripp have a single global notification when a change event occurs.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @method _defAttrChangeFn
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @param {EventFacade} e
828c58761d90445b8b9d20a82d85dc1479317f71Tripp _defAttrChangeFn: function (e) {
828c58761d90445b8b9d20a82d85dc1479317f71Tripp if (!this._setAttrVal(e.attrName, e.subAttrName, e.prevVal, e.newVal)) {
828c58761d90445b8b9d20a82d85dc1479317f71Tripp Y.log('State not updated and stopImmediatePropagation called for attribute: ' + e.attrName + ' , value:' + e.newVal, 'warn', 'attribute');
828c58761d90445b8b9d20a82d85dc1479317f71Tripp // Prevent "after" listeners from being invoked since nothing changed.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp A client-only identifier for this model.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp Like the `id` attribute, `clientId` may be used to retrieve model
828c58761d90445b8b9d20a82d85dc1479317f71Tripp instances from lists. Unlike the `id` attribute, `clientId` is
828c58761d90445b8b9d20a82d85dc1479317f71Tripp automatically generated, and is only intended to be used on the client
828c58761d90445b8b9d20a82d85dc1479317f71Tripp during the current pageview.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @attribute clientId
828c58761d90445b8b9d20a82d85dc1479317f71Tripp @type String
0fdefaa9ca017edfb76b736c825b34186f33045aTripp A unique identifier for this model. Among other things, this id may be
0fdefaa9ca017edfb76b736c825b34186f33045aTripp used to retrieve model instances from lists, so it should be unique.
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp If the id is empty, this model instance is assumed to represent a new
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp item that hasn't yet been saved.
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp If you would prefer to use a custom attribute as this model's id instead
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp of using the `id` attribute (for example, maybe you'd rather use `_id`
a89ad754cce3cfc8aee71760e10217b54020360dTripp or `uid` as the primary id), you may set the `idAttribute` property to
a89ad754cce3cfc8aee71760e10217b54020360dTripp the name of your custom id attribute. The `id` attribute will then
6a3585e2672045e8e28e6a45f279f80aef446959Tripp act as an alias for your custom attribute.
a89ad754cce3cfc8aee71760e10217b54020360dTripp @attribute id
6a3585e2672045e8e28e6a45f279f80aef446959Tripp @type String|Number|null
6a3585e2672045e8e28e6a45f279f80aef446959Tripp @default `null`