oqtane.framework/Oqtane.Server/wwwroot/js/reload.js
2024-12-18 10:09:02 -05:00

88 lines
2.5 KiB
JavaScript

const scriptInfoBySrc = new Map();
function getKey(script) {
if (script.hasAttribute("src") && script.src !== "") {
return script.src;
} else {
return script.innerHTML;
}
}
export function onUpdate() {
let timestamp = Date.now();
let enhancedNavigation = scriptInfoBySrc.size !== 0;
// iterate over all script elements in page
const scripts = document.getElementsByTagName("script");
for (const script of scripts) {
let key = getKey(script);
let scriptInfo = scriptInfoBySrc.get(key);
if (!scriptInfo) {
// new script added
scriptInfo = { timestamp: timestamp };
scriptInfoBySrc.set(key, scriptInfo);
if (enhancedNavigation) {
reloadScript(script);
}
} else {
// existing script
scriptInfo.timestamp = timestamp;
if (script.hasAttribute("data-reload") && script.getAttribute("data-reload") === "true") {
reloadScript(script);
}
}
}
// remove scripts that are no longer referenced
for (const [key, scriptInfo] of scriptInfoBySrc) {
if (scriptInfo.timestamp !== timestamp) {
scriptInfoBySrc.delete(key);
}
}
}
function reloadScript(script) {
try {
replaceScript(script);
} catch (error) {
if (script.hasAttribute("src") && script.src !== "") {
console.error("Failed to load external script: ${script.src}", error);
} else {
console.error("Failed to load inline script: ${script.innerHtml}", error);
}
}
}
function replaceScript(script) {
return new Promise((resolve, reject) => {
var newScript = document.createElement("script");
newScript.async = false;
if (script.type !== "") {
newScript.type = script.type;
}
if (script.src !== "") {
newScript.src = script.src;
if (script.integrity !== "") {
newScript.integrity = script.integrity;
}
if (script.crossorigin !== "") {
newScript.crossOrigin = script.crossOrigin;
}
} else {
newScript.innerHTML = script.innerHTML;
}
newScript.onload = () => resolve();
newScript.onerror = (error) => reject(error);
// remove existing newScript script
script.remove();
// replace with new newScript to force reload in Blazor
document.head.appendChild(newScript);
});
}