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