3
Copyright 2012 Yahoo! Inc. All rights reserved.
4
Licensed under the BSD License.
5
http://yuilibrary.com/license/
7
YUI.add('cache-offline', function(Y) {
10
* Provides a Cache subclass which uses HTML5 `localStorage` for persistence.
13
* @submodule cache-offline
17
* Extends Cache utility with offline functionality.
22
function CacheOffline() {
23
CacheOffline.superclass.constructor.apply(this, arguments);
26
var localStorage = null,
31
localStorage = Y.config.win.localStorage;
34
Y.log("Could not access localStorage.", "warn", "cache");
37
/////////////////////////////////////////////////////////////////////////////
39
// CacheOffline events
41
/////////////////////////////////////////////////////////////////////////////
45
* @description Fired when an entry could not be added, most likely due to
46
* exceeded browser quota.
48
* <dt>error (Object)</dt> <dd>The error object.</dd>
52
/////////////////////////////////////////////////////////////////////////////
54
// CacheOffline static
56
/////////////////////////////////////////////////////////////////////////////
65
* @value "cacheOffline"
70
/////////////////////////////////////////////////////////////////////////////
72
// CacheOffline Attributes
74
/////////////////////////////////////////////////////////////////////////////
78
* @description A string that must be passed in via the constructor.
79
* This identifier is used to sandbox one cache instance's entries
80
* from another. Calling the cache instance's flush and length methods
81
* or get("entries") will apply to only these sandboxed entries.
93
* @description Absolute Date when data expires or
94
* relative number of milliseconds. Zero disables expiration.
96
* @default 86400000 (one day)
104
* @description Disabled.
114
* @attribute uniqueKeys
115
* @description Always true for CacheOffline.
129
* Removes all items from all sandboxes. Useful if localStorage has
130
* exceeded quota. Only supported on browsers that implement HTML 5
136
flushAll: function() {
137
var store = localStorage, key;
145
if (store.hasOwnProperty(key)) {
146
store.removeItem(key);
151
Y.log("All sandboxes of OfflineCache flushed", "info", "cache");
154
Y.log("Could not flush all OfflineCache sandboxes.", "warn", "cache");
159
Y.extend(CacheOffline, Y.Cache, localStorage ? {
160
/////////////////////////////////////////////////////////////////////////////
162
// Offline is supported
164
/////////////////////////////////////////////////////////////////////////////
166
/////////////////////////////////////////////////////////////////////////////
168
// CacheOffline protected methods
170
/////////////////////////////////////////////////////////////////////////////
172
* Always return null.
177
_setMax: function(value) {
187
_getSize: function() {
190
l=localStorage.length;
193
if(localStorage.key(i).indexOf(this.get("sandbox")) === 0) {
203
* @method _getEntries
206
_getEntries: function() {
209
l=localStorage.length,
210
sandbox = this.get("sandbox");
213
if(localStorage.key(i).indexOf(sandbox) === 0) {
214
entries[i] = JSON.parse(localStorage.key(i).substring(sandbox.length));
221
* Adds entry to cache.
224
* @param e {Event.Facade} Event Facade with the following properties:
226
* <dt>entry (Object)</dt> <dd>The cached entry.</dd>
230
_defAddFn: function(e) {
232
request = entry.request,
233
cached = entry.cached,
234
expires = entry.expires;
236
// Convert Dates to msecs on the way into localStorage
237
entry.cached = cached.getTime();
238
entry.expires = expires ? expires.getTime() : expires;
241
localStorage.setItem(this.get("sandbox")+JSON.stringify({"request":request}), JSON.stringify(entry));
242
Y.log("Cached offline entry: " + Y.dump(entry), "info", "cache");
245
this.fire("error", {error:error});
246
Y.log("Could not cache offline entry: " + Y.dump(entry) +
247
" due to error: " + Y.dump(error), "warn", "cache");
254
* @method _defFlushFn
255
* @param e {Event.Facade} Event Facade object.
258
_defFlushFn: function(e) {
260
i=localStorage.length-1;
263
key = localStorage.key(i);
264
if(key.indexOf(this.get("sandbox")) === 0) {
265
localStorage.removeItem(key);
270
/////////////////////////////////////////////////////////////////////////////
272
// CacheOffline public methods
274
/////////////////////////////////////////////////////////////////////////////
276
* Adds a new entry to the cache of the format
277
* {request:request, response:response, cached:cached, expires: expires}.
280
* @param request {Object} Request value must be a String or JSON.
281
* @param response {Object} Response value must be a String or JSON.
285
* Retrieves cached object for given request, if available.
286
* Returns null if there is no cache match.
289
* @param request {Object} Request object.
290
* @return {Object} Cached object with the properties request, response,
291
* and expires, or null.
293
retrieve: function(request) {
294
this.fire("request", {request: request});
296
var entry, expires, sandboxedrequest;
299
sandboxedrequest = this.get("sandbox")+JSON.stringify({"request":request});
301
entry = JSON.parse(localStorage.getItem(sandboxedrequest));
310
// Convert msecs to Dates on the way out of localStorage
311
entry.cached = new Date(entry.cached);
312
expires = entry.expires;
313
expires = !expires ? null : new Date(expires);
314
entry.expires = expires;
316
if(this._isMatch(request, entry)) {
317
this.fire("retrieve", {entry: entry});
318
Y.log("Retrieved offlinecached response: " + Y.dump(entry) +
319
" for request: " + Y.dump(request), "info", "cache");
326
/////////////////////////////////////////////////////////////////////////////
328
// Offline is not supported
330
/////////////////////////////////////////////////////////////////////////////
333
* Always return null.
338
_setMax: function(value) {
344
Y.CacheOffline = CacheOffline;
347
}, '3.5.1' ,{requires:['cache-base', 'json']});