Skip to content

Instantly share code, notes, and snippets.

@zbinlin
Last active December 7, 2016 03:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zbinlin/f6fe2a6ffe401b90736c38058f7a306e to your computer and use it in GitHub Desktop.
Save zbinlin/f6fe2a6ffe401b90736c38058f7a306e to your computer and use it in GitHub Desktop.
shared session storage
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<button onclick="changeColor()">Change Color</button>
<script src="./shared-session-storage.js"></script>
<script>
function changeColor() {
var r = Math.floor(Math.random() * 256);
var g = Math.floor(Math.random() * 256);
var b = Math.floor(Math.random() * 256);
var color = "rgb(" + [r, g, b].join(", ") + ")";
window.sharedSessionStorage.setItem("color", color);
}
var oldColor;
var intervalId = setInterval(function () {
var color = sharedSessionStorage.getItem("color");
if (oldColor !== color) {
document.body.style.backgroundColor = color;
oldColor = color;
}
}, 40);
</script>
</body>
</html>
"use strict";
;(function (global) {
var ACTION_REQUEST = "REQUEST";
var ACTION_RESPONSE = "RESPONSE";
var ACTION_PUSH = "PUSH";
function SharedSessionStorage() {
this.__prefixKey__ = "##shared-session-storage##";
global.addEventListener("storage", this, true);
global.addEventListener("unload", this, true);
var SESSION_ID_KEY = "__shared-session-storage__session-id-key__";
var sessionId = global.sessionStorage.getItem(SESSION_ID_KEY);
if (sessionId === null) {
sessionId = "ID#" + Math.floor(Math.random() * 1e6) + "$";
global.sessionStorage.setItem(SESSION_ID_KEY, sessionId);
}
this.sessionId = sessionId;
this.LOCAL_SESSION_KEYS = "__local-storage__session-keys__";
this.SYNC_SHARED_SESSION_STORAGE_KEY = "__local-storage__sync-shared-session_storage-key__";
var keys = global.localStorage.getItem(this.LOCAL_SESSION_KEYS);
if (keys) {
if (keys.indexOf(sessionId) > -1) {
keys = keys.replace(sessionId, "");
}
if (keys) {
var idx = keys.indexOf("$");
if (idx === -1) {
idx = keys.length;
} else {
idx += 1;
}
var targetId = keys.slice(0, idx);
this.__sync__({
action: ACTION_REQUEST,
originalId: this.sessionId,
targetId: targetId,
});
}
keys += this.sessionId;
} else {
keys = this.sessionId;
}
global.localStorage.setItem(this.LOCAL_SESSION_KEYS, keys);
}
SharedSessionStorage.prototype.__sync__ = function sync(data) {
global.localStorage.setItem(this.SYNC_SHARED_SESSION_STORAGE_KEY, JSON.stringify(data));
global.localStorage.removeItem(this.SYNC_SHARED_SESSION_STORAGE_KEY);
};
SharedSessionStorage.prototype.handleEvent = function handleEvent(evt) {
switch (evt.type) {
case "storage":
return this.__handleStorage__(evt);
case "unload":
global.removeEventListener("storage", this, true);
global.removeEventListener("unload", this, true);
return this.__handleUnload__(evt);
}
};
SharedSessionStorage.prototype.__handleStorage__ = function handleStorage(evt) {
var key = evt.key;
var newValue = evt.newValue;
if (key !== this.SYNC_SHARED_SESSION_STORAGE_KEY || newValue == null) {
return;
}
var obj = JSON.parse(newValue);
switch (obj.action) {
case ACTION_REQUEST:
if (obj.targetId === this.sessionId) {
var data = this.entries();
this.__sync__({
action: ACTION_RESPONSE,
targetId: obj.originalId,
originalId: obj.targetId,
data: data,
});
}
break;
case ACTION_RESPONSE:
if (obj.targetId === this.sessionId) {
this.setAllItem(obj.data);
}
break;
case ACTION_PUSH:
if (obj.originalId !== this.sessionId) {
this.setAllItem(obj.data);
}
break;
}
};
SharedSessionStorage.prototype.__handleUnload__ = function handleUnload(evt) {
var keys = global.localStorage.getItem(this.LOCAL_SESSION_KEYS);
if (keys == null) {
return;
}
keys = keys.replace(this.sessionId, "");
if (keys.length === 0) {
global.localStorage.removeItem(this.LOCAL_SESSION_KEYS);
} else {
global.localStorage.setItem(this.LOCAL_SESSION_KEYS, keys);
}
};
SharedSessionStorage.prototype.__wrapKey__ = function wrapKey(key) {
return this.__prefixKey__ + key;
};
SharedSessionStorage.prototype.__unwrapKey__ = function wrapKey(key) {
if (this.__hasWrappedKey__(key)) {
return key.slice(this.__prefixKey__.length);
} else {
return key;
}
};
SharedSessionStorage.prototype.__hasWrappedKey__ = function hasWrapped(key) {
return key.indexOf(this.__prefixKey__) > -1;
};
SharedSessionStorage.prototype.keys = function keys(iter) {
var keys = [];
var length = global.sessionStorage.length;
for (var i = 0; i < length; i++) {
var key = global.sessionStorage.key(i);
if (this.__hasWrappedKey__(key)) {
keys.push(this.__unwrapKey__(key));
}
}
return keys;
};
SharedSessionStorage.prototype.entries = function entries() {
var keys = this.keys();
var items = [];
for (var i = 0, len = keys.length; i < len; i++) {
var key = keys[i];
items.push([key, this.getItem(key)]);
}
return items;
};
SharedSessionStorage.prototype.setAllItem = function setAllItem(iter) {
for (var i = 0, len = iter.length; i < len; i++) {
var ary = iter[i];
var key = this.__wrapKey__(ary[0]);
var val = ary[1];
if (val == null) {
global.sessionStorage.removeItem(key);
} else {
global.sessionStorage.setItem(key, val);
}
}
};
SharedSessionStorage.prototype.getItem = function getItem(key) {
return global.sessionStorage.getItem(this.__wrapKey__(key));
};
SharedSessionStorage.prototype.setItem = function setItem(key, val) {
var ret = global.sessionStorage.setItem(this.__wrapKey__(key), val);
this.__sync__({
action: ACTION_PUSH,
originalId: this.sessionId,
data: [[key, String(val)]],
});
return ret;
};
SharedSessionStorage.prototype.removeItem = function removeItem(key) {
var ret = global.sessionStorage.removeItem(this.__wrapKey__(key));
this.__sync__({
action: ACTION_PUSH,
originalId: this.sessionId,
data: [[key, null]],
});
return ret;
};
SharedSessionStorage.prototype.key = function key(idx) {
var keys = [];
var length = global.sessionStorage.length;
for (var i = 0; i < length; i++) {
var key = global.sessionStorage.key(i);
if (this.__hasWrappedKey__(key)) {
keys.push(this.__unwrapKey__(key));
if (keys.length - 1 === idx) {
return keys[keys.length - 1];
}
}
}
};
SharedSessionStorage.prototype.clear = function clear() {
var keys = this.keys();
var items = [];
for (var i = 0, len = keys.length; i < len; i++) {
var key = keys[i];
global.sessionStorage.removeItem(this.__wrapKey__(key));
items.push([key, null]);
}
this.__sync__({
action: ACTION_PUSH,
originalId: this.sessionId,
data: items,
});
};
Object.defineProperty(SharedSessionStorage.prototype, "length", {
get() {
var count = 0;
var length = global.sessionStorage.length;
for (var i = 0; i < length; i++) {
var key = global.sessionStorage.key(i);
if (this.__hasWrappedKey__(key)) {
count += 1;
}
}
return count;
},
});
var sharedSessionStorage = new SharedSessionStorage();
global.sharedSessionStorage = sharedSessionStorage;
})(window);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment