Skip to content

Instantly share code, notes, and snippets.

@rfessler
Created January 11, 2013 15:02
Show Gist options
  • Save rfessler/4511299 to your computer and use it in GitHub Desktop.
Save rfessler/4511299 to your computer and use it in GitHub Desktop.
storageExample using json
.rwb1 {background-color: red;}
.rwb2 {background-color: yellow;}
#container {
width: 200px;
height: 200px;
padding: 10px;
margin: 0 auto;
text-align: center;
}
<!DOCTYPE HTML>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<title>
</title>
<link rel="stylesheet" href="a.css">
<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.2.min.js?v1.7.2" type="text/javascript"> </script>
<script src="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.23/jquery-ui.min.js?v1.8.23" type="text/javascript"> </script>
<script src="jquery/jquery-jstorage.js" type="text/javascript"></script>
<script src="a.js" type="text/javascript"></script>
</head>
<body>
<div id="container" >
<p>click on this box to do work i.e., turn color to red & remove this text.</p>
</div>
<hr>
</body>
</html>
var jsonObj;
$(document).ready(function(ready) {
$selection = $('#container');
$selection.addClass('rwb2'); // red
// stringify selector
jsonObj = JSON.stringify($('#container'));
// place selector in storage
$.jStorage.set('currentpageselector', jsonObj)
$('#container').on('click', function(el){
_this = $(this);
// get selector string out of storage
var jsonStr = $.jStorage.get('currentpageselector');
// parse the selector string
var obj = $.parseJSON(jsonStr);
// create the jquery object
var _selector = $(obj.selector);
// do work i.e., addclass/removeClass
_selector.addClass('rwb1').removeClass('rwb2');
_selector.text('Done!!');
});
});
/**
* just extra original code
* @type {Object}
* ===============================
var myObj = {
level_one: {
level_two: {
key: 'val'
},
level_two_too: {
level_three: {
key: 'val'
}
}
},
level_one_too: {
key: 'val'
}
};
$('#container').removeClass('rwb1');
str = JSON.stringify(myObj);
$('#container').text(str);
console.log('string');
console.log(str);
console.log('object');
console.log($.parseJSON(str));
// var obj = $.parseJSON(jsonObj);
// var _this = $(obj.selector);
// _this.addClass('rwb2');
// or
// var obj = $.parseJSON(JSON.stringify($('#container')));
// var _this = $(obj.selector);
// _this.addClass('rwb2') ;
*/
/*
* ----------------------------- JSTORAGE -------------------------------------
* Simple local storage wrapper to save data on the browser side, supporting
* all major browsers - IE6+, Firefox2+, Safari4+, Chrome4+ and Opera 10.5+
*
* Copyright (c) 2010 - 2012 Andris Reinman, [email protected]
* Project homepage: www.jstorage.info
*
* Licensed under MIT-style license:
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
(function () {
var
/* jStorage version */
JSTORAGE_VERSION = "0.3.1",
/* detect a dollar object or create one if not found */
$ = window.jQuery || window.$ || (window.$ = {}),
/* check for a JSON handling support */
JSON = {
parse:
window.JSON && (window.JSON.parse || window.JSON.decode) ||
String.prototype.evalJSON && function (str) { return String(str).evalJSON(); } ||
$.parseJSON ||
$.evalJSON,
stringify:
Object.toJSON ||
window.JSON && (window.JSON.stringify || window.JSON.encode) ||
$.toJSON
};
// Break if no JSON support was found
if (!JSON.parse || !JSON.stringify) {
throw new Error("No JSON support found, include //cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js to page");
}
var
/* This is the object, that holds the cached values */
_storage = {},
/* Actual browser storage (localStorage or globalStorage['domain']) */
_storage_service = { jStorage: "{}" },
/* DOM element for older IE versions, holds userData behavior */
_storage_elm = null,
/* How much space does the storage take */
_storage_size = 0,
/* which backend is currently used */
_backend = false,
/* onchange observers */
_observers = {},
/* timeout to wait after onchange event */
_observer_timeout = false,
/* last update time */
_observer_update = 0,
/* pubsub observers */
_pubsub_observers = {},
/* skip published items older than current timestamp */
_pubsub_last = +new Date(),
/* Next check for TTL */
_ttl_timeout,
/**
* XML encoding and decoding as XML nodes can't be JSON'ized
* XML nodes are encoded and decoded if the node is the value to be saved
* but not if it's as a property of another object
* Eg. -
* $.jStorage.set("key", xmlNode); // IS OK
* $.jStorage.set("key", {xml: xmlNode}); // NOT OK
*/
_XMLService = {
/**
* Validates a XML node to be XML
* based on jQuery.isXML function
*/
isXML: function (elm) {
var documentElement = (elm ? elm.ownerDocument || elm : 0).documentElement;
return documentElement ? documentElement.nodeName !== "HTML" : false;
},
/**
* Encodes a XML node to string
* based on http://www.mercurytide.co.uk/news/article/issues-when-working-ajax/
*/
encode: function (xmlNode) {
if (!this.isXML(xmlNode)) {
return false;
}
try { // Mozilla, Webkit, Opera
return new XMLSerializer().serializeToString(xmlNode);
} catch (E1) {
try { // IE
return xmlNode.xml;
} catch (E2) { }
}
return false;
},
/**
* Decodes a XML node from string
* loosely based on http://outwestmedia.com/jquery-plugins/xmldom/
*/
decode: function (xmlString) {
var dom_parser = ("DOMParser" in window && (new DOMParser()).parseFromString) ||
(window.ActiveXObject && function (_xmlString) {
var xml_doc = new ActiveXObject('Microsoft.XMLDOM');
xml_doc.async = 'false';
xml_doc.loadXML(_xmlString);
return xml_doc;
}),
resultXML;
if (!dom_parser) {
return false;
}
resultXML = dom_parser.call("DOMParser" in window && (new DOMParser()) || window, xmlString, 'text/xml');
return this.isXML(resultXML) ? resultXML : false;
}
},
_localStoragePolyfillSetKey = function () { };
////////////////////////// PRIVATE METHODS ////////////////////////
/**
* Initialization function. Detects if the browser supports DOM Storage
* or userData behavior and behaves accordingly.
*/
function _init() {
/* Check if browser supports localStorage */
var localStorageReallyWorks = false;
if ("localStorage" in window) {
try {
window.localStorage.setItem('_tmptest', 'tmpval');
localStorageReallyWorks = true;
window.localStorage.removeItem('_tmptest');
} catch (BogusQuotaExceededErrorOnIos5) {
// Thanks be to iOS5 Private Browsing mode which throws
// QUOTA_EXCEEDED_ERRROR DOM Exception 22.
}
}
if (localStorageReallyWorks) {
try {
if (window.localStorage) {
_storage_service = window.localStorage;
_backend = "localStorage";
_observer_update = _storage_service.jStorage_update;
}
} catch (E3) { /* Firefox fails when touching localStorage and cookies are disabled */ }
}
/* Check if browser supports globalStorage */
else if ("globalStorage" in window) {
try {
if (window.globalStorage) {
_storage_service = window.globalStorage[window.location.hostname];
_backend = "globalStorage";
_observer_update = _storage_service.jStorage_update;
}
} catch (E4) { /* Firefox fails when touching localStorage and cookies are disabled */ }
}
/* Check if browser supports userData behavior */
else {
_storage_elm = document.createElement('link');
if (_storage_elm.addBehavior) {
/* Use a DOM element to act as userData storage */
_storage_elm.style.behavior = 'url(#default#userData)';
/* userData element needs to be inserted into the DOM! */
document.getElementsByTagName('head')[0].appendChild(_storage_elm);
try {
_storage_elm.load("jStorage");
} catch (E) {
// try to reset cache
_storage_elm.setAttribute("jStorage", "{}");
_storage_elm.save("jStorage");
_storage_elm.load("jStorage");
}
var data = "{}";
try {
data = _storage_elm.getAttribute("jStorage");
} catch (E5) { }
try {
_observer_update = _storage_elm.getAttribute("jStorage_update");
} catch (E6) { }
_storage_service.jStorage = data;
_backend = "userDataBehavior";
} else {
_storage_elm = null;
return;
}
}
// Load data from storage
_load_storage();
// remove dead keys
_handleTTL();
// create localStorage and sessionStorage polyfills if needed
_createPolyfillStorage("local");
_createPolyfillStorage("session");
// start listening for changes
_setupObserver();
// initialize publish-subscribe service
_handlePubSub();
// handle cached navigation
if ("addEventListener" in window) {
window.addEventListener("pageshow", function (event) {
if (event.persisted) {
_storageObserver();
}
}, false);
}
}
/**
* Create a polyfill for localStorage (type="local") or sessionStorage (type="session")
*
* @param {String} type Either "local" or "session"
* @param {Boolean} forceCreate If set to true, recreate the polyfill (needed with flush)
*/
function _createPolyfillStorage(type, forceCreate) {
var _skipSave = false,
_length = 0,
i,
storage,
storage_source = {};
var rand = Math.random();
if (!forceCreate && typeof window[type + "Storage"] != "undefined") {
return;
}
// Use globalStorage for localStorage if available
if (type == "local" && window.globalStorage) {
localStorage = window.globalStorage[window.location.hostname];
return;
}
// only IE6/7 from this point on
if (_backend != "userDataBehavior") {
return;
}
// Remove existing storage element if available
if (forceCreate && window[type + "Storage"] && window[type + "Storage"].parentNode) {
window[type + "Storage"].parentNode.removeChild(window[type + "Storage"]);
}
storage = document.createElement("button");
document.getElementsByTagName('head')[0].appendChild(storage);
if (type == "local") {
storage_source = _storage;
} else if (type == "session") {
_sessionStoragePolyfillUpdate();
}
for (i in storage_source) {
if (storage_source.hasOwnProperty(i) && i != "__jstorage_meta" && i != "length" && typeof storage_source[i] != "undefined") {
if (!(i in storage)) {
_length++;
}
storage[i] = storage_source[i];
}
}
// Polyfill API
/**
* Indicates how many keys are stored in the storage
*/
storage.length = _length;
/**
* Returns the key of the nth stored value
*
* @param {Number} n Index position
* @return {String} Key name of the nth stored value
*/
storage.key = function (n) {
var count = 0, i;
_sessionStoragePolyfillUpdate();
for (i in storage_source) {
if (storage_source.hasOwnProperty(i) && i != "__jstorage_meta" && i != "length" && typeof storage_source[i] != "undefined") {
if (count == n) {
return i;
}
count++;
}
}
}
/**
* Returns the current value associated with the given key
*
* @param {String} key key name
* @return {Mixed} Stored value
*/
storage.getItem = function (key) {
_sessionStoragePolyfillUpdate();
if (type == "session") {
return storage_source[key];
}
return $.jStorage.get(key);
}
/**
* Sets or updates value for a give key
*
* @param {String} key Key name to be updated
* @param {String} value String value to be stored
*/
storage.setItem = function (key, value) {
if (typeof value == "undefined") {
return;
}
storage[key] = (value || "").toString();
}
/**
* Removes key from the storage
*
* @param {String} key Key name to be removed
*/
storage.removeItem = function (key) {
if (type == "local") {
return $.jStorage.deleteKey(key);
}
storage[key] = undefined;
_skipSave = true;
if (key in storage) {
storage.removeAttribute(key);
}
_skipSave = false;
}
/**
* Clear storage
*/
storage.clear = function () {
if (type == "session") {
window.name = "";
_createPolyfillStorage("session", true);
return;
}
$.jStorage.flush();
}
if (type == "local") {
_localStoragePolyfillSetKey = function (key, value) {
if (key == "length") {
return;
}
_skipSave = true;
if (typeof value == "undefined") {
if (key in storage) {
_length--;
storage.removeAttribute(key);
}
} else {
if (!(key in storage)) {
_length++;
}
storage[key] = (value || "").toString();
}
storage.length = _length;
_skipSave = false;
}
}
function _sessionStoragePolyfillUpdate() {
if (type != "session") {
return;
}
try {
storage_source = JSON.parse(window.name || "{}");
} catch (E) {
storage_source = {};
}
}
function _sessionStoragePolyfillSave() {
if (type != "session") {
return;
}
window.name = JSON.stringify(storage_source);
};
storage.attachEvent("onpropertychange", function (e) {
if (e.propertyName == "length") {
return;
}
if (_skipSave || e.propertyName == "length") {
return;
}
if (type == "local") {
if (!(e.propertyName in storage_source) && typeof storage[e.propertyName] != "undefined") {
_length++;
}
} else if (type == "session") {
_sessionStoragePolyfillUpdate();
if (typeof storage[e.propertyName] != "undefined" && !(e.propertyName in storage_source)) {
storage_source[e.propertyName] = storage[e.propertyName];
_length++;
} else if (typeof storage[e.propertyName] == "undefined" && e.propertyName in storage_source) {
delete storage_source[e.propertyName];
_length--;
} else {
storage_source[e.propertyName] = storage[e.propertyName];
}
_sessionStoragePolyfillSave();
storage.length = _length;
return;
}
$.jStorage.set(e.propertyName, storage[e.propertyName]);
storage.length = _length;
});
window[type + "Storage"] = storage;
}
/**
* Reload data from storage when needed
*/
function _reloadData() {
var data = "{}";
if (_backend == "userDataBehavior") {
_storage_elm.load("jStorage");
try {
data = _storage_elm.getAttribute("jStorage");
} catch (E5) { }
try {
_observer_update = _storage_elm.getAttribute("jStorage_update");
} catch (E6) { }
_storage_service.jStorage = data;
}
_load_storage();
// remove dead keys
_handleTTL();
_handlePubSub();
}
/**
* Sets up a storage change observer
*/
function _setupObserver() {
if (_backend == "localStorage" || _backend == "globalStorage") {
if ("addEventListener" in window) {
window.addEventListener("storage", _storageObserver, false);
} else {
document.attachEvent("onstorage", _storageObserver);
}
} else if (_backend == "userDataBehavior") {
setInterval(_storageObserver, 1000);
}
}
/**
* Fired on any kind of data change, needs to check if anything has
* really been changed
*/
function _storageObserver() {
var updateTime;
// cumulate change notifications with timeout
clearTimeout(_observer_timeout);
_observer_timeout = setTimeout(function () {
if (_backend == "localStorage" || _backend == "globalStorage") {
updateTime = _storage_service.jStorage_update;
} else if (_backend == "userDataBehavior") {
_storage_elm.load("jStorage");
try {
updateTime = _storage_elm.getAttribute("jStorage_update");
} catch (E5) { }
}
if (updateTime && updateTime != _observer_update) {
_observer_update = updateTime;
_checkUpdatedKeys();
}
}, 25);
}
/**
* Reloads the data and checks if any keys are changed
*/
function _checkUpdatedKeys() {
var oldCrc32List = JSON.parse(JSON.stringify(_storage.__jstorage_meta.CRC32)),
newCrc32List;
_reloadData();
newCrc32List = JSON.parse(JSON.stringify(_storage.__jstorage_meta.CRC32));
var key,
updated = [],
removed = [];
for (key in oldCrc32List) {
if (oldCrc32List.hasOwnProperty(key)) {
if (!newCrc32List[key]) {
removed.push(key);
continue;
}
if (oldCrc32List[key] != newCrc32List[key] && String(oldCrc32List[key]).substr(0, 2) == "2.") {
updated.push(key);
}
}
}
for (key in newCrc32List) {
if (newCrc32List.hasOwnProperty(key)) {
if (!oldCrc32List[key]) {
updated.push(key);
}
}
}
_fireObservers(updated, "updated");
_fireObservers(removed, "deleted");
}
/**
* Fires observers for updated keys
*
* @param {Array|String} keys Array of key names or a key
* @param {String} action What happened with the value (updated, deleted, flushed)
*/
function _fireObservers(keys, action) {
keys = [].concat(keys || []);
if (action == "flushed") {
keys = [];
for (var key in _observers) {
if (_observers.hasOwnProperty(key)) {
keys.push(key);
}
}
action = "deleted";
}
for (var i = 0, len = keys.length; i < len; i++) {
if (_observers[keys[i]]) {
for (var j = 0, jlen = _observers[keys[i]].length; j < jlen; j++) {
_observers[keys[i]][j](keys[i], action);
}
}
}
}
/**
* Publishes key change to listeners
*/
function _publishChange() {
var updateTime = (+new Date()).toString();
if (_backend == "localStorage" || _backend == "globalStorage") {
_storage_service.jStorage_update = updateTime;
} else if (_backend == "userDataBehavior") {
_storage_elm.setAttribute("jStorage_update", updateTime);
_storage_elm.save("jStorage");
}
_storageObserver();
}
/**
* Loads the data from the storage based on the supported mechanism
*/
function _load_storage() {
/* if jStorage string is retrieved, then decode it */
if (_storage_service.jStorage) {
try {
_storage = JSON.parse(String(_storage_service.jStorage));
} catch (E6) { _storage_service.jStorage = "{}"; }
} else {
_storage_service.jStorage = "{}";
}
_storage_size = _storage_service.jStorage ? String(_storage_service.jStorage).length : 0;
if (!_storage.__jstorage_meta) {
_storage.__jstorage_meta = {};
}
if (!_storage.__jstorage_meta.CRC32) {
_storage.__jstorage_meta.CRC32 = {};
}
}
/**
* This functions provides the "save" mechanism to store the jStorage object
*/
function _save() {
_dropOldEvents(); // remove expired events
try {
_storage_service.jStorage = JSON.stringify(_storage);
// If userData is used as the storage engine, additional
if (_storage_elm) {
_storage_elm.setAttribute("jStorage", _storage_service.jStorage);
_storage_elm.save("jStorage");
}
_storage_size = _storage_service.jStorage ? String(_storage_service.jStorage).length : 0;
} catch (E7) { /* probably cache is full, nothing is saved this way*/ }
}
/**
* Function checks if a key is set and is string or numberic
*
* @param {String} key Key name
*/
function _checkKey(key) {
if (!key || (typeof key != "string" && typeof key != "number")) {
throw new TypeError('Key name must be string or numeric');
}
if (key == "__jstorage_meta") {
throw new TypeError('Reserved key name');
}
return true;
}
/**
* Removes expired keys
*/
function _handleTTL() {
var curtime, i, TTL, CRC32, nextExpire = Infinity, changed = false, deleted = [];
clearTimeout(_ttl_timeout);
if (!_storage.__jstorage_meta || typeof _storage.__jstorage_meta.TTL != "object") {
// nothing to do here
return;
}
curtime = +new Date();
TTL = _storage.__jstorage_meta.TTL;
CRC32 = _storage.__jstorage_meta.CRC32;
for (i in TTL) {
if (TTL.hasOwnProperty(i)) {
if (TTL[i] <= curtime) {
delete TTL[i];
delete CRC32[i];
delete _storage[i];
changed = true;
deleted.push(i);
} else if (TTL[i] < nextExpire) {
nextExpire = TTL[i];
}
}
}
// set next check
if (nextExpire != Infinity) {
_ttl_timeout = setTimeout(_handleTTL, nextExpire - curtime);
}
// save changes
if (changed) {
_save();
_publishChange();
_fireObservers(deleted, "deleted");
}
}
/**
* Checks if there's any events on hold to be fired to listeners
*/
function _handlePubSub() {
if (!_storage.__jstorage_meta.PubSub) {
return;
}
var pubelm,
_pubsubCurrent = _pubsub_last;
for (var i = len = _storage.__jstorage_meta.PubSub.length - 1; i >= 0; i--) {
pubelm = _storage.__jstorage_meta.PubSub[i];
if (pubelm[0] > _pubsub_last) {
_pubsubCurrent = pubelm[0];
_fireSubscribers(pubelm[1], pubelm[2]);
}
}
_pubsub_last = _pubsubCurrent;
}
/**
* Fires all subscriber listeners for a pubsub channel
*
* @param {String} channel Channel name
* @param {Mixed} payload Payload data to deliver
*/
function _fireSubscribers(channel, payload) {
if (_pubsub_observers[channel]) {
for (var i = 0, len = _pubsub_observers[channel].length; i < len; i++) {
// send immutable data that can't be modified by listeners
_pubsub_observers[channel][i](channel, JSON.parse(JSON.stringify(payload)));
}
}
}
/**
* Remove old events from the publish stream (at least 2sec old)
*/
function _dropOldEvents() {
if (!_storage.__jstorage_meta.PubSub) {
return;
}
var retire = +new Date() - 2000;
for (var i = 0, len = _storage.__jstorage_meta.PubSub.length; i < len; i++) {
if (_storage.__jstorage_meta.PubSub[i][0] <= retire) {
// deleteCount is needed for IE6
_storage.__jstorage_meta.PubSub.splice(i, _storage.__jstorage_meta.PubSub.length - i);
break;
}
}
if (!_storage.__jstorage_meta.PubSub.length) {
delete _storage.__jstorage_meta.PubSub;
}
}
/**
* Publish payload to a channel
*
* @param {String} channel Channel name
* @param {Mixed} payload Payload to send to the subscribers
*/
function _publish(channel, payload) {
if (!_storage.__jstorage_meta) {
_storage.__jstorage_meta = {};
}
if (!_storage.__jstorage_meta.PubSub) {
_storage.__jstorage_meta.PubSub = [];
}
_storage.__jstorage_meta.PubSub.unshift([+new Date, channel, payload]);
_save();
_publishChange();
}
/**
* JS Implementation of MurmurHash2
*
* SOURCE: https://github.com/garycourt/murmurhash-js (MIT licensed)
*
* @author <a href="mailto:[email protected]">Gary Court</a>
* @see http://github.com/garycourt/murmurhash-js
* @author <a href="mailto:[email protected]">Austin Appleby</a>
* @see http://sites.google.com/site/murmurhash/
*
* @param {string} str ASCII only
* @param {number} seed Positive integer only
* @return {number} 32-bit positive integer hash
*/
function murmurhash2_32_gc(str, seed) {
var
l = str.length,
h = seed ^ l,
i = 0,
k;
while (l >= 4) {
k =
((str.charCodeAt(i) & 0xff)) |
((str.charCodeAt(++i) & 0xff) << 8) |
((str.charCodeAt(++i) & 0xff) << 16) |
((str.charCodeAt(++i) & 0xff) << 24);
k = (((k & 0xffff) * 0x5bd1e995) + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16));
k ^= k >>> 24;
k = (((k & 0xffff) * 0x5bd1e995) + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16));
h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16)) ^ k;
l -= 4;
++i;
}
switch (l) {
case 3: h ^= (str.charCodeAt(i + 2) & 0xff) << 16;
case 2: h ^= (str.charCodeAt(i + 1) & 0xff) << 8;
case 1: h ^= (str.charCodeAt(i) & 0xff);
h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16));
}
h ^= h >>> 13;
h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16));
h ^= h >>> 15;
return h >>> 0;
}
////////////////////////// PUBLIC INTERFACE /////////////////////////
$.jStorage = {
/* Version number */
version: JSTORAGE_VERSION,
/**
* Sets a key's value.
*
* @param {String} key Key to set. If this value is not set or not
* a string an exception is raised.
* @param {Mixed} value Value to set. This can be any value that is JSON
* compatible (Numbers, Strings, Objects etc.).
* @param {Object} [options] - possible options to use
* @param {Number} [options.TTL] - optional TTL value
* @return {Mixed} the used value
*/
set: function (key, value, options) {
_checkKey(key);
options = options || {};
// undefined values are deleted automatically
if (typeof value == "undefined") {
this.deleteKey(key);
return value;
}
if (_XMLService.isXML(value)) {
value = { _is_xml: true, xml: _XMLService.encode(value) };
} else if (typeof value == "function") {
return undefined; // functions can't be saved!
} else if (value && typeof value == "object") {
// clone the object before saving to _storage tree
value = JSON.parse(JSON.stringify(value));
}
_storage[key] = value;
_storage.__jstorage_meta.CRC32[key] = "2." + murmurhash2_32_gc(JSON.stringify(value));
this.setTTL(key, options.TTL || 0); // also handles saving and _publishChange
_localStoragePolyfillSetKey(key, value);
_fireObservers(key, "updated");
return value;
},
/**
* Looks up a key in cache
*
* @param {String} key - Key to look up.
* @param {mixed} def - Default value to return, if key didn't exist.
* @return {Mixed} the key value, default value or null
*/
get: function (key, def) {
_checkKey(key);
if (key in _storage) {
if (_storage[key] && typeof _storage[key] == "object" && _storage[key]._is_xml) {
return _XMLService.decode(_storage[key].xml);
} else {
return _storage[key];
}
}
return typeof (def) == 'undefined' ? null : def;
},
/**
* Deletes a key from cache.
*
* @param {String} key - Key to delete.
* @return {Boolean} true if key existed or false if it didn't
*/
deleteKey: function (key) {
_checkKey(key);
if (key in _storage) {
delete _storage[key];
// remove from TTL list
if (typeof _storage.__jstorage_meta.TTL == "object" &&
key in _storage.__jstorage_meta.TTL) {
delete _storage.__jstorage_meta.TTL[key];
}
delete _storage.__jstorage_meta.CRC32[key];
_localStoragePolyfillSetKey(key, undefined);
_save();
_publishChange();
_fireObservers(key, "deleted");
return true;
}
return false;
},
/**
* Sets a TTL for a key, or remove it if ttl value is 0 or below
*
* @param {String} key - key to set the TTL for
* @param {Number} ttl - TTL timeout in milliseconds
* @return {Boolean} true if key existed or false if it didn't
*/
setTTL: function (key, ttl) {
var curtime = +new Date();
_checkKey(key);
ttl = Number(ttl) || 0;
if (key in _storage) {
if (!_storage.__jstorage_meta.TTL) {
_storage.__jstorage_meta.TTL = {};
}
// Set TTL value for the key
if (ttl > 0) {
_storage.__jstorage_meta.TTL[key] = curtime + ttl;
} else {
delete _storage.__jstorage_meta.TTL[key];
}
_save();
_handleTTL();
_publishChange();
return true;
}
return false;
},
/**
* Gets remaining TTL (in milliseconds) for a key or 0 when no TTL has been set
*
* @param {String} key Key to check
* @return {Number} Remaining TTL in milliseconds
*/
getTTL: function (key) {
var curtime = +new Date(), ttl;
_checkKey(key);
if (key in _storage && _storage.__jstorage_meta.TTL && _storage.__jstorage_meta.TTL[key]) {
ttl = _storage.__jstorage_meta.TTL[key] - curtime;
return ttl || 0;
}
return 0;
},
/**
* Deletes everything in cache.
*
* @return {Boolean} Always true
*/
flush: function () {
_storage = { __jstorage_meta: { CRC32: {}} };
_createPolyfillStorage("local", true);
_save();
_publishChange();
_fireObservers(null, "flushed");
return true;
},
/**
* Returns a read-only copy of _storage
*
* @return {Object} Read-only copy of _storage
*/
storageObj: function () {
function F() { }
F.prototype = _storage;
return new F();
},
/**
* Returns an index of all used keys as an array
* ['key1', 'key2',..'keyN']
*
* @return {Array} Used keys
*/
index: function () {
var index = [], i;
for (i in _storage) {
if (_storage.hasOwnProperty(i) && i != "__jstorage_meta") {
index.push(i);
}
}
return index;
},
/**
* How much space in bytes does the storage take?
*
* @return {Number} Storage size in chars (not the same as in bytes,
* since some chars may take several bytes)
*/
storageSize: function () {
return _storage_size;
},
/**
* Which backend is currently in use?
*
* @return {String} Backend name
*/
currentBackend: function () {
return _backend;
},
/**
* Test if storage is available
*
* @return {Boolean} True if storage can be used
*/
storageAvailable: function () {
return !!_backend;
},
/**
* Register change listeners
*
* @param {String} key Key name
* @param {Function} callback Function to run when the key changes
*/
listenKeyChange: function (key, callback) {
_checkKey(key);
if (!_observers[key]) {
_observers[key] = [];
}
_observers[key].push(callback);
},
/**
* Remove change listeners
*
* @param {String} key Key name to unregister listeners against
* @param {Function} [callback] If set, unregister the callback, if not - unregister all
*/
stopListening: function (key, callback) {
_checkKey(key);
if (!_observers[key]) {
return;
}
if (!callback) {
delete _observers[key];
return;
}
for (var i = _observers[key].length - 1; i >= 0; i--) {
if (_observers[key][i] == callback) {
_observers[key].splice(i, 1);
}
}
},
/**
* Subscribe to a Publish/Subscribe event stream
*
* @param {String} channel Channel name
* @param {Function} callback Function to run when the something is published to the channel
*/
subscribe: function (channel, callback) {
channel = (channel || "").toString();
if (!channel) {
throw new TypeError('Channel not defined');
}
if (!_pubsub_observers[channel]) {
_pubsub_observers[channel] = [];
}
_pubsub_observers[channel].push(callback);
},
/**
* Publish data to an event stream
*
* @param {String} channel Channel name
* @param {Mixed} payload Payload to deliver
*/
publish: function (channel, payload) {
channel = (channel || "").toString();
if (!channel) {
throw new TypeError('Channel not defined');
}
_publish(channel, payload);
},
/**
* Reloads the data from browser storage
*/
reInit: function () {
_reloadData();
}
};
// Initialize jStorage
_init();
})();
{
"folders":
[
{
"file_exclude_patterns":
[
//"*.sublime-workspace"
]
},
{
"path": "/C/Users/rfessler/Documents/Dropbox/Projects/storage"
}
]
}
{
"auto_complete":
{
"selected_items":
[
]
},
"buffers":
[
{
"contents": ".rwb1 {background-color: red;}\n.rwb2 {background-color: yellow;}\n\n#container {\n width: 200px;\n height: 200px;\n padding: 10px;\n margin: 0 auto;\n text-align: center;\n}\n\n\n",
"settings":
{
"buffer_size": 183,
"line_ending": "Windows",
"name": "a.css"
}
},
{
"contents": "<!DOCTYPE HTML>\n<html lang=\"en-US\">\n \n <head>\n <meta charset=\"UTF-8\">\n <title>\n </title>\n <link rel=\"stylesheet\" href=\"a.css\">\n <script src=\"http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.2.min.js?v1.7.2\" type=\"text/javascript\"> </script>\n <script src=\"http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.23/jquery-ui.min.js?v1.8.23\" type=\"text/javascript\"> </script> \n <script src=\"jquery/jquery-jstorage.js\" type=\"text/javascript\"></script>\n <script src=\"a.js\" type=\"text/javascript\"></script> \n </head>\n \n <body>\n <div id=\"container\" >\n <p>click on this box to do work i.e., turn color to red & remove this text.</p>\n </div>\n <hr>\n\n </body>\n\n</html>\n",
"settings":
{
"buffer_size": 755,
"line_ending": "Windows",
"name": "a.html"
}
},
{
"contents": "var jsonObj;\n\n $(document).ready(function(ready) {\n \n $selection = $('#container');\n $selection.addClass('rwb2'); // red\n\n // stringify selector\n jsonObj = JSON.stringify($('#container'));\n \n // place selector in storage\n $.jStorage.set('currentpageselector', jsonObj)\n\n\n \n $('#container').on('click', function(el){\n _this = $(this);\n\n // get selector string out of storage\n var jsonStr = $.jStorage.get('currentpageselector');\n \n // parse the selector string\n var obj = $.parseJSON(jsonStr);\n\n // create the jquery object \n var _selector = $(obj.selector);\n\n // do work i.e., addclass/removeClass\n _selector.addClass('rwb1').removeClass('rwb2');\n _selector.text('Done!!');\n });\n \n });\n\n\n\n\n\n\n /**\n * just extra original code\n * @type {Object}\n * ===============================\n var myObj = {\n level_one: {\n level_two: {\n key: 'val'\n },\n level_two_too: {\n level_three: {\n key: 'val'\n }\n }\n },\n level_one_too: {\n key: 'val'\n }\n };\n\n $('#container').removeClass('rwb1');\n \n str = JSON.stringify(myObj);\n $('#container').text(str);\n console.log('string');\n console.log(str);\n console.log('object');\n console.log($.parseJSON(str)); \n\n // var obj = $.parseJSON(jsonObj);\n // var _this = $(obj.selector);\n // _this.addClass('rwb2');\n\n // or \n // var obj = $.parseJSON(JSON.stringify($('#container')));\n // var _this = $(obj.selector);\n // _this.addClass('rwb2') ;\n \n */\n",
"settings":
{
"buffer_size": 1927,
"line_ending": "Windows",
"name": "a.js"
}
},
{
"contents": "/*\n* ----------------------------- JSTORAGE -------------------------------------\n* Simple local storage wrapper to save data on the browser side, supporting\n* all major browsers - IE6+, Firefox2+, Safari4+, Chrome4+ and Opera 10.5+\n*\n* Copyright (c) 2010 - 2012 Andris Reinman, [email protected]\n* Project homepage: www.jstorage.info\n*\n* Licensed under MIT-style license:\n*\n* Permission is hereby granted, free of charge, to any person obtaining a copy\n* of this software and associated documentation files (the \"Software\"), to deal\n* in the Software without restriction, including without limitation the rights\n* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n* copies of the Software, and to permit persons to whom the Software is\n* furnished to do so, subject to the following conditions:\n*\n* THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n* SOFTWARE.\n*/\n\n(function () {\n var\n /* jStorage version */\n JSTORAGE_VERSION = \"0.3.1\",\n\n /* detect a dollar object or create one if not found */\n $ = window.jQuery || window.$ || (window.$ = {}),\n\n /* check for a JSON handling support */\n JSON = {\n parse:\n window.JSON && (window.JSON.parse || window.JSON.decode) ||\n String.prototype.evalJSON && function (str) { return String(str).evalJSON(); } ||\n $.parseJSON ||\n $.evalJSON,\n stringify:\n Object.toJSON ||\n window.JSON && (window.JSON.stringify || window.JSON.encode) ||\n $.toJSON\n };\n\n // Break if no JSON support was found\n if (!JSON.parse || !JSON.stringify) {\n throw new Error(\"No JSON support found, include //cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js to page\");\n }\n\n var\n /* This is the object, that holds the cached values */\n _storage = {},\n\n /* Actual browser storage (localStorage or globalStorage['domain']) */\n _storage_service = { jStorage: \"{}\" },\n\n /* DOM element for older IE versions, holds userData behavior */\n _storage_elm = null,\n\n /* How much space does the storage take */\n _storage_size = 0,\n\n /* which backend is currently used */\n _backend = false,\n\n /* onchange observers */\n _observers = {},\n\n /* timeout to wait after onchange event */\n _observer_timeout = false,\n\n /* last update time */\n _observer_update = 0,\n\n /* pubsub observers */\n _pubsub_observers = {},\n\n /* skip published items older than current timestamp */\n _pubsub_last = +new Date(),\n\n /* Next check for TTL */\n _ttl_timeout,\n\n /**\n * XML encoding and decoding as XML nodes can't be JSON'ized\n * XML nodes are encoded and decoded if the node is the value to be saved\n * but not if it's as a property of another object\n * Eg. -\n * $.jStorage.set(\"key\", xmlNode); // IS OK\n * $.jStorage.set(\"key\", {xml: xmlNode}); // NOT OK\n */\n _XMLService = {\n /**\n * Validates a XML node to be XML\n * based on jQuery.isXML function\n */\n isXML: function (elm) {\n var documentElement = (elm ? elm.ownerDocument || elm : 0).documentElement;\n return documentElement ? documentElement.nodeName !== \"HTML\" : false;\n },\n\n /**\n * Encodes a XML node to string\n * based on http://www.mercurytide.co.uk/news/article/issues-when-working-ajax/\n */\n encode: function (xmlNode) {\n if (!this.isXML(xmlNode)) {\n return false;\n }\n try { // Mozilla, Webkit, Opera\n return new XMLSerializer().serializeToString(xmlNode);\n } catch (E1) {\n try { // IE\n return xmlNode.xml;\n } catch (E2) { }\n }\n return false;\n },\n\n /**\n * Decodes a XML node from string\n * loosely based on http://outwestmedia.com/jquery-plugins/xmldom/\n */\n decode: function (xmlString) {\n var dom_parser = (\"DOMParser\" in window && (new DOMParser()).parseFromString) ||\n (window.ActiveXObject && function (_xmlString) {\n var xml_doc = new ActiveXObject('Microsoft.XMLDOM');\n xml_doc.async = 'false';\n xml_doc.loadXML(_xmlString);\n return xml_doc;\n }),\n resultXML;\n if (!dom_parser) {\n return false;\n }\n resultXML = dom_parser.call(\"DOMParser\" in window && (new DOMParser()) || window, xmlString, 'text/xml');\n return this.isXML(resultXML) ? resultXML : false;\n }\n },\n\n _localStoragePolyfillSetKey = function () { };\n\n ////////////////////////// PRIVATE METHODS ////////////////////////\n\n /**\n * Initialization function. Detects if the browser supports DOM Storage\n * or userData behavior and behaves accordingly.\n */\n function _init() {\n /* Check if browser supports localStorage */\n var localStorageReallyWorks = false;\n if (\"localStorage\" in window) {\n try {\n window.localStorage.setItem('_tmptest', 'tmpval');\n localStorageReallyWorks = true;\n window.localStorage.removeItem('_tmptest');\n } catch (BogusQuotaExceededErrorOnIos5) {\n // Thanks be to iOS5 Private Browsing mode which throws\n // QUOTA_EXCEEDED_ERRROR DOM Exception 22.\n }\n }\n\n if (localStorageReallyWorks) {\n try {\n if (window.localStorage) {\n _storage_service = window.localStorage;\n _backend = \"localStorage\";\n _observer_update = _storage_service.jStorage_update;\n }\n } catch (E3) { /* Firefox fails when touching localStorage and cookies are disabled */ }\n }\n /* Check if browser supports globalStorage */\n else if (\"globalStorage\" in window) {\n try {\n if (window.globalStorage) {\n _storage_service = window.globalStorage[window.location.hostname];\n _backend = \"globalStorage\";\n _observer_update = _storage_service.jStorage_update;\n }\n } catch (E4) { /* Firefox fails when touching localStorage and cookies are disabled */ }\n }\n /* Check if browser supports userData behavior */\n else {\n _storage_elm = document.createElement('link');\n if (_storage_elm.addBehavior) {\n /* Use a DOM element to act as userData storage */\n _storage_elm.style.behavior = 'url(#default#userData)';\n\n /* userData element needs to be inserted into the DOM! */\n document.getElementsByTagName('head')[0].appendChild(_storage_elm);\n\n try {\n _storage_elm.load(\"jStorage\");\n } catch (E) {\n // try to reset cache\n _storage_elm.setAttribute(\"jStorage\", \"{}\");\n _storage_elm.save(\"jStorage\");\n _storage_elm.load(\"jStorage\");\n }\n\n var data = \"{}\";\n try {\n data = _storage_elm.getAttribute(\"jStorage\");\n } catch (E5) { }\n\n try {\n _observer_update = _storage_elm.getAttribute(\"jStorage_update\");\n } catch (E6) { }\n\n _storage_service.jStorage = data;\n _backend = \"userDataBehavior\";\n } else {\n _storage_elm = null;\n return;\n }\n }\n\n // Load data from storage\n _load_storage();\n\n // remove dead keys\n _handleTTL();\n\n // create localStorage and sessionStorage polyfills if needed\n _createPolyfillStorage(\"local\");\n _createPolyfillStorage(\"session\");\n\n // start listening for changes\n _setupObserver();\n\n // initialize publish-subscribe service\n _handlePubSub();\n\n // handle cached navigation\n if (\"addEventListener\" in window) {\n window.addEventListener(\"pageshow\", function (event) {\n if (event.persisted) {\n _storageObserver();\n }\n }, false);\n }\n }\n\n /**\n * Create a polyfill for localStorage (type=\"local\") or sessionStorage (type=\"session\")\n *\n * @param {String} type Either \"local\" or \"session\"\n * @param {Boolean} forceCreate If set to true, recreate the polyfill (needed with flush)\n */\n function _createPolyfillStorage(type, forceCreate) {\n var _skipSave = false,\n _length = 0,\n i,\n storage,\n storage_source = {};\n\n var rand = Math.random();\n\n if (!forceCreate && typeof window[type + \"Storage\"] != \"undefined\") {\n return;\n }\n\n // Use globalStorage for localStorage if available\n if (type == \"local\" && window.globalStorage) {\n localStorage = window.globalStorage[window.location.hostname];\n return;\n }\n\n // only IE6/7 from this point on\n if (_backend != \"userDataBehavior\") {\n return;\n }\n\n // Remove existing storage element if available\n if (forceCreate && window[type + \"Storage\"] && window[type + \"Storage\"].parentNode) {\n window[type + \"Storage\"].parentNode.removeChild(window[type + \"Storage\"]);\n }\n\n storage = document.createElement(\"button\");\n document.getElementsByTagName('head')[0].appendChild(storage);\n\n if (type == \"local\") {\n storage_source = _storage;\n } else if (type == \"session\") {\n _sessionStoragePolyfillUpdate();\n }\n\n for (i in storage_source) {\n if (storage_source.hasOwnProperty(i) && i != \"__jstorage_meta\" && i != \"length\" && typeof storage_source[i] != \"undefined\") {\n if (!(i in storage)) {\n _length++;\n }\n storage[i] = storage_source[i];\n }\n }\n\n // Polyfill API\n\n /**\n * Indicates how many keys are stored in the storage\n */\n storage.length = _length;\n\n /**\n * Returns the key of the nth stored value\n *\n * @param {Number} n Index position\n * @return {String} Key name of the nth stored value\n */\n storage.key = function (n) {\n var count = 0, i;\n _sessionStoragePolyfillUpdate();\n for (i in storage_source) {\n if (storage_source.hasOwnProperty(i) && i != \"__jstorage_meta\" && i != \"length\" && typeof storage_source[i] != \"undefined\") {\n if (count == n) {\n return i;\n }\n count++;\n }\n }\n }\n\n /**\n * Returns the current value associated with the given key\n *\n * @param {String} key key name\n * @return {Mixed} Stored value\n */\n storage.getItem = function (key) {\n _sessionStoragePolyfillUpdate();\n if (type == \"session\") {\n return storage_source[key];\n }\n return $.jStorage.get(key);\n }\n\n /**\n * Sets or updates value for a give key\n *\n * @param {String} key Key name to be updated\n * @param {String} value String value to be stored\n */\n storage.setItem = function (key, value) {\n if (typeof value == \"undefined\") {\n return;\n }\n storage[key] = (value || \"\").toString();\n }\n\n /**\n * Removes key from the storage\n *\n * @param {String} key Key name to be removed\n */\n storage.removeItem = function (key) {\n if (type == \"local\") {\n return $.jStorage.deleteKey(key);\n }\n\n storage[key] = undefined;\n\n _skipSave = true;\n if (key in storage) {\n storage.removeAttribute(key);\n }\n _skipSave = false;\n }\n\n /**\n * Clear storage\n */\n storage.clear = function () {\n if (type == \"session\") {\n window.name = \"\";\n _createPolyfillStorage(\"session\", true);\n return;\n }\n $.jStorage.flush();\n }\n\n if (type == \"local\") {\n _localStoragePolyfillSetKey = function (key, value) {\n if (key == \"length\") {\n return;\n }\n _skipSave = true;\n if (typeof value == \"undefined\") {\n if (key in storage) {\n _length--;\n storage.removeAttribute(key);\n }\n } else {\n if (!(key in storage)) {\n _length++;\n }\n storage[key] = (value || \"\").toString();\n }\n storage.length = _length;\n _skipSave = false;\n }\n }\n\n function _sessionStoragePolyfillUpdate() {\n if (type != \"session\") {\n return;\n }\n try {\n storage_source = JSON.parse(window.name || \"{}\");\n } catch (E) {\n storage_source = {};\n }\n }\n\n function _sessionStoragePolyfillSave() {\n if (type != \"session\") {\n return;\n }\n window.name = JSON.stringify(storage_source);\n };\n\n storage.attachEvent(\"onpropertychange\", function (e) {\n if (e.propertyName == \"length\") {\n return;\n }\n\n if (_skipSave || e.propertyName == \"length\") {\n return;\n }\n\n if (type == \"local\") {\n if (!(e.propertyName in storage_source) && typeof storage[e.propertyName] != \"undefined\") {\n _length++;\n }\n } else if (type == \"session\") {\n _sessionStoragePolyfillUpdate();\n if (typeof storage[e.propertyName] != \"undefined\" && !(e.propertyName in storage_source)) {\n storage_source[e.propertyName] = storage[e.propertyName];\n _length++;\n } else if (typeof storage[e.propertyName] == \"undefined\" && e.propertyName in storage_source) {\n delete storage_source[e.propertyName];\n _length--;\n } else {\n storage_source[e.propertyName] = storage[e.propertyName];\n }\n\n _sessionStoragePolyfillSave();\n storage.length = _length;\n return;\n }\n\n $.jStorage.set(e.propertyName, storage[e.propertyName]);\n storage.length = _length;\n });\n\n window[type + \"Storage\"] = storage;\n }\n\n /**\n * Reload data from storage when needed\n */\n function _reloadData() {\n var data = \"{}\";\n\n if (_backend == \"userDataBehavior\") {\n _storage_elm.load(\"jStorage\");\n\n try {\n data = _storage_elm.getAttribute(\"jStorage\");\n } catch (E5) { }\n\n try {\n _observer_update = _storage_elm.getAttribute(\"jStorage_update\");\n } catch (E6) { }\n\n _storage_service.jStorage = data;\n }\n\n _load_storage();\n\n // remove dead keys\n _handleTTL();\n\n _handlePubSub();\n }\n\n /**\n * Sets up a storage change observer\n */\n function _setupObserver() {\n if (_backend == \"localStorage\" || _backend == \"globalStorage\") {\n if (\"addEventListener\" in window) {\n window.addEventListener(\"storage\", _storageObserver, false);\n } else {\n document.attachEvent(\"onstorage\", _storageObserver);\n }\n } else if (_backend == \"userDataBehavior\") {\n setInterval(_storageObserver, 1000);\n }\n }\n\n /**\n * Fired on any kind of data change, needs to check if anything has\n * really been changed\n */\n function _storageObserver() {\n var updateTime;\n // cumulate change notifications with timeout\n clearTimeout(_observer_timeout);\n _observer_timeout = setTimeout(function () {\n if (_backend == \"localStorage\" || _backend == \"globalStorage\") {\n updateTime = _storage_service.jStorage_update;\n } else if (_backend == \"userDataBehavior\") {\n _storage_elm.load(\"jStorage\");\n try {\n updateTime = _storage_elm.getAttribute(\"jStorage_update\");\n } catch (E5) { }\n }\n\n if (updateTime && updateTime != _observer_update) {\n _observer_update = updateTime;\n _checkUpdatedKeys();\n }\n }, 25);\n }\n\n /**\n * Reloads the data and checks if any keys are changed\n */\n function _checkUpdatedKeys() {\n var oldCrc32List = JSON.parse(JSON.stringify(_storage.__jstorage_meta.CRC32)),\n newCrc32List;\n\n _reloadData();\n newCrc32List = JSON.parse(JSON.stringify(_storage.__jstorage_meta.CRC32));\n\n var key,\n updated = [],\n removed = [];\n\n for (key in oldCrc32List) {\n if (oldCrc32List.hasOwnProperty(key)) {\n if (!newCrc32List[key]) {\n removed.push(key);\n continue;\n }\n if (oldCrc32List[key] != newCrc32List[key] && String(oldCrc32List[key]).substr(0, 2) == \"2.\") {\n updated.push(key);\n }\n }\n }\n\n for (key in newCrc32List) {\n if (newCrc32List.hasOwnProperty(key)) {\n if (!oldCrc32List[key]) {\n updated.push(key);\n }\n }\n }\n\n _fireObservers(updated, \"updated\");\n _fireObservers(removed, \"deleted\");\n }\n\n /**\n * Fires observers for updated keys\n *\n * @param {Array|String} keys Array of key names or a key\n * @param {String} action What happened with the value (updated, deleted, flushed)\n */\n function _fireObservers(keys, action) {\n keys = [].concat(keys || []);\n if (action == \"flushed\") {\n keys = [];\n for (var key in _observers) {\n if (_observers.hasOwnProperty(key)) {\n keys.push(key);\n }\n }\n action = \"deleted\";\n }\n for (var i = 0, len = keys.length; i < len; i++) {\n if (_observers[keys[i]]) {\n for (var j = 0, jlen = _observers[keys[i]].length; j < jlen; j++) {\n _observers[keys[i]][j](keys[i], action);\n }\n }\n }\n }\n\n /**\n * Publishes key change to listeners\n */\n function _publishChange() {\n var updateTime = (+new Date()).toString();\n\n if (_backend == \"localStorage\" || _backend == \"globalStorage\") {\n _storage_service.jStorage_update = updateTime;\n } else if (_backend == \"userDataBehavior\") {\n _storage_elm.setAttribute(\"jStorage_update\", updateTime);\n _storage_elm.save(\"jStorage\");\n }\n\n _storageObserver();\n }\n\n /**\n * Loads the data from the storage based on the supported mechanism\n */\n function _load_storage() {\n /* if jStorage string is retrieved, then decode it */\n if (_storage_service.jStorage) {\n try {\n _storage = JSON.parse(String(_storage_service.jStorage));\n } catch (E6) { _storage_service.jStorage = \"{}\"; }\n } else {\n _storage_service.jStorage = \"{}\";\n }\n _storage_size = _storage_service.jStorage ? String(_storage_service.jStorage).length : 0;\n\n if (!_storage.__jstorage_meta) {\n _storage.__jstorage_meta = {};\n }\n if (!_storage.__jstorage_meta.CRC32) {\n _storage.__jstorage_meta.CRC32 = {};\n }\n }\n\n /**\n * This functions provides the \"save\" mechanism to store the jStorage object\n */\n function _save() {\n _dropOldEvents(); // remove expired events\n try {\n _storage_service.jStorage = JSON.stringify(_storage);\n // If userData is used as the storage engine, additional\n if (_storage_elm) {\n _storage_elm.setAttribute(\"jStorage\", _storage_service.jStorage);\n _storage_elm.save(\"jStorage\");\n }\n _storage_size = _storage_service.jStorage ? String(_storage_service.jStorage).length : 0;\n } catch (E7) { /* probably cache is full, nothing is saved this way*/ }\n }\n\n /**\n * Function checks if a key is set and is string or numberic\n *\n * @param {String} key Key name\n */\n function _checkKey(key) {\n if (!key || (typeof key != \"string\" && typeof key != \"number\")) {\n throw new TypeError('Key name must be string or numeric');\n }\n if (key == \"__jstorage_meta\") {\n throw new TypeError('Reserved key name');\n }\n return true;\n }\n\n /**\n * Removes expired keys\n */\n function _handleTTL() {\n var curtime, i, TTL, CRC32, nextExpire = Infinity, changed = false, deleted = [];\n\n clearTimeout(_ttl_timeout);\n\n if (!_storage.__jstorage_meta || typeof _storage.__jstorage_meta.TTL != \"object\") {\n // nothing to do here\n return;\n }\n\n curtime = +new Date();\n TTL = _storage.__jstorage_meta.TTL;\n\n CRC32 = _storage.__jstorage_meta.CRC32;\n for (i in TTL) {\n if (TTL.hasOwnProperty(i)) {\n if (TTL[i] <= curtime) {\n delete TTL[i];\n delete CRC32[i];\n delete _storage[i];\n changed = true;\n deleted.push(i);\n } else if (TTL[i] < nextExpire) {\n nextExpire = TTL[i];\n }\n }\n }\n\n // set next check\n if (nextExpire != Infinity) {\n _ttl_timeout = setTimeout(_handleTTL, nextExpire - curtime);\n }\n\n // save changes\n if (changed) {\n _save();\n _publishChange();\n _fireObservers(deleted, \"deleted\");\n }\n }\n\n /**\n * Checks if there's any events on hold to be fired to listeners\n */\n function _handlePubSub() {\n if (!_storage.__jstorage_meta.PubSub) {\n return;\n }\n var pubelm,\n _pubsubCurrent = _pubsub_last;\n\n for (var i = len = _storage.__jstorage_meta.PubSub.length - 1; i >= 0; i--) {\n pubelm = _storage.__jstorage_meta.PubSub[i];\n if (pubelm[0] > _pubsub_last) {\n _pubsubCurrent = pubelm[0];\n _fireSubscribers(pubelm[1], pubelm[2]);\n }\n }\n\n _pubsub_last = _pubsubCurrent;\n }\n\n /**\n * Fires all subscriber listeners for a pubsub channel\n *\n * @param {String} channel Channel name\n * @param {Mixed} payload Payload data to deliver\n */\n function _fireSubscribers(channel, payload) {\n if (_pubsub_observers[channel]) {\n for (var i = 0, len = _pubsub_observers[channel].length; i < len; i++) {\n // send immutable data that can't be modified by listeners\n _pubsub_observers[channel][i](channel, JSON.parse(JSON.stringify(payload)));\n }\n }\n }\n\n /**\n * Remove old events from the publish stream (at least 2sec old)\n */\n function _dropOldEvents() {\n if (!_storage.__jstorage_meta.PubSub) {\n return;\n }\n\n var retire = +new Date() - 2000;\n\n for (var i = 0, len = _storage.__jstorage_meta.PubSub.length; i < len; i++) {\n if (_storage.__jstorage_meta.PubSub[i][0] <= retire) {\n // deleteCount is needed for IE6\n _storage.__jstorage_meta.PubSub.splice(i, _storage.__jstorage_meta.PubSub.length - i);\n break;\n }\n }\n\n if (!_storage.__jstorage_meta.PubSub.length) {\n delete _storage.__jstorage_meta.PubSub;\n }\n }\n\n /**\n * Publish payload to a channel\n *\n * @param {String} channel Channel name\n * @param {Mixed} payload Payload to send to the subscribers\n */\n function _publish(channel, payload) {\n if (!_storage.__jstorage_meta) {\n _storage.__jstorage_meta = {};\n }\n if (!_storage.__jstorage_meta.PubSub) {\n _storage.__jstorage_meta.PubSub = [];\n }\n\n _storage.__jstorage_meta.PubSub.unshift([+new Date, channel, payload]);\n\n _save();\n _publishChange();\n }\n\n /**\n * JS Implementation of MurmurHash2\n *\n * SOURCE: https://github.com/garycourt/murmurhash-js (MIT licensed)\n *\n * @author <a href=\"mailto:[email protected]\">Gary Court</a>\n * @see http://github.com/garycourt/murmurhash-js\n * @author <a href=\"mailto:[email protected]\">Austin Appleby</a>\n * @see http://sites.google.com/site/murmurhash/\n *\n * @param {string} str ASCII only\n * @param {number} seed Positive integer only\n * @return {number} 32-bit positive integer hash\n */\n\n function murmurhash2_32_gc(str, seed) {\n var\n l = str.length,\n h = seed ^ l,\n i = 0,\n k;\n\n while (l >= 4) {\n k =\n ((str.charCodeAt(i) & 0xff)) |\n ((str.charCodeAt(++i) & 0xff) << 8) |\n ((str.charCodeAt(++i) & 0xff) << 16) |\n ((str.charCodeAt(++i) & 0xff) << 24);\n\n k = (((k & 0xffff) * 0x5bd1e995) + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16));\n k ^= k >>> 24;\n k = (((k & 0xffff) * 0x5bd1e995) + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16));\n\n h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16)) ^ k;\n\n l -= 4;\n ++i;\n }\n\n switch (l) {\n case 3: h ^= (str.charCodeAt(i + 2) & 0xff) << 16;\n case 2: h ^= (str.charCodeAt(i + 1) & 0xff) << 8;\n case 1: h ^= (str.charCodeAt(i) & 0xff);\n h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16));\n }\n\n h ^= h >>> 13;\n h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16));\n h ^= h >>> 15;\n\n return h >>> 0;\n }\n\n ////////////////////////// PUBLIC INTERFACE /////////////////////////\n\n $.jStorage = {\n /* Version number */\n version: JSTORAGE_VERSION,\n\n /**\n * Sets a key's value.\n *\n * @param {String} key Key to set. If this value is not set or not\n * a string an exception is raised.\n * @param {Mixed} value Value to set. This can be any value that is JSON\n * compatible (Numbers, Strings, Objects etc.).\n * @param {Object} [options] - possible options to use\n * @param {Number} [options.TTL] - optional TTL value\n * @return {Mixed} the used value\n */\n set: function (key, value, options) {\n _checkKey(key);\n\n options = options || {};\n\n // undefined values are deleted automatically\n if (typeof value == \"undefined\") {\n this.deleteKey(key);\n return value;\n }\n\n if (_XMLService.isXML(value)) {\n value = { _is_xml: true, xml: _XMLService.encode(value) };\n } else if (typeof value == \"function\") {\n return undefined; // functions can't be saved!\n } else if (value && typeof value == \"object\") {\n // clone the object before saving to _storage tree\n value = JSON.parse(JSON.stringify(value));\n }\n\n _storage[key] = value;\n\n _storage.__jstorage_meta.CRC32[key] = \"2.\" + murmurhash2_32_gc(JSON.stringify(value));\n\n this.setTTL(key, options.TTL || 0); // also handles saving and _publishChange\n\n _localStoragePolyfillSetKey(key, value);\n\n _fireObservers(key, \"updated\");\n return value;\n },\n\n /**\n * Looks up a key in cache\n *\n * @param {String} key - Key to look up.\n * @param {mixed} def - Default value to return, if key didn't exist.\n * @return {Mixed} the key value, default value or null\n */\n get: function (key, def) {\n _checkKey(key);\n if (key in _storage) {\n if (_storage[key] && typeof _storage[key] == \"object\" && _storage[key]._is_xml) {\n return _XMLService.decode(_storage[key].xml);\n } else {\n return _storage[key];\n }\n }\n return typeof (def) == 'undefined' ? null : def;\n },\n\n /**\n * Deletes a key from cache.\n *\n * @param {String} key - Key to delete.\n * @return {Boolean} true if key existed or false if it didn't\n */\n deleteKey: function (key) {\n _checkKey(key);\n if (key in _storage) {\n delete _storage[key];\n // remove from TTL list\n if (typeof _storage.__jstorage_meta.TTL == \"object\" &&\n key in _storage.__jstorage_meta.TTL) {\n delete _storage.__jstorage_meta.TTL[key];\n }\n\n delete _storage.__jstorage_meta.CRC32[key];\n _localStoragePolyfillSetKey(key, undefined);\n\n _save();\n _publishChange();\n _fireObservers(key, \"deleted\");\n return true;\n }\n return false;\n },\n\n /**\n * Sets a TTL for a key, or remove it if ttl value is 0 or below\n *\n * @param {String} key - key to set the TTL for\n * @param {Number} ttl - TTL timeout in milliseconds\n * @return {Boolean} true if key existed or false if it didn't\n */\n setTTL: function (key, ttl) {\n var curtime = +new Date();\n _checkKey(key);\n ttl = Number(ttl) || 0;\n if (key in _storage) {\n if (!_storage.__jstorage_meta.TTL) {\n _storage.__jstorage_meta.TTL = {};\n }\n\n // Set TTL value for the key\n if (ttl > 0) {\n _storage.__jstorage_meta.TTL[key] = curtime + ttl;\n } else {\n delete _storage.__jstorage_meta.TTL[key];\n }\n\n _save();\n\n _handleTTL();\n\n _publishChange();\n return true;\n }\n return false;\n },\n\n /**\n * Gets remaining TTL (in milliseconds) for a key or 0 when no TTL has been set\n *\n * @param {String} key Key to check\n * @return {Number} Remaining TTL in milliseconds\n */\n getTTL: function (key) {\n var curtime = +new Date(), ttl;\n _checkKey(key);\n if (key in _storage && _storage.__jstorage_meta.TTL && _storage.__jstorage_meta.TTL[key]) {\n ttl = _storage.__jstorage_meta.TTL[key] - curtime;\n return ttl || 0;\n }\n return 0;\n },\n\n /**\n * Deletes everything in cache.\n *\n * @return {Boolean} Always true\n */\n flush: function () {\n _storage = { __jstorage_meta: { CRC32: {}} };\n _createPolyfillStorage(\"local\", true);\n _save();\n _publishChange();\n _fireObservers(null, \"flushed\");\n return true;\n },\n\n /**\n * Returns a read-only copy of _storage\n *\n * @return {Object} Read-only copy of _storage\n */\n storageObj: function () {\n function F() { }\n F.prototype = _storage;\n return new F();\n },\n\n /**\n * Returns an index of all used keys as an array\n * ['key1', 'key2',..'keyN']\n *\n * @return {Array} Used keys\n */\n index: function () {\n var index = [], i;\n for (i in _storage) {\n if (_storage.hasOwnProperty(i) && i != \"__jstorage_meta\") {\n index.push(i);\n }\n }\n return index;\n },\n\n /**\n * How much space in bytes does the storage take?\n *\n * @return {Number} Storage size in chars (not the same as in bytes,\n * since some chars may take several bytes)\n */\n storageSize: function () {\n return _storage_size;\n },\n\n /**\n * Which backend is currently in use?\n *\n * @return {String} Backend name\n */\n currentBackend: function () {\n return _backend;\n },\n\n /**\n * Test if storage is available\n *\n * @return {Boolean} True if storage can be used\n */\n storageAvailable: function () {\n return !!_backend;\n },\n\n /**\n * Register change listeners\n *\n * @param {String} key Key name\n * @param {Function} callback Function to run when the key changes\n */\n listenKeyChange: function (key, callback) {\n _checkKey(key);\n if (!_observers[key]) {\n _observers[key] = [];\n }\n _observers[key].push(callback);\n },\n\n /**\n * Remove change listeners\n *\n * @param {String} key Key name to unregister listeners against\n * @param {Function} [callback] If set, unregister the callback, if not - unregister all\n */\n stopListening: function (key, callback) {\n _checkKey(key);\n\n if (!_observers[key]) {\n return;\n }\n\n if (!callback) {\n delete _observers[key];\n return;\n }\n\n for (var i = _observers[key].length - 1; i >= 0; i--) {\n if (_observers[key][i] == callback) {\n _observers[key].splice(i, 1);\n }\n }\n },\n\n /**\n * Subscribe to a Publish/Subscribe event stream\n *\n * @param {String} channel Channel name\n * @param {Function} callback Function to run when the something is published to the channel\n */\n subscribe: function (channel, callback) {\n channel = (channel || \"\").toString();\n if (!channel) {\n throw new TypeError('Channel not defined');\n }\n if (!_pubsub_observers[channel]) {\n _pubsub_observers[channel] = [];\n }\n _pubsub_observers[channel].push(callback);\n },\n\n /**\n * Publish data to an event stream\n *\n * @param {String} channel Channel name\n * @param {Mixed} payload Payload to deliver\n */\n publish: function (channel, payload) {\n channel = (channel || \"\").toString();\n if (!channel) {\n throw new TypeError('Channel not defined');\n }\n\n _publish(channel, payload);\n },\n\n /**\n * Reloads the data from browser storage\n */\n reInit: function () {\n _reloadData();\n }\n };\n\n // Initialize jStorage\n _init();\n})();",
"settings":
{
"buffer_size": 29752,
"line_ending": "Windows",
"name": "jquery-jstorage.js"
}
},
{
"file": "a.html",
"settings":
{
"buffer_size": 755,
"line_ending": "Windows"
}
}
],
"build_system": "Packages/User/Firefox-preview.sublime-build",
"command_palette":
{
"height": 375.0,
"selected_items":
[
[
"gis",
"Gist: Open Gist"
],
[
"sscss",
"Set Syntax: CSS"
],
[
"ssja",
"Set Syntax: jQuery (JavaScript)"
],
[
"sshtm",
"Set Syntax: HTML"
],
[
"gist",
"Gist: Open Gist"
],
[
"tid",
"Tidy HTML"
],
[
"html",
"Set Syntax: HTML"
],
[
"tidy",
"Tidy HTML"
],
[
"mark",
"Set Syntax: Markdown"
],
[
"javas",
"Set Syntax: JavaScript"
],
[
"pack",
"Package Control: Disable Package"
],
[
"insta",
"Package Control: Install Package"
],
[
"exo",
"Export to HTML: Show Export Menu"
],
[
"showex",
"Export to HTML: Show Export Menu"
],
[
"expo",
"Export to HTML: Show Export Menu"
],
[
"exp",
"Export to HTML: Show Export Menu"
],
[
"inst",
"Package Control: Install Package"
],
[
"prin",
"Print to HTML: print as HTML via browser"
],
[
"packa",
"Package Control: Upgrade Package"
],
[
"pri",
"Print to HTML: print as HTML via browser"
],
[
"print",
"Package Control: Install Package"
],
[
"prett",
"HTMLPrettify: Prettify"
],
[
"pret",
"HTMLPrettify: Prettify"
],
[
"f",
"HTMLPrettify: Prettify"
],
[
"javasc",
"Set Syntax: JavaScript"
],
[
"java",
"Project: Save As"
],
[
"markd",
"Set Syntax: Markdown"
],
[
"ins",
"Package Control: Install Package"
],
[
"htm",
"Set Syntax: HTML"
],
[
"spec",
"CSSpecific: Check specifity"
],
[
"css",
"Set Syntax: CSS"
],
[
"packag",
"Package Control: Remove Package"
],
[
"csscom",
"Sort via CSScomb"
],
[
"cssco",
"Sort via CSScomb"
],
[
"cssc",
"Sort via CSScomb"
],
[
"sort",
"Sort via CSScomb"
],
[
"comb",
"Sort via CSScomb"
],
[
"install",
"Package Control: Install Package"
],
[
"spe",
"CSSpecific: Check specifity"
],
[
"i",
"Package Control: Install Package"
],
[
"filenew",
"File: New View into File"
],
[
"pref",
"Preferences: Prefixr Key Bindings – Default"
],
[
"snipp",
"Snippet: CSS - clearfix"
],
[
"in",
"Package Control: Install Package"
],
[
"sni",
"Snippet: nav - Placeholder"
],
[
"side",
"View: Toggle Open Files in Side Bar"
],
[
"syntas",
"Set Syntax: Tasks"
],
[
"todo",
"Set Syntax: mdTodo"
],
[
"too",
"Todo: Add"
],
[
"instal",
"Package Control: Install Package"
]
],
"width": 386.0
},
"console":
{
"height": 133.0
},
"distraction_free":
{
"menu_visible": true,
"show_minimap": false,
"show_open_files": false,
"show_tabs": false,
"side_bar_visible": false,
"status_bar_visible": false
},
"file_history":
[
"/C/Users/rfessler/Documents/Dropbox/PSPadProjects/errordiv re-design/errordiv re-design project.sublime-project",
"/C/Users/rfessler/AppData/Roaming/Sublime Text 2/Packages/User/Preferences.sublime-settings",
"/C/Users/rfessler/Documents/Dropbox/Projects/storage/a.html",
"/C/Users/rfessler/Documents/Dropbox/Projects/storage/a.js",
"/C/Users/rfessler/Documents/Dropbox/Projects/storage/a.css",
"/D/_SearsClean Update Proj Originals/master.css",
"/D/_SearsClean Update Proj Originals/SearsCleanMaster.Master",
"/C/Users/rfessler/AppData/Roaming/Sublime Text 2/Packages/Default/Preferences.sublime-settings",
"/C/Users/rfessler/AppData/Local/Temp/SearsCleanMaster.Master",
"/D/update-customer.js",
"/D/address-info.js",
"/D/customerdetail phone number section.js",
"/C/Users/rfessler/AppData/Roaming/Sublime Text 2/Packages/Default/Default (Windows).sublime-keymap",
"/C/Users/rfessler/AppData/Roaming/Sublime Text 2/Packages/User/Default (Windows).sublime-keymap",
"/C/Windows/System32/drivers/etc/hosts",
"/D/temp2.js",
"/C/Users/rfessler/AppData/Roaming/Sublime Text 2/Packages/SublimePrint/SublimePrint.sublime-settings",
"/C/Users/rfessler/AppData/Roaming/Sublime Text 2/Packages/SublimePrint/SublimePrintSelection.py",
"/D/temp.html",
"/C/Users/rfessler/Documents/Dropbox/PSPadProjects/errordiv re-design/default.html",
"/C/Users/rfessler/AppData/Roaming/Sublime Text 2/Packages/ExportHtml/Default.sublime-commands",
"/C/Users/rfessler/AppData/Roaming/Sublime Text 2/Packages/ExportHtml/readme.md",
"/C/Users/rfessler/AppData/Roaming/Sublime Text 2/Packages/ExportHtml/ExportHtml.sublime-settings",
"/c/users/rfessler/appdata/local/temp/tmpo1dpls.html",
"/C/Users/rfessler/Documents/Visual Studio 2010/Projects/SearsClean/SearsClientAccessWeb/css/global - Copy.css",
"/C/Users/rfessler/Documents/Visual Studio 2010/Projects/SearsClean/SearsClientAccessWeb/css/global.css",
"/C/Users/rfessler/AppData/Roaming/Sublime Text 2/Packages/SublimePrint/SublimePrintSelection.pyc",
"/C/Users/rfessler/Documents/GitHub/Work/README_NOW.md",
"/C/Users/rfessler/Documents/GitHub/Work/README",
"/C/Users/rfessler/AppData/Roaming/Sublime Text 2/Packages/User/Firefox-preview.sublime-build",
"/C/temp/css/pretty-global.css",
"/C/Users/rfessler/AppData/Roaming/Sublime Text 2/Packages/CSScomb/Context.sublime-menu",
"/C/Users/rfessler/AppData/Roaming/Sublime Text 2/Packages/CSScomb/CSScomb.py",
"/C/Users/rfessler/AppData/Roaming/Sublime Text 2/Packages/CSScomb/CSScomb.sublime-commands",
"/C/Users/rfessler/AppData/Roaming/Sublime Text 2/Packages/CSScomb/Main.sublime-menu",
"/C/Users/rfessler/AppData/Roaming/Sublime Text 2/Packages/CSScomb/README.md",
"/C/Users/rfessler/AppData/Roaming/Sublime Text 2/Packages/Prefixr/Default (Windows).sublime-keymap",
"/C/temp/css/delimit.txt",
"/C/temp/css/combine2.bat",
"/C/temp/css/combine.bat",
"/C/temp/css/scaw.css",
"/C/Users/rfessler/AppData/Roaming/Sublime Text 2/Packages/CSS Snippets/README.md"
],
"find":
{
"height": 35.0
},
"find_in_files":
{
"height": 0.0,
"where_history":
[
""
]
},
"find_state":
{
"case_sensitive": false,
"find_history":
[
"~",
"[",
"\"numbers\": false,",
"\"numbers\": true",
"tr",
"/n",
" ",
"div",
"\"></",
"detect_slow",
"hide",
"/**",
"start",
"/**",
"START - css file seperator"
],
"highlight": true,
"in_selection": false,
"preserve_case": false,
"regex": false,
"replace_history":
[
"\"numbers\": true,",
"\"numbers\": false",
"\\n",
"/n"
],
"reverse": false,
"show_context": true,
"use_buffer2": true,
"whole_word": false,
"wrap": true
},
"groups":
[
{
"selected": 4,
"sheets":
[
{
"buffer": 0,
"settings":
{
"buffer_size": 183,
"regions":
{
},
"selection":
[
[
183,
183
]
],
"settings":
{
"gist_description": "storageExample using json",
"gist_filename": "a.css",
"gist_html_url": "https://gist.github.com/4511299",
"gist_url": "https://api.github.com/gists/4511299",
"syntax": "Packages/Text/Plain text.tmLanguage"
},
"translation.x": 0.0,
"translation.y": 0.0,
"zoom_level": 1.0
},
"type": "text"
},
{
"buffer": 1,
"settings":
{
"buffer_size": 755,
"regions":
{
},
"selection":
[
[
755,
755
]
],
"settings":
{
"gist_description": "storageExample using json",
"gist_filename": "a.html",
"gist_html_url": "https://gist.github.com/4511299",
"gist_url": "https://api.github.com/gists/4511299",
"syntax": "Packages/Text/Plain text.tmLanguage"
},
"translation.x": 0.0,
"translation.y": 0.0,
"zoom_level": 1.0
},
"type": "text"
},
{
"buffer": 2,
"settings":
{
"buffer_size": 1927,
"regions":
{
},
"selection":
[
[
235,
235
]
],
"settings":
{
"gist_description": "storageExample using json",
"gist_filename": "a.js",
"gist_html_url": "https://gist.github.com/4511299",
"gist_url": "https://api.github.com/gists/4511299",
"syntax": "Packages/Text/Plain text.tmLanguage"
},
"translation.x": 0.0,
"translation.y": 0.0,
"zoom_level": 1.0
},
"type": "text"
},
{
"buffer": 3,
"settings":
{
"buffer_size": 29752,
"regions":
{
},
"selection":
[
[
29752,
29752
]
],
"settings":
{
"gist_description": "storageExample using json",
"gist_filename": "jquery-jstorage.js",
"gist_html_url": "https://gist.github.com/4511299",
"gist_url": "https://api.github.com/gists/4511299",
"syntax": "Packages/Text/Plain text.tmLanguage"
},
"translation.x": 0.0,
"translation.y": 0.0,
"zoom_level": 1.0
},
"type": "text"
},
{
"buffer": 4,
"file": "a.html",
"settings":
{
"buffer_size": 755,
"regions":
{
},
"selection":
[
[
571,
571
]
],
"settings":
{
"syntax": "Packages/HTML/HTML.tmLanguage",
"tab_size": 4,
"translate_tabs_to_spaces": true
},
"translation.x": 0.0,
"translation.y": 0.0,
"zoom_level": 1.0
},
"type": "text"
}
]
}
],
"incremental_find":
{
"height": 35.0
},
"input":
{
"height": 31.0
},
"layout":
{
"cells":
[
[
0,
0,
1,
1
]
],
"cols":
[
0.0,
1.0
],
"rows":
[
0.0,
1.0
]
},
"menu_visible": true,
"output.csspecific":
{
"height": 124.0
},
"output.exec":
{
"height": 119.0
},
"replace":
{
"height": 64.0
},
"save_all_on_build": true,
"select_file":
{
"height": 0.0,
"selected_items":
[
],
"width": 0.0
},
"select_project":
{
"height": 500.0,
"selected_items":
[
[
"",
"/C/Users/rfessler/Documents/Dropbox/Projects/LeftNavUserControls/LeftNavigation.sublime-project"
]
],
"width": 380.0
},
"show_minimap": true,
"show_open_files": true,
"show_tabs": true,
"side_bar_visible": true,
"side_bar_width": 173.0,
"status_bar_visible": true
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment