diff -r d334a616c023 -r e16a97fb364a src/cm/media/js/lib/yui/yui3-3.15.0/build/model-sync-local/model-sync-local-debug.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/cm/media/js/lib/yui/yui3-3.15.0/build/model-sync-local/model-sync-local-debug.js Mon Mar 10 15:19:48 2014 +0100 @@ -0,0 +1,360 @@ +YUI.add('model-sync-local', function (Y, NAME) { + +/* +An extension which provides a sync implementation through locally stored +key value pairs, either through the HTML localStorage API or falling back +onto an in-memory cache, that can be mixed into a Model or ModelList subclass. + +@module app +@submodule model-sync-local +@since 3.13.0 +**/ + +/** +An extension which provides a sync implementation through locally stored +key value pairs, either through the HTML localStorage API or falling back +onto an in-memory cache, that can be mixed into a Model or ModelList subclass. + +A group of Models/ModelLists is serialized in localStorage by either its +class name, or a specified 'root' that is provided. + + var User = Y.Base.create('user', Y.Model, [Y.ModelSync.Local], { + root: 'user' + }); + + var Users = Y.Base.create('users', Y.ModelList, [Y.ModelSync.Local], { + model: User, + }); + +@class ModelSync.Local +@extensionfor Model +@extensionfor ModelList +@since 3.13.0 +**/ +function LocalSync() {} + +/** +Properties that shouldn't be turned into ad-hoc attributes when passed to a +Model or ModelList constructor. + +@property _NON_ATTRS_CFG +@type Array +@default ['root'] +@static +@protected +@since 3.13.0 +**/ +LocalSync._NON_ATTRS_CFG = ['root']; + +/** +Feature testing for `localStorage` availability. +Will return falsey for browsers with `localStorage`, but that don't +actually work, such as iOS Safari in private browsing mode. + +@property _hasLocalStorage +@type Boolean +@private +**/ +LocalSync._hasLocalStorage = (function () { + var LS = Y.config.win.localStorage, + test = Y.guid(); + + try { + LS.setItem(test, test); + LS.removeItem(test); + return true; + } catch (e) { + return false; + } +})(), + +/** +Object of key/value pairs to fall back on when localStorage is not available. + +@property _data +@type Object +@private +**/ + +LocalSync._data = LocalSync._data || {}; + +/** +Cache to quickly access a specific object with a given ID. + +@property _store +@type Array +@private +**/ + +LocalSync._store = LocalSync._store || {}; + +LocalSync.prototype = { + + // -- Public Methods ------------------------------------------------------- + + /** + Root used as the key inside of localStorage and/or the in-memory store. + + @property root + @type String + @default "" + @since 3.13.0 + **/ + root: '', + + /** + Shortcut for access to localStorage. + + @property storage + @type Storage + @default null + @since 3.13.0 + **/ + storage: null, + + // -- Lifecycle Methods ----------------------------------------------------- + initializer: function (config) { + var store, data; + + config || (config = {}); + + if ('root' in config) { + this.root = config.root || ''; + } + + // This is checking to see if the sync layer is being applied to + // a ModelList, and if so, is looking for a `root` property on its + // Model's prototype instead. + if (!this.root && this.model && this.model.prototype.root) { + this.root = this.model.prototype.root; + } + + if (LocalSync._hasLocalStorage) { + this.storage = Y.config.win.localStorage; + store = this.storage.getItem(this.root); + } else { + Y.log("Could not access localStorage.", "warn"); + } + + // Pull in existing data from localStorage, if possible. + // Otherwise, see if there's existing data on the local cache. + if (store) { + LocalSync._store[this.root] = store.split('|') || []; + + Y.Array.each(LocalSync._store[this.root], function (id) { + LocalSync._data[id] = Y.JSON.parse(this.storage.getItem(id)); + }, this); + } else { + LocalSync._store[this.root] || (LocalSync._store[this.root] = []); + } + }, + + // -- Public Methods ----------------------------------------------------------- + + /** + Creates a synchronization layer with the localStorage API, if available. + Otherwise, falls back to a in-memory data store. + + This method is called internally by load(), save(), and destroy(). + + @method sync + @param {String} action Sync action to perform. May be one of the following: + + * **create**: Store a newly-created model for the first time. + * **read** : Load an existing model. + * **update**: Update an existing model. + * **delete**: Delete an existing model. + + @param {Object} [options] Sync options + @param {Function} [callback] Called when the sync operation finishes. + @param {Error|null} callback.err If an error occurred, this parameter will + contain the error. If the sync operation succeeded, _err_ will be + falsey. + @param {Any} [callback.response] The response from our sync. This value will + be passed to the parse() method, which is expected to parse it and + return an attribute hash. + **/ + sync: function (action, options, callback) { + options || (options = {}); + var response, errorInfo; + + try { + switch (action) { + case 'read': + if (this._isYUIModelList) { + response = this._index(options); + } else { + response = this._show(options); + } + break; + case 'create': + response = this._create(options); + break; + case 'update': + response = this._update(options); + break; + case 'delete': + response = this._destroy(options); + break; + } + } catch (error) { + errorInfo = error.message; + } + + if (response) { + callback(null, response); + } else if (errorInfo) { + callback(errorInfo); + } else { + callback("Data not found in LocalStorage"); + } + }, + + /** + Generate a random GUID for our Models. This can be overriden if you have + another method of generating different IDs. + + @method generateID + @protected + @param {String} pre Optional GUID prefix + **/ + generateID: function (pre) { + return Y.guid(pre + '_'); + }, + + // -- Protected Methods ---------------------------------------------------- + + /** + Sync method correlating to the "read" operation, for a Model List + + @method _index + @return {Object[]} Array of objects found for that root key + @protected + @since 3.13.0 + **/ + _index: function () { + var store = LocalSync._store[this.root], + data = Y.Array.map(store, function (id) { + return LocalSync._data[id]; + }); + + return data; + }, + + /** + Sync method correlating to the "read" operation, for a Model + + @method _show + @return {Object} Object found for that root key and model ID + @protected + @since 3.13.0 + **/ + _show: function () { + return LocalSync._data[this.get('id')] || null; + }, + + /** + Sync method correlating to the "create" operation + + @method _show + @return {Object} The new object created. + @protected + @since 3.13.0 + **/ + _create: function () { + var hash = this.toJSON(); + + hash.id = this.generateID(this.root); + + LocalSync._data[hash.id] = hash; + if (this.storage) { + this.storage.setItem(hash.id, hash); + } + + LocalSync._store[this.root].push(hash.id); + + this._save(); + return hash; + }, + + /** + Sync method correlating to the "update" operation + + @method _update + @return {Object} The updated object. + @protected + @since 3.13.0 + **/ + _update: function () { + var hash = this.toJSON(), + id = this.get('id'); + + LocalSync._data[id] = hash; + + if (this.storage) { + this.storage.setItem(id, hash); + } + + if (Y.Array.indexOf(LocalSync._store[this.root], id) === -1) { + LocalSync._store[this.root].push(id); + } + + this._save(); + + return hash; + }, + + /** + Sync method correlating to the "delete" operation. Deletes the data + from the in-memory object, and saves into localStorage if available. + + @method _destroy + @protected + @since 3.13.0 + **/ + _destroy: function () { + var id = this.get('id'), + storage = this.storage; + + if (!LocalSync._data[id]) { + return; + } + + delete LocalSync._data[id]; + + if (storage) { + storage.removeItem(id); + } + + LocalSync._store[this.root] = Y.Array.filter(LocalSync._store[this.root], function (item) { + return item.id != id; + }); + + this._save(); + return this.toJSON(); + }, + + /** + Saves the current in-memory store into a localStorage key/value pair + if localStorage is available; otherwise, does nothing. + + @method _save + @protected + @since 3.13.0 + **/ + _save: function () { + if (LocalSync._hasLocalStorage && this.storage) { + this.storage.setItem( + this.root, + LocalSync._store[this.root].join('|') + ); + } + } +}; + +// -- Namespace --------------------------------------------------------------- + +Y.namespace('ModelSync').Local = LocalSync; + + +}, '@VERSION@', {"requires": ["model", "json-stringify"]});