#

API Docs for: 3.10.3
Show: Inherited Protected Private Deprecated

# File: cache/js/cache-offline.js

    /**
     * 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;