Created
September 2, 2011 22:39
-
-
Save benekastah/1190123 to your computer and use it in GitHub Desktop.
This is the basis for my DomStore repo (https://github.com/benekastah/DomStore)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function () | |
{ | |
var hasProperty = Object.hasOwnProperty, | |
// make sure we have a trim function available | |
trim = String.prototype.trim || function () { return this.replace(/^\s*/, '').replace(/\s*$/, ''); }, | |
// This function divides a string into multiple strings of a certain length. | |
// Some browsers limit an individual cookie to about 4000 bytes of data | |
// This allows us to store all the info we want by splitting an item into multiple cookies | |
divide = function (len) | |
{ | |
var thisLen = this.length; | |
if (thisLen < len) | |
return [this]; | |
var indx = 0; | |
var result = []; | |
while (indx < thisLen) | |
{ | |
result.push(this.substr(indx, len)); | |
indx += len; | |
} | |
return result; | |
}, | |
// This encodes a string to json and then escapes it for safe storage in a cookie. | |
// This function relies on there being JSON support present. | |
encode = function (str, doEscape) | |
{ | |
var val = str; | |
doEscape = doEscape === undefined ? true : doEscape; | |
try | |
{ | |
val = JSON.stringify(val); | |
} catch (e) | |
{ | |
val = val.toString(); | |
} | |
if (doEscape) | |
val = escape(val); | |
return val; | |
}, | |
// encode's companion. Reverses the process. | |
decode = function (str) | |
{ | |
var val = unescape(str); | |
try | |
{ | |
val = JSON.parse(val); | |
} catch (e) { } | |
return val; | |
}, | |
// Gets a config object from the arguments, allowing you to pass in a single object, or a name and a value. | |
getConfig = function (args) | |
{ | |
var config; | |
if (typeof args[0] !== "string") | |
{ | |
config = args[0]; | |
} else | |
{ | |
config = {}; | |
config[args[0]] = args[1]; | |
} | |
return config; | |
}, | |
// Tests for a function | |
isFn = function (item) { return typeof item === "function"; }, | |
// Makes a name out of the arguments. | |
// getName("a", "b", "c") => "a_b_c" | |
getName = function () | |
{ | |
return Array.prototype.join.call(arguments, "_"); | |
}; | |
// This object takes care of all things cookie. | |
var cookie = (function () | |
{ | |
// Iterator that will give you each cookie stored under a particular name. | |
function forEachCookie(name, callback) | |
{ | |
var cookies = document.cookie.split(";"), | |
nameRe = new RegExp("^" + name + "_\\d+$"), | |
cookie, thisName, thisValue; | |
for (var i = 0, len = cookies.length; i < len; i++) | |
{ | |
cookie = cookies[i].split("="); | |
thisName = trim.call(cookie.shift()); | |
if (nameRe.test(thisName)) | |
{ | |
thisValue = unescape(cookie.join("=")); | |
callback(thisName, thisValue); | |
} | |
} | |
} | |
// This formulates cookie data into a string, and then writes it to document.cookie | |
function write(config) | |
{ | |
var name = config.name, | |
value = config.value, | |
expireDate = config.expireDate, | |
domainName = config.domain, | |
pathName = config.path; | |
expireDate = expireDate instanceof Date ? expireDate.toUTCString() : expireDate; | |
var expire = expireDate ? "; expires=" + expireDate : ''; | |
var path = pathName ? "; path=" + escape(pathName) : ''; | |
var domain = domainName ? "; domain=" + escape(domainName) : ''; | |
var ck = '' + name + "=" + value + expire + domain + path; | |
document.cookie = ck; | |
return ck; | |
} | |
// Return our API object | |
return { | |
// This is a setting that can be modified at any time | |
// It is not recommended to have a cookie exceed this length | |
// Any cookie longer than this will be split into multiple cookies seamlessly, so we don't have to worry about the limitation | |
maxLength: 4000 | |
// The config object is a hash of key value pairs. Each key represents a new cookie that will be set. | |
// The prefix will be appended with an underscore to the beginning of each cookie name. | |
// As long as the JSON library is loaded, values can be anything. Otherwise, stick to strings here. | |
, set: function (config, prefix) | |
{ | |
var name, value, writeConfig; | |
for (name in config) | |
{ | |
if (!hasProperty.call(config, name)) continue; | |
this.remove(name); | |
value = config[name]; | |
value = encode(value); | |
value = divide.call(value, this.maxLength - (name.length + 10)); | |
for (var i = 0, len = value.length; i < len; i++) | |
{ | |
writeConfig = {}; | |
writeConfig.name = getName(prefix, name, i); | |
writeConfig.value = value[i]; | |
write(writeConfig); | |
} | |
} | |
} | |
// The values will be JSON decoded automatically. | |
, get: function (name, prefix) | |
{ | |
var value = ""; | |
forEachCookie(getName(prefix, name), function (thisName, thisValue) | |
{ | |
value += thisValue; | |
}); | |
value = trim(value); | |
if (value) | |
value = decode(value); | |
return value === '' ? null : value; | |
} | |
// Deletes cookies associated with name | |
, remove: function (name) | |
{ | |
var scope = this; | |
forEachCookie(name, function (thisName, thisValue) | |
{ | |
scope.write({ | |
name: thisName, | |
value: '', | |
expireDate: new Date(0) | |
}); | |
}); | |
} | |
}; | |
})(); | |
// The basic funcions for interaction with either localStorage or sessionStorage | |
var domStorage = { | |
set: function (config, object) | |
{ | |
var name, value; | |
for (name in config) | |
{ | |
if (!hasProperty.call(config, name)) continue; | |
value = config[name]; | |
value = encode(value, false); | |
object.setItem(name, value); | |
} | |
} | |
, get: function (name, object) | |
{ | |
var result = object.getItem(name); | |
if (result) | |
result = decode(result); | |
return result; | |
} | |
}; | |
// Assemble our object | |
var domStore = { | |
cookie: cookie | |
, prefix: location.host | |
}; | |
function makeStorageObject(key, object) | |
{ | |
// These functions decide between DOMStorage and cookies, depending on browser support | |
this[key] = { | |
storage: object && isFn(object.setItem) && isFn(object.getItem) ? object : null | |
, prefix: getName(domStore.prefix, key) | |
// Arguments accepted here are: | |
// (string) name, (mixed) value | |
// or | |
// (object) config with key value pairs that match the name, value args above | |
, set: function () | |
{ | |
var config = getConfig(arguments), | |
storage = this.storage; | |
if (storage) | |
domStorage.set(config, storage); | |
else | |
cookie.set(config, this.prefix); | |
} | |
// Again, values come back JSON decoded (if the browser supports it) | |
// load json2.js to make sure older browsers support this feature. | |
, get: function (name) | |
{ | |
var storage = this.storage; | |
if (storage) | |
return domStorage.get(name, storage); | |
else | |
return cookie.get(name, this.prefix); | |
} | |
}; | |
} | |
// Make sure we don't get any errors trying to access these objects | |
var local = null, session = null; | |
try | |
{ | |
local = localStorage; | |
session = sessionStorage; | |
} | |
catch (e) { } | |
makeStorageObject.call(domStore, "local", local); | |
makeStorageObject.call(domStore, "session", session); | |
// Export our object | |
this.domStore = domStore; | |
}).call(this); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment