(() => { function guessAbiskoProject() { if (window.__ABISKO__ && window.__ABISKO__.getAllocations) { const allocations = window.__ABISKO__.getAllocations(); if (allocations.length > 0) { return allocations[0].projectId; } } if (window.location.href.includes("svt.se/barnkanalen")) { return "barnplay"; } else if (window.location.href.includes("motherbrain")) { return "motherbrain"; } else if (window.location.href.includes("svtbarn")) { return "barnplay"; } else if (window.location.href.includes("svtplaywebb")) { return "svtplay"; } else if (window.location.href.includes("web-examples.abisko")) { return "team_abisko"; } else if (window.location.href.includes("localhost")) { return "team_abisko"; } else if (window.location.href.includes("svt.se")) { return "nyheter"; } return "svtplay"; } function getCookieDomain() { const hostname = window.location.hostname; if (hostname === "localhost") { return hostname; } const topLevelDomain = "." + hostname.split(".").slice(-2).join("."); return topLevelDomain; } function isStageEnvironment() { if ( window.location.href.includes("dev.borealis.svt.se") || window.location.href.includes("dev.kn.svt.se") || window.location.href.includes("dev.e.svt.se") || window.location.href.includes("dev.aurora.svt.se") || window.location.href.includes("stage.svtplay.se") || window.location.href.includes("stage.svtbarn.se") || window.location.href.includes("localhost") ) { return true; } return false; } function guessAbiskoUrl(abiskoProject) { if (isStageEnvironment()) { return `https://api.stage.svt.se/abisko/public/experiments/${abiskoProject}/web`; } return `https://api.svt.se/abisko/public/experiments/${abiskoProject}/web`; } const PREVIEW_SESSION_STORAGE_KEY = "abisko-previewed-variants"; const ABISKO_PROJECT = guessAbiskoProject(); const ABISKO_URL = guessAbiskoUrl(ABISKO_PROJECT); function createCss() { const styles = ` #abiskoPopup { position:fixed; top:10px; left:10px; z-index:100000; background-color:#FFF; padding:20px; min-width: 400px; border: 2px solid #ddd; overflow: scroll; max-height: 90%; } .abiskoHeading { background-color:rgb(23, 26, 26); color:#FFF; padding:5px; font-weight: 400; } .experiments { padding:5px; } .experimentName { margin-top:10px; margin-bottom: 0; color: #000; font-size: 22px; text-transform: uppercase; } .variantInput { display:none; } .variantLabel { color:#000; display:block; font-size:20px; cursor:pointer; } .variantInput:checked + label { color: #fc4e7e; font-weight: 800; cursor:unset; } .okButton { background-color: #fc4e7e; border: 2px solid #fc4e7e; color: white; font-weight: 800; border-radius: 7px; margin-top:20px; padding: 5px 30px; } .okButton:hover { background-color: white; color: #fc4e7e; } .cancelButton { background-color: #bbb; border: 2px solid #bbb; color: white; font-weight: 800; color: white; border-radius: 7px; margin-top:20px; margin-left: 10px; padding: 5px 10px; } .cancelButton:hover { background-color: white; color: #bbb; } #deprecationMessage { background-color:rgb(248, 23, 23); color: white; font-weight: 800; font-size: 20px; margin-bottom: 10px; padding: 5px; } #deprecationMessage a { color: white; } `; const styleSheet = document.createElement("style"); styleSheet.innerText = styles; return styleSheet; } function getCookieName() { const cookieName = `svt-abisko-${ABISKO_PROJECT}-experiments`; if (isStageEnvironment()) { return `stage-${cookieName}`; } return cookieName; } async function getAbiskoExperiments() { const response = await fetch(ABISKO_URL); const body = await response.json(); return body.activeExperiments.filter( (item) => item.experimentState === "RUNNING" ); } function parseSelectedVariants(cookieValue) { try { const experiments = decodeURIComponent(cookieValue) .split(";")[1] .split(","); return experiments.reduce((acc, experiment) => { const [experimentId, variantId] = experiment.split(":"); return (acc[experimentId] = variantId), acc; }, {}); } catch (e) { console.log("could not parse cookie value: ", cookieValue); return []; } } function getCookie() { const cookieName = getCookieName(); try { const cookieValue = document.cookie .split("; ") .find((row) => row.startsWith(`${cookieName}=`)) .split("=")[1]; return parseSelectedVariants(cookieValue); } catch (e) { throw Error(`Could not find cookie ${cookieName}`); } } function createVariantInput(experimentId, variantId, selected) { const el = document.createElement("input"); el.setAttribute("type", "radio"); el.setAttribute("id", `${experimentId}-${variantId}`); el.setAttribute("name", experimentId); el.setAttribute("value", variantId); el.className = "variantInput"; if (selected) { el.checked = true; } return el; } function getExperimentsFromSessionStorage() { return ( JSON.parse(sessionStorage.getItem(PREVIEW_SESSION_STORAGE_KEY)) || {} ); } function createLabel(experimentId, variantId) { const el = document.createElement("label"); el.setAttribute("for", `${experimentId}-${variantId}`); el.textContent = variantId; el.className = "variantLabel"; return el; } function createExperimentHeading(experimentId) { const el = document.createElement("h2"); el.textContent = experimentId; return el; } function getSelectedVariants() { const checkedInputs = Array.from( document.querySelectorAll(".variantInput:checked") ); return checkedInputs.reduce((acc, inputElement) => { return (acc[inputElement.name] = inputElement.value), acc; }, {}); } function buildCookieString(selectedVariants) { const variantStrings = Object.keys(selectedVariants).map((experiment) => { return `${experiment}:${selectedVariants[experiment]}`; }); const cookieString = `${ABISKO_PROJECT};${variantStrings.join(",")}`; return encodeURIComponent(cookieString); } function saveCookie(selectedVariants) { document.cookie = `${getCookieName()}=${buildCookieString( selectedVariants )};path=/;max-age=31536000;SameSite=Lax;domain=${getCookieDomain()}`; } function saveSessionStorage(selectedVariants) { sessionStorage.setItem( PREVIEW_SESSION_STORAGE_KEY, JSON.stringify(selectedVariants) ); } function isSelected(experimentId, variantId, experimentsFromCookie) { return experimentsFromCookie[experimentId] === variantId; } function createExperimentsSection(experiments, experimentsFromCookie) { const experimentsSection = document.createElement("section"); experimentsSection.className = "experiments"; if (experiments.length === 0) { const heading = createExperimentHeading( "Currently no active experiments" ); heading.className = "experimentName"; experimentsSection.appendChild(heading); } experiments.forEach((experiment) => { const heading = createExperimentHeading(experiment.id); heading.className = "experimentName"; experimentsSection.appendChild(heading); experiment.activeVariants.forEach((variant) => { const selected = isSelected( experiment.id, variant.id, experimentsFromCookie ); const variantInput = createVariantInput( experiment.id, variant.id, selected ); experimentsSection.appendChild(variantInput); const label = createLabel(experiment.id, variant.id); experimentsSection.appendChild(label); }); }); return experimentsSection; } function onOk() { const selectedVariants = getSelectedVariants(); saveCookie(selectedVariants); saveSessionStorage(selectedVariants); location.reload(); } function closePopup() { const abiskoPopup = document.getElementById("abiskoPopup"); abiskoPopup.remove(); } function closeOnEscape() { document.addEventListener("keydown", (e) => { if (e.key === "Escape") { closePopup(); } }); } function renderPopup(experiments) { const experimentsFromCookie = getCookie(); const experimentsFromSessionStorage = getExperimentsFromSessionStorage(); const storedExperiments = { ...experimentsFromCookie, ...experimentsFromSessionStorage, }; const popup = document.createElement("div"); popup.id = "abiskoPopup"; const styles = createCss(); popup.appendChild(styles); const deprecationHeading = document.createElement("h2"); deprecationHeading.textContent = "⚠️ This bookmarklet is outdated"; const deprecationText = document.createElement("p"); deprecationText.innerHTML = 'Go to https://abisko.svt.se/docs to get the latest version'; const deprecationMessage = document.createElement("div"); deprecationMessage.id = "deprecationMessage"; deprecationMessage.appendChild(deprecationHeading); deprecationMessage.appendChild(deprecationText); popup.appendChild(deprecationMessage); const h1 = document.createElement("h1"); h1.className = "abiskoHeading"; h1.textContent = "a/bisko"; popup.appendChild(h1); const experimentsSection = createExperimentsSection( experiments, storedExperiments ); popup.appendChild(experimentsSection); const okButton = document.createElement("button"); okButton.textContent = "OK"; okButton.className = "okButton"; okButton.onclick = onOk; popup.appendChild(okButton); const cancelButton = document.createElement("button"); cancelButton.textContent = "Cancel"; cancelButton.className = "cancelButton"; cancelButton.onclick = closePopup; popup.appendChild(cancelButton); document.body.appendChild(popup); } function main() { getAbiskoExperiments().then((activeExperiments) => { activeExperiments.sort((a, b) => a.id.localeCompare(b.id)); renderPopup(activeExperiments); }); closeOnEscape(); } main(); })();