- /**
- * Provides a Cache subclass which uses HTML5 `localStorage` for persistence.
- *
- * @module cache
- * @submodule cache-offline
- */
-
- /**
- * Extends Cache utility with offline functionality.
- * @class CacheOffline
- * @extends Cache
- * @constructor
- */
- function CacheOffline() {
- CacheOffline.superclass.constructor.apply(this, arguments);
- }
-
- var localStorage = null,
- JSON = Y.JSON;
-
- // Bug 2529572
- try {
- localStorage = Y.config.win.localStorage;
- }
- catch(e) {
- Y.log("Could not access localStorage.", "warn", "cache");
- }
-
- /////////////////////////////////////////////////////////////////////////////
- //
- // CacheOffline events
- //
- /////////////////////////////////////////////////////////////////////////////
-
- /**
- * @event error
- * @description Fired when an entry could not be added, most likely due to
- * exceeded browser quota.
- * <dl>
- * <dt>error (Object)</dt> <dd>The error object.</dd>
- * </dl>
- */
-
- /////////////////////////////////////////////////////////////////////////////
- //
- // CacheOffline static
- //
- /////////////////////////////////////////////////////////////////////////////
- Y.mix(CacheOffline, {
- /**
- * Class name.
- *
- * @property NAME
- * @type String
- * @static
- * @final
- * @value "cacheOffline"
- */
- NAME: "cacheOffline",
-
- ATTRS: {
- /////////////////////////////////////////////////////////////////////////////
- //
- // CacheOffline Attributes
- //
- /////////////////////////////////////////////////////////////////////////////
-
- /**
- * @attribute sandbox
- * @description A string that must be passed in via the constructor.
- * This identifier is used to sandbox one cache instance's entries
- * from another. Calling the cache instance's flush and length methods
- * or get("entries") will apply to only these sandboxed entries.
- * @type String
- * @default "default"
- * @initOnly
- */
- sandbox: {
- value: "default",
- writeOnce: "initOnly"
- },
-
- /**
- * @attribute expires
- * @description Absolute Date when data expires or
- * relative number of milliseconds. Zero disables expiration.
- * @type Date | Number
- * @default 86400000 (one day)
- */
- expires: {
- value: 86400000
- },
-
- /**
- * @attribute max
- * @description Disabled.
- * @readOnly
- * @default null
- */
- max: {
- value: null,
- readOnly: true
- },
-
- /**
- * @attribute uniqueKeys
- * @description Always true for CacheOffline.
- * @readOnly
- * @default true
- */
- uniqueKeys: {
- value: true,
- readOnly: true,
- setter: function() {
- return true;
- }
- }
- },
-
- /**
- * Removes all items from all sandboxes. Useful if localStorage has
- * exceeded quota. Only supported on browsers that implement HTML 5
- * localStorage.
- *
- * @method flushAll
- * @static
- */
- flushAll: function() {
- var store = localStorage, key;
- if(store) {
- if(store.clear) {
- store.clear();
- }
- // FF2.x and FF3.0.x
- else {
- for (key in store) {
- if (store.hasOwnProperty(key)) {
- store.removeItem(key);
- delete store[key];
- }
- }
- }
- Y.log("All sandboxes of OfflineCache flushed", "info", "cache");
- }
- else {
- Y.log("Could not flush all OfflineCache sandboxes.", "warn", "cache");
- }
- }
- });
-
- Y.extend(CacheOffline, Y.Cache, localStorage ? {
- /////////////////////////////////////////////////////////////////////////////
- //
- // Offline is supported
- //
- /////////////////////////////////////////////////////////////////////////////
-
- /////////////////////////////////////////////////////////////////////////////
- //
- // CacheOffline protected methods
- //
- /////////////////////////////////////////////////////////////////////////////
- /**
- * Always return null.
- *
- * @method _setMax
- * @protected
- */
- _setMax: function(value) {
- return null;
- },
-
- /**
- * Gets size.
- *
- * @method _getSize
- * @protected
- */
- _getSize: function() {
- var count = 0,
- i=0,
- l=localStorage.length;
- for(; i<l; ++i) {
- // Match sandbox id
- if(localStorage.key(i).indexOf(this.get("sandbox")) === 0) {
- count++;
- }
- }
- return count;
- },
-
- /**
- * Gets all entries.
- *
- * @method _getEntries
- * @protected
- */
- _getEntries: function() {
- var entries = [],
- i=0,
- l=localStorage.length,
- sandbox = this.get("sandbox");
- for(; i<l; ++i) {
- // Match sandbox id
- if(localStorage.key(i).indexOf(sandbox) === 0) {
- entries[i] = JSON.parse(localStorage.key(i).substring(sandbox.length));
- }
- }
- return entries;
- },
-
- /**
- * Adds entry to cache.
- *
- * @method _defAddFn
- * @param e {Event.Facade} Event Facade with the following properties:
- * <dl>
- * <dt>entry (Object)</dt> <dd>The cached entry.</dd>
- * </dl>
- * @protected
- */
- _defAddFn: function(e) {
- var entry = e.entry,
- request = entry.request,
- cached = entry.cached,
- expires = entry.expires;
-
- // Convert Dates to msecs on the way into localStorage
- entry.cached = cached.getTime();
- entry.expires = expires ? expires.getTime() : expires;
-
- try {
- localStorage.setItem(this.get("sandbox")+JSON.stringify({"request":request}), JSON.stringify(entry));
- Y.log("Cached offline entry: " + Y.dump(entry), "info", "cache");
- }
- catch(error) {
- this.fire("error", {error:error});
- Y.log("Could not cache offline entry: " + Y.dump(entry) +
- " due to error: " + Y.dump(error), "warn", "cache");
- }
- },
-
- /**
- * Flushes cache.
- *
- * @method _defFlushFn
- * @param e {Event.Facade} Event Facade object.
- * @protected
- */
- _defFlushFn: function(e) {
- var key,
- i=localStorage.length-1;
- for(; i>-1; --i) {
- // Match sandbox id
- key = localStorage.key(i);
- if(key.indexOf(this.get("sandbox")) === 0) {
- localStorage.removeItem(key);
- }
- }
- },
-
- /////////////////////////////////////////////////////////////////////////////
- //
- // CacheOffline public methods
- //
- /////////////////////////////////////////////////////////////////////////////
- /**
- * Adds a new entry to the cache of the format
- * {request:request, response:response, cached:cached, expires: expires}.
- *
- * @method add
- * @param request {Object} Request value must be a String or JSON.
- * @param response {Object} Response value must be a String or JSON.
- */
-
- /**
- * Retrieves cached object for given request, if available.
- * Returns null if there is no cache match.
- *
- * @method retrieve
- * @param request {Object} Request object.
- * @return {Object} Cached object with the properties request, response,
- * and expires, or null.
- */
- retrieve: function(request) {
- this.fire("request", {request: request});
-
- var entry, expires, sandboxedrequest;
-
- try {
- sandboxedrequest = this.get("sandbox")+JSON.stringify({"request":request});
- try {
- entry = JSON.parse(localStorage.getItem(sandboxedrequest));
- }
- catch(e) {
- }
- }
- catch(e2) {
- }
-
- if(entry) {
- // Convert msecs to Dates on the way out of localStorage
- entry.cached = new Date(entry.cached);
- expires = entry.expires;
- expires = !expires ? null : new Date(expires);
- entry.expires = expires;
-
- if(this._isMatch(request, entry)) {
- this.fire("retrieve", {entry: entry});
- Y.log("Retrieved offlinecached response: " + Y.dump(entry) +
- " for request: " + Y.dump(request), "info", "cache");
- return entry;
- }
- }
- return null;
- }
- } :
- /////////////////////////////////////////////////////////////////////////////
- //
- // Offline is not supported
- //
- /////////////////////////////////////////////////////////////////////////////
- {
- /**
- * Always return null.
- *
- * @method _setMax
- * @protected
- */
- _setMax: function(value) {
- return null;
- }
- });
-
-
- Y.CacheOffline = CacheOffline;
-
-