Instantly share code, notes, and snippets.
Last active
December 7, 2016 03:16
-
Star
0
(0)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
Save zbinlin/f6fe2a6ffe401b90736c38058f7a306e to your computer and use it in GitHub Desktop.
shared session storage
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
<!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> |
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
"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