Created
February 13, 2021 11:52
-
-
Save kachar/b04e2b13b1419a0e6cc6fa0fda69f50d to your computer and use it in GitHub Desktop.
cross-domain-local-storage ES6
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
/** | |
* Created by dagan on 07/04/2014. | |
* https://github.com/ofirdagan/cross-domain-local-storage | |
*/ | |
const MESSAGE_NAMESPACE = "cross-domain-local-message"; | |
/* global console */ | |
export const xdLocalStorage = () => { | |
const requests = {}; | |
let options = { | |
iframeId: "cross-domain-iframe", | |
iframeUrl: undefined, | |
initCallback: () => {}, | |
}; | |
let requestId = -1; | |
let iframe; | |
let wasInit = false; | |
let iframeReady = true; | |
const applyCallback = (data) => { | |
if (requests[data.id]) { | |
requests[data.id](data); | |
delete requests[data.id]; | |
} | |
}; | |
const receiveMessage = (event) => { | |
const { data, origin } = event; | |
if (origin !== window.origin) { | |
return; | |
} | |
console.debug("XD: receiveMessage1", event, origin); | |
if (data && data.namespace === MESSAGE_NAMESPACE) { | |
if (data.id === "iframe-ready") { | |
iframeReady = true; | |
options.initCallback(); | |
} else { | |
applyCallback(data); | |
} | |
} | |
}; | |
const buildMessage = (action, key, value, callback) => { | |
console.debug("XD: buildMessage", action, key, value, callback); | |
requestId++; | |
requests[requestId] = callback; | |
const data = { | |
namespace: MESSAGE_NAMESPACE, | |
id: requestId, | |
action, | |
key, | |
value, | |
}; | |
iframe.contentWindow.postMessage(data, "*"); | |
}; | |
const init = (customOptions) => { | |
options = { ...options, ...customOptions }; | |
if (window.addEventListener) { | |
window.addEventListener("message", receiveMessage, false); | |
} else { | |
window.attachEvent("onmessage", receiveMessage); | |
} | |
const temp = document.createElement("div"); | |
temp.innerHTML = `<iframe id="${options.iframeId}" src="${options.iframeUrl}" style="display: none;"></iframe>`; | |
document.body.appendChild(temp); | |
iframe = document.getElementById(options.iframeId); | |
}; | |
const isApiReady = () => { | |
if (!wasInit) { | |
console.log("You must call xdLocalStorage.init() before using it."); | |
return false; | |
} | |
if (!iframeReady) { | |
console.log( | |
"You must wait for iframe ready message before using the api." | |
); | |
return false; | |
} | |
return true; | |
}; | |
const isDomReady = () => document.readyState === "complete"; | |
return { | |
//callback is optional for cases you use the api before window load. | |
init: (customOptions) => { | |
if (!customOptions.iframeUrl) { | |
throw new Error("You must specify iframeUrl"); | |
} | |
if (wasInit) { | |
console.log("xdLocalStorage was already initialized!"); | |
return; | |
} | |
wasInit = true; | |
if (isDomReady()) { | |
init(customOptions); | |
} else { | |
if (document.addEventListener) { | |
// All browsers expect IE < 9 | |
document.addEventListener("readystatechange", () => { | |
if (isDomReady()) { | |
init(customOptions); | |
} | |
}); | |
} else { | |
// IE < 9 | |
document.attachEvent("readystatechange", () => { | |
if (isDomReady()) { | |
init(customOptions); | |
} | |
}); | |
} | |
} | |
}, | |
setItem: (key, value, callback) => { | |
if (!isApiReady()) { | |
return; | |
} | |
buildMessage("set", key, value, callback); | |
}, | |
getItem: (key, callback) => { | |
if (!isApiReady()) { | |
return; | |
} | |
buildMessage("get", key, null, callback); | |
}, | |
removeItem: (key, callback) => { | |
if (!isApiReady()) { | |
return; | |
} | |
buildMessage("remove", key, null, callback); | |
}, | |
key: (index, callback) => { | |
if (!isApiReady()) { | |
return; | |
} | |
buildMessage("key", index, null, callback); | |
}, | |
getSize: (callback) => { | |
if (!isApiReady()) { | |
return; | |
} | |
buildMessage("size", null, null, callback); | |
}, | |
getLength: (callback) => { | |
if (!isApiReady()) { | |
return; | |
} | |
buildMessage("length", null, null, callback); | |
}, | |
clear: (callback) => { | |
if (!isApiReady()) { | |
return; | |
} | |
buildMessage("clear", null, null, callback); | |
}, | |
wasInit: () => wasInit, | |
}; | |
}; | |
export default xdLocalStorage; | |
export const xdLocalStoragePostMessageApi = () => { | |
const defaultData = { namespace: MESSAGE_NAMESPACE }; | |
const postData = (id, data) => { | |
const mergedData = { ...defaultData, id, ...data }; | |
window.parent.postMessage(mergedData, "*"); | |
}; | |
const getData = (id, key) => { | |
const value = localStorage.getItem(key); | |
postData(id, { key, value }); | |
}; | |
const setData = (id, key, value) => { | |
localStorage.setItem(key, value); | |
const checkGet = localStorage.getItem(key); | |
postData(id, { success: checkGet === value }); | |
}; | |
const removeData = (id, key) => { | |
localStorage.removeItem(key); | |
postData(id, {}); | |
}; | |
const getKey = (id, index) => { | |
const key = localStorage.key(index); | |
postData(id, { key }); | |
}; | |
const getSize = (id) => { | |
const size = JSON.stringify(localStorage).length; | |
postData(id, { size }); | |
}; | |
const getLength = (id) => { | |
const length = localStorage.length; | |
postData(id, { length }); | |
}; | |
const clear = (id) => { | |
localStorage.clear(); | |
postData(id, {}); | |
}; | |
const receiveMessage = (event) => { | |
const { data } = event; | |
console.debug("XD: receiveMessage20", event); | |
if (data && data.namespace === MESSAGE_NAMESPACE) { | |
if (data.action === "set") { | |
setData(data.id, data.key, data.value); | |
} else if (data.action === "get") { | |
getData(data.id, data.key); | |
} else if (data.action === "remove") { | |
removeData(data.id, data.key); | |
} else if (data.action === "key") { | |
getKey(data.id, data.key); | |
} else if (data.action === "size") { | |
getSize(data.id); | |
} else if (data.action === "length") { | |
getLength(data.id); | |
} else if (data.action === "clear") { | |
clear(data.id); | |
} | |
} | |
}; | |
if (window.addEventListener) { | |
window.addEventListener("message", receiveMessage, false); | |
} else { | |
window.attachEvent("onmessage", receiveMessage); | |
} | |
const sendOnLoad = () => { | |
console.debug("XD: sendOnLoad"); | |
const data = { | |
namespace: MESSAGE_NAMESPACE, | |
id: "iframe-ready", | |
}; | |
window.parent.postMessage(data, "*"); | |
}; | |
//on creation | |
sendOnLoad(); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment