jquery.ajax.cache.js 4.38 KB
// github.com/paulirish/jquery-ajax-localstorage-cache
// dependent on Modernizr's localStorage test
var storage,
    fail,
    uid;
try {
    uid = new Date;
    (storage = window.localStorage).setItem(uid, uid);
    fail = storage.getItem(uid) != uid;
    storage.removeItem(uid);
    fail && (storage = false);
} catch(e) {}

$.ajaxPrefilter(function (options, originalOptions, jqXHR) {

    if (!storage && options.localCache) {
        window.localStorage = new customStorage();
    }

    // Cache it ?
    if (!options.localCache) return;

    // do some cleanup first
    cleanOldStorage();

    var lifetl = options.cacheTTL || 1;

    var cacheKey = options.cacheKey ||
        options.url.replace(/jQuery.*/, '') + options.type + (options.data || '');

    if(options.url.match('/delete/i'))

    // isCacheValid is a function to validate cache
    if (options.isCacheValid && !options.isCacheValid()) {
        window.localStorage.removeItem(cacheKey);
    }
    // if there's a TTL that's expired, flush this item
    var ttl = window.localStorage.getItem(cacheKey + 'cachettl');
    if (ttl && ttl < +new Date()) {

        window.localStorage.removeItem(cacheKey);
        window.localStorage.removeItem(cacheKey + 'cachettl');
        ttl = 'expired';
    }

    var value = window.localStorage.getItem(cacheKey);
    if (value) {
        //In the cache? So get it, apply success callback & abort the XHR request
        // parse back to JSON if we can.
        if (options.dataType.indexOf('json') === 0) value = JSON.parse(value);
        options.success(value);
        // Abort is broken on JQ 1.5 :(
        jqXHR.abort();
    } else {

        //If it not in the cache, we change the success callback, just put data on localstorage and after that apply the initial callback
        if (options.success) {
            options.realsuccess = options.success;
        }
        options.success = function (data) {
            var strdata = data;
            if (this.dataType.indexOf('json') === 0) strdata = JSON.stringify(data);
            window.localStorage.setItem(cacheKey, strdata);
            if (options.realsuccess) options.realsuccess(data);
        };

        // store timestamp
        if (!ttl || ttl === 'expired') {

            lifespan = options.cacheTTLType || 's';

            switch (lifespan)
            {
                case 'm':
                    lifetl *= 60; // minutes
                    break;
                case 'h':
                    lifetl *= 3600; // hours
                    break;
            }
            window.localStorage.setItem(cacheKey + 'cachettl', +new Date() + 1000 * lifetl);
        }
    }
});
function cleanOldStorage(){
    if(window.localStorage.toString()=='[object Storage]')
    {
        for(i=window.localStorage.length-1; i >=0; i--)
        {
            key = window.localStorage.key(i);
            if(key && key.match(/cachettl/i)){
                value = window.localStorage.getItem(key);
                if(value < +new Date())
                {
                    window.localStorage.removeItem(key);    console.log(key + '  removed');
                    window.localStorage.removeItem(key.replace('cachettl',''));   console.log(key + 'cachettl  removed');
                }
            }
        }
    }
    else if(window.localStorage.items) {
        for(var key in window.localStorage.items){
            if(key && key.match(/cachettl/i)){
                value = window.localStorage.items[key];
                if(value < +new Date())
                {
                    window.localStorage.removeItem(key);     console.log(key + '  removed');
                    window.localStorage.removeItem(key.replace('cachettl',''));
                }
            }
        }
    }
}

function customStorage() {}

customStorage.prototype.items = Object();

customStorage.prototype.setItem = function (key, response) {
    this.items[key] = Object();
    this.items[key].response = response;
    return true;
}
customStorage.prototype.removeItem = function (key)
{
    if(this.items[key])
    {
        this.items[key] = null;
    }
}

customStorage.prototype.getItem = function (key) {

    // if cache does not exist
    if (this.items[key] == null)
        return false;

    // everything is passed - lets return the response
    return this.items[key].response;
}

customStorage.prototype.clear = function () {
    // flush all cache
    this.items = Object();
    return true;
}