src/cm/media/js/lib/yui/yui3-3.15.0/build/model-sync-local/model-sync-local-debug.js
changeset 602 e16a97fb364a
equal deleted inserted replaced
601:d334a616c023 602:e16a97fb364a
       
     1 YUI.add('model-sync-local', function (Y, NAME) {
       
     2 
       
     3 /*
       
     4 An extension which provides a sync implementation through locally stored
       
     5 key value pairs, either through the HTML localStorage API or falling back
       
     6 onto an in-memory cache, that can be mixed into a Model or ModelList subclass.
       
     7 
       
     8 @module app
       
     9 @submodule model-sync-local
       
    10 @since 3.13.0
       
    11 **/
       
    12 
       
    13 /**
       
    14 An extension which provides a sync implementation through locally stored
       
    15 key value pairs, either through the HTML localStorage API or falling back
       
    16 onto an in-memory cache, that can be mixed into a Model or ModelList subclass.
       
    17 
       
    18 A group of Models/ModelLists is serialized in localStorage by either its
       
    19 class name, or a specified 'root' that is provided.
       
    20 
       
    21     var User = Y.Base.create('user', Y.Model, [Y.ModelSync.Local], {
       
    22         root: 'user'
       
    23     });
       
    24 
       
    25     var Users = Y.Base.create('users', Y.ModelList, [Y.ModelSync.Local], {
       
    26         model: User,
       
    27     });
       
    28 
       
    29 @class ModelSync.Local
       
    30 @extensionfor Model
       
    31 @extensionfor ModelList
       
    32 @since 3.13.0
       
    33 **/
       
    34 function LocalSync() {}
       
    35 
       
    36 /**
       
    37 Properties that shouldn't be turned into ad-hoc attributes when passed to a
       
    38 Model or ModelList constructor.
       
    39 
       
    40 @property _NON_ATTRS_CFG
       
    41 @type Array
       
    42 @default ['root']
       
    43 @static
       
    44 @protected
       
    45 @since 3.13.0
       
    46 **/
       
    47 LocalSync._NON_ATTRS_CFG = ['root'];
       
    48 
       
    49 /**
       
    50 Feature testing for `localStorage` availability.
       
    51 Will return falsey for browsers with `localStorage`, but that don't
       
    52 actually work, such as iOS Safari in private browsing mode.
       
    53 
       
    54 @property _hasLocalStorage
       
    55 @type Boolean
       
    56 @private
       
    57 **/
       
    58 LocalSync._hasLocalStorage = (function () {
       
    59     var LS   = Y.config.win.localStorage,
       
    60         test = Y.guid();
       
    61 
       
    62     try {
       
    63         LS.setItem(test, test);
       
    64         LS.removeItem(test);
       
    65         return true;
       
    66     } catch (e) {
       
    67         return false;
       
    68     }
       
    69 })(),
       
    70 
       
    71 /**
       
    72 Object of key/value pairs to fall back on when localStorage is not available.
       
    73 
       
    74 @property _data
       
    75 @type Object
       
    76 @private
       
    77 **/
       
    78 
       
    79 LocalSync._data = LocalSync._data || {};
       
    80 
       
    81 /**
       
    82 Cache to quickly access a specific object with a given ID.
       
    83 
       
    84 @property _store
       
    85 @type Array
       
    86 @private
       
    87 **/
       
    88 
       
    89 LocalSync._store = LocalSync._store || {};
       
    90 
       
    91 LocalSync.prototype = {
       
    92 
       
    93     // -- Public Methods -------------------------------------------------------
       
    94     
       
    95     /**
       
    96     Root used as the key inside of localStorage and/or the in-memory store.
       
    97     
       
    98     @property root
       
    99     @type String
       
   100     @default ""
       
   101     @since 3.13.0
       
   102     **/
       
   103     root: '',
       
   104 
       
   105     /**
       
   106     Shortcut for access to localStorage.
       
   107     
       
   108     @property storage
       
   109     @type Storage
       
   110     @default null
       
   111     @since 3.13.0
       
   112     **/
       
   113     storage: null,
       
   114 
       
   115     // -- Lifecycle Methods -----------------------------------------------------
       
   116     initializer: function (config) {
       
   117         var store, data;
       
   118 
       
   119         config || (config = {});
       
   120 
       
   121         if ('root' in config) {
       
   122             this.root = config.root || '';
       
   123         }
       
   124 
       
   125         // This is checking to see if the sync layer is being applied to
       
   126         // a ModelList, and if so, is looking for a `root` property on its
       
   127         // Model's prototype instead.
       
   128         if (!this.root && this.model && this.model.prototype.root) {
       
   129             this.root = this.model.prototype.root;
       
   130         }
       
   131 
       
   132         if (LocalSync._hasLocalStorage) {
       
   133             this.storage = Y.config.win.localStorage;
       
   134             store = this.storage.getItem(this.root);
       
   135         } else {
       
   136             Y.log("Could not access localStorage.", "warn");
       
   137         }
       
   138 
       
   139         // Pull in existing data from localStorage, if possible.
       
   140         // Otherwise, see if there's existing data on the local cache.
       
   141         if (store) {
       
   142             LocalSync._store[this.root] = store.split('|') || [];
       
   143 
       
   144             Y.Array.each(LocalSync._store[this.root], function (id) {
       
   145                 LocalSync._data[id] = Y.JSON.parse(this.storage.getItem(id));
       
   146             }, this);
       
   147         } else {
       
   148             LocalSync._store[this.root] || (LocalSync._store[this.root] = []);
       
   149         }
       
   150     },
       
   151     
       
   152     // -- Public Methods -----------------------------------------------------------
       
   153     
       
   154     /**
       
   155     Creates a synchronization layer with the localStorage API, if available.
       
   156     Otherwise, falls back to a in-memory data store.
       
   157 
       
   158     This method is called internally by load(), save(), and destroy().
       
   159 
       
   160     @method sync
       
   161     @param {String} action Sync action to perform. May be one of the following:
       
   162 
       
   163       * **create**: Store a newly-created model for the first time.
       
   164       * **read**  : Load an existing model.
       
   165       * **update**: Update an existing model.
       
   166       * **delete**: Delete an existing model.
       
   167 
       
   168     @param {Object} [options] Sync options
       
   169     @param {Function} [callback] Called when the sync operation finishes.
       
   170       @param {Error|null} callback.err If an error occurred, this parameter will
       
   171         contain the error. If the sync operation succeeded, _err_ will be
       
   172         falsey.
       
   173       @param {Any} [callback.response] The response from our sync. This value will
       
   174         be passed to the parse() method, which is expected to parse it and
       
   175         return an attribute hash.
       
   176     **/
       
   177     sync: function (action, options, callback) {
       
   178         options || (options = {});
       
   179         var response, errorInfo;
       
   180 
       
   181         try {
       
   182             switch (action) {
       
   183                 case 'read':
       
   184                     if (this._isYUIModelList) {
       
   185                         response = this._index(options);
       
   186                     } else {
       
   187                         response = this._show(options);
       
   188                     }
       
   189                     break;
       
   190                 case 'create':
       
   191                     response = this._create(options);
       
   192                     break;
       
   193                 case 'update':
       
   194                     response = this._update(options);
       
   195                     break;
       
   196                 case 'delete':
       
   197                     response = this._destroy(options);
       
   198                     break;
       
   199             }
       
   200         } catch (error) {
       
   201             errorInfo = error.message;
       
   202         }
       
   203 
       
   204         if (response) {
       
   205             callback(null, response);
       
   206         } else if (errorInfo) {
       
   207             callback(errorInfo);
       
   208         } else {
       
   209             callback("Data not found in LocalStorage");
       
   210         }
       
   211     },
       
   212 
       
   213     /**
       
   214     Generate a random GUID for our Models. This can be overriden if you have
       
   215     another method of generating different IDs.
       
   216     
       
   217     @method generateID
       
   218     @protected
       
   219     @param {String} pre Optional GUID prefix
       
   220     **/
       
   221     generateID: function (pre) {
       
   222         return Y.guid(pre + '_');
       
   223     },
       
   224 
       
   225     // -- Protected Methods ----------------------------------------------------
       
   226 
       
   227     /**
       
   228     Sync method correlating to the "read" operation, for a Model List
       
   229     
       
   230     @method _index
       
   231     @return {Object[]} Array of objects found for that root key
       
   232     @protected
       
   233     @since 3.13.0
       
   234     **/
       
   235     _index: function () {
       
   236         var store = LocalSync._store[this.root],
       
   237             data  = Y.Array.map(store, function (id) {
       
   238                 return LocalSync._data[id];
       
   239             });
       
   240 
       
   241         return data;
       
   242     },
       
   243 
       
   244     /**
       
   245     Sync method correlating to the "read" operation, for a Model
       
   246     
       
   247     @method _show
       
   248     @return {Object} Object found for that root key and model ID
       
   249     @protected
       
   250     @since 3.13.0
       
   251     **/
       
   252     _show: function () {
       
   253         return LocalSync._data[this.get('id')] || null;
       
   254     },
       
   255     
       
   256     /**
       
   257     Sync method correlating to the "create" operation
       
   258     
       
   259     @method _show
       
   260     @return {Object} The new object created.
       
   261     @protected
       
   262     @since 3.13.0
       
   263     **/
       
   264     _create: function () {
       
   265         var hash  = this.toJSON();
       
   266 
       
   267         hash.id = this.generateID(this.root);
       
   268 
       
   269         LocalSync._data[hash.id] = hash;
       
   270         if (this.storage) {
       
   271             this.storage.setItem(hash.id, hash);
       
   272         }
       
   273 
       
   274         LocalSync._store[this.root].push(hash.id);
       
   275 
       
   276         this._save();
       
   277         return hash;
       
   278     },
       
   279 
       
   280     /**
       
   281     Sync method correlating to the "update" operation
       
   282 
       
   283     @method _update
       
   284     @return {Object} The updated object.
       
   285     @protected
       
   286     @since 3.13.0
       
   287     **/
       
   288     _update: function () {
       
   289         var hash = this.toJSON(),
       
   290             id = this.get('id');
       
   291 
       
   292         LocalSync._data[id] = hash;
       
   293         
       
   294         if (this.storage) {
       
   295             this.storage.setItem(id, hash);
       
   296         }
       
   297 
       
   298         if (Y.Array.indexOf(LocalSync._store[this.root], id) === -1) {
       
   299             LocalSync._store[this.root].push(id);
       
   300         }
       
   301 
       
   302         this._save();
       
   303 
       
   304         return hash;
       
   305     },
       
   306 
       
   307     /**
       
   308     Sync method correlating to the "delete" operation.  Deletes the data
       
   309     from the in-memory object, and saves into localStorage if available.
       
   310     
       
   311     @method _destroy
       
   312     @protected
       
   313     @since 3.13.0
       
   314     **/
       
   315     _destroy: function () {
       
   316         var id = this.get('id'),
       
   317             storage = this.storage;
       
   318 
       
   319         if (!LocalSync._data[id]) {
       
   320             return;
       
   321         }
       
   322 
       
   323         delete LocalSync._data[id];
       
   324 
       
   325         if (storage) {
       
   326             storage.removeItem(id);
       
   327         }
       
   328 
       
   329         LocalSync._store[this.root] = Y.Array.filter(LocalSync._store[this.root], function (item) {
       
   330             return item.id != id;
       
   331         });
       
   332 
       
   333         this._save();
       
   334         return this.toJSON();
       
   335     },
       
   336     
       
   337     /**
       
   338     Saves the current in-memory store into a localStorage key/value pair
       
   339     if localStorage is available; otherwise, does nothing.
       
   340     
       
   341     @method _save
       
   342     @protected
       
   343     @since 3.13.0
       
   344     **/
       
   345     _save: function () {
       
   346         if (LocalSync._hasLocalStorage && this.storage) {
       
   347             this.storage.setItem(
       
   348                 this.root,
       
   349                 LocalSync._store[this.root].join('|')
       
   350             );
       
   351         }
       
   352     }
       
   353 };
       
   354 
       
   355 // -- Namespace ---------------------------------------------------------------
       
   356 
       
   357 Y.namespace('ModelSync').Local = LocalSync;
       
   358 
       
   359 
       
   360 }, '@VERSION@', {"requires": ["model", "json-stringify"]});