/* =========================================================
LGT Campaign Bar (BALK 3) โ v2 (STICKY FIXED)
Loaded as
So this file MUST be valid JavaScript (even if extension is .html).
Behaviour:
- Height 30px, mobile-only
- Inserted AFTER black USP bar (.lgt-uspbar-top)
- Sticky logic:
* If USP clone (.lgt-uspbar-clone) is visible (opacity > 0.02) -> show fixed bar under it
* Else if scrollY >= 49 -> show fixed bar under white header
* Else -> show flow bar in-page
- Close: hides for 30 minutes (sessionStorage)
- If no active campaign -> bar does not exist (display none + css var 0)
========================================================= */
(function(){
"use strict";
var MQ = window.matchMedia && window.matchMedia("(max-width: 768px)");
function isMobile(){ return MQ ? MQ.matches : (window.innerWidth <= 768); }
// Some themes scroll inside a container (overflow:auto) instead of window.
// We detect the real scroller so sticky logic works everywhere.
var scroller = null;
var scrollIsWindow = true;
function pickScroller(){
var candidates = [
document.querySelector("main#maincontent"),
document.querySelector("main.page-main"),
document.querySelector(".page-wrapper"),
document.scrollingElement || document.documentElement
].filter(Boolean);
for (var i=0;i el.clientHeight + 2);
if (canScroll && tall){
scroller = el;
scrollIsWindow = false;
return;
}
}
scroller = window;
scrollIsWindow = true;
}
function getScrollTop(){
if (scrollIsWindow) return window.pageYOffset || 0;
return scroller ? (scroller.scrollTop || 0) : 0;
}
var CLOSE_KEY_UNTIL = "lgt_campaignbar_closed_until";
var CLOSE_MS = 30 * 60 * 1000;
// --------- Campaign data (edit here) ----------
// All CTAs go to /cadeautips as requested
// textHtml can contain emoji + simple inline SVG.
var campaigns = [
// TEST (today -> 1 June 2026)
{
id: "test",
start: "2026-02-27T00:00:00+01:00",
end: "2026-06-01T23:59:59+02:00",
bg: "#ffd1dc",
fg: "#333",
textHtml:
'๐งช Testbalk (' + (new Date()).toLocaleDateString("nl-NL") + '): ' +
'naar cadeautips'
},
// VALENTIJN (yearly)
{ id:"valentijn-2026", start:"2026-01-25T00:00:00+01:00", end:"2026-02-14T23:59:59+01:00", bg:"#ffd1dc", fg:"#333",
textHtml:'โค๏ธ Valentijnsactie โ cadeautips' },
{ id:"valentijn-2027", start:"2027-01-25T00:00:00+01:00", end:"2027-02-14T23:59:59+01:00", bg:"#ffd1dc", fg:"#333",
textHtml:'โค๏ธ Valentijnsactie โ cadeautips' },
{ id:"valentijn-2028", start:"2028-01-25T00:00:00+01:00", end:"2028-02-14T23:59:59+01:00", bg:"#ffd1dc", fg:"#333",
textHtml:'โค๏ธ Valentijnsactie โ cadeautips' },
// MOEDERDAG (NL: 2e zondag mei) โ show 3 weeks before through that day
{ id:"moederdag-2026", start:"2026-04-19T00:00:00+02:00", end:"2026-05-10T23:59:59+02:00", bg:"#ffe6f2", fg:"#333",
textHtml:'๐ท Moederdag cadeautips โ shop nu' },
{ id:"moederdag-2027", start:"2027-04-18T00:00:00+02:00", end:"2027-05-09T23:59:59+02:00", bg:"#ffe6f2", fg:"#333",
textHtml:'๐ท Moederdag cadeautips โ shop nu' },
{ id:"moederdag-2028", start:"2028-04-23T00:00:00+02:00", end:"2028-05-14T23:59:59+02:00", bg:"#ffe6f2", fg:"#333",
textHtml:'๐ท Moederdag cadeautips โ shop nu' },
// VADERDAG (NL: 3e zondag juni) โ show 3 weeks before through that day
{ id:"vaderdag-2026", start:"2026-05-24T00:00:00+02:00", end:"2026-06-21T23:59:59+02:00", bg:"#d9ecff", fg:"#0b2545",
textHtml:'๐ Vaderdag cadeautips โ shop nu' },
{ id:"vaderdag-2027", start:"2027-05-30T00:00:00+02:00", end:"2027-06-20T23:59:59+02:00", bg:"#d9ecff", fg:"#0b2545",
textHtml:'๐ Vaderdag cadeautips โ shop nu' },
{ id:"vaderdag-2028", start:"2028-05-28T00:00:00+02:00", end:"2028-06-18T23:59:59+02:00", bg:"#d9ecff", fg:"#0b2545",
textHtml:'๐ Vaderdag cadeautips โ shop nu' },
// BLACK FRIDAY (show 10 days up to BF, plus weekend through Cyber Monday)
{ id:"bf-2026", start:"2026-11-16T00:00:00+01:00", end:"2026-11-30T23:59:59+01:00", bg:"#111", fg:"#fff",
textHtml:'๐ฅ Black Friday deals โ bekijk acties' },
{ id:"bf-2027", start:"2027-11-15T00:00:00+01:00", end:"2027-11-29T23:59:59+01:00", bg:"#111", fg:"#fff",
textHtml:'๐ฅ Black Friday deals โ bekijk acties' },
{ id:"bf-2028", start:"2028-11-13T00:00:00+01:00", end:"2028-11-27T23:59:59+01:00", bg:"#111", fg:"#fff",
textHtml:'๐ฅ Black Friday deals โ bekijk acties' },
// SINTERKLAAS (but do NOT show during BF windows)
{ id:"sint-2026", start:"2026-11-12T00:00:00+01:00", end:"2026-12-05T23:59:59+01:00", bg:"#ffefc7", fg:"#5a2a00",
textHtml:'๐ Sinterklaas cadeautips โ bekijk tips' },
{ id:"sint-2027", start:"2027-11-10T00:00:00+01:00", end:"2027-12-05T23:59:59+01:00", bg:"#ffefc7", fg:"#5a2a00",
textHtml:'๐ Sinterklaas cadeautips โ bekijk tips' },
{ id:"sint-2028", start:"2028-11-10T00:00:00+01:00", end:"2028-12-05T23:59:59+01:00", bg:"#ffefc7", fg:"#5a2a00",
textHtml:'๐ Sinterklaas cadeautips โ bekijk tips' },
// KERST (starts Dec 6, ends Dec 31)
{ id:"kerst-2026", start:"2026-12-06T00:00:00+01:00", end:"2026-12-31T23:59:59+01:00", bg:"#0f3d2e", fg:"#fff",
textHtml:'๐ Kerst cadeautips โ shop kerst' },
{ id:"kerst-2027", start:"2027-12-06T00:00:00+01:00", end:"2027-12-31T23:59:59+01:00", bg:"#0f3d2e", fg:"#fff",
textHtml:'๐ Kerst cadeautips โ shop kerst' },
{ id:"kerst-2028", start:"2028-12-06T00:00:00+01:00", end:"2028-12-31T23:59:59+01:00", bg:"#0f3d2e", fg:"#fff",
textHtml:'๐ Kerst cadeautips โ shop kerst' },
// HAPPY NEW YEAR (Jan 1 - Jan 7)
{ id:"hny-2027", start:"2027-01-01T00:00:00+01:00", end:"2027-01-07T23:59:59+01:00", bg:"#e6f3ff", fg:"#0b2545",
textHtml:'โจ Happy New Year โ cadeautips' },
{ id:"hny-2028", start:"2028-01-01T00:00:00+01:00", end:"2028-01-07T23:59:59+01:00", bg:"#e6f3ff", fg:"#0b2545",
textHtml:'โจ Happy New Year โ cadeautips' },
{ id:"hny-2029", start:"2029-01-01T00:00:00+01:00", end:"2029-01-07T23:59:59+01:00", bg:"#e6f3ff", fg:"#0b2545",
textHtml:'โจ Happy New Year โ cadeautips' }
];
// Black Friday windows used to suppress Sinterklaas
var bfWindows = [
["2026-11-16T00:00:00+01:00","2026-11-30T23:59:59+01:00"],
["2027-11-15T00:00:00+01:00","2027-11-29T23:59:59+01:00"],
["2028-11-13T00:00:00+01:00","2028-11-27T23:59:59+01:00"]
];
// --------- helpers ----------
function nowMs(){ return Date.now(); }
function setCssVarHeight(px){
try{ document.documentElement.style.setProperty("--lgt-campaignbar-h", px + "px"); }catch(e){}
}
function getClosedUntil(){
try{
var v = sessionStorage.getItem(CLOSE_KEY_UNTIL);
return v ? parseInt(v,10) : 0;
}catch(e){ return 0; }
}
function isClosed(){
var until = getClosedUntil();
return until && nowMs() < until;
}
function closeFor30Min(){
try{ sessionStorage.setItem(CLOSE_KEY_UNTIL, String(nowMs() + CLOSE_MS)); }catch(e){}
}
function inWindow(startIso, endIso){
var t = nowMs();
var s = new Date(startIso).getTime();
var e = new Date(endIso).getTime();
return (t >= s && t <= e);
}
function isInBlackFridayWindow(){
for (var i=0;i 0 ? h : 56;
}
function getUspStickyOffset(){
// If the black sticky clone is visible, campaign bar must sit UNDER it.
var uspClone = document.querySelector(".lgt-uspbar-clone");
if (!uspClone) return 0;
var cs = window.getComputedStyle(uspClone);
var op = parseFloat(cs.opacity || "0") || 0;
if (op > 0.02) return 49;
return 0;
}
function uspCloneVisible(){
var uspClone = document.querySelector(".lgt-uspbar-clone");
if (!uspClone) return false;
var cs = getComputedStyle(uspClone);
var op = parseFloat(cs.opacity || "0") || 0;
return op > 0.02;
}
function buildBar(id){
var el = document.createElement("div");
el.id = id;
el.innerHTML =
'' +
'';
return el;
}
var flowBar = null;
var fixedBar = null;
var active = null;
var raf = 0;
function ensureBars(){
ensureStyle();
if (!flowBar) flowBar = document.getElementById("header-specialday-bar") || buildBar("header-specialday-bar");
if (!fixedBar) {
fixedBar = document.getElementById("header-specialday-bar-fixed") || buildBar("header-specialday-bar-fixed");
if (!fixedBar.isConnected) document.body.appendChild(fixedBar);
}
}
function applyCampaign(c){
ensureBars();
if (!c){
active = null;
setCssVarHeight(0);
flowBar.style.display = "none";
fixedBar.style.display = "none";
return;
}
active = c;
setCssVarHeight(30);
flowBar.style.background = c.bg || "#ffd1dc";
flowBar.style.color = c.fg || "#333";
fixedBar.style.background = c.bg || "#ffd1dc";
fixedBar.style.color = c.fg || "#333";
flowBar.querySelector(".lgt-specialday-text").innerHTML = c.textHtml || "";
fixedBar.querySelector(".lgt-specialday-text").innerHTML = c.textHtml || "";
// insert flowBar after usp top if possible
var uspTop = document.querySelector(".lgt-uspbar-top");
if (uspTop && uspTop.parentNode){
uspTop.insertAdjacentElement("afterend", flowBar);
} else {
var header = document.querySelector("header.page-header") || document.querySelector(".page-header") || document.querySelector("header");
if (header) header.insertAdjacentElement("afterend", flowBar);
}
// reset display states; updatePosition() decides fixed/flow
flowBar.style.display = "flex";
fixedBar.style.display = "none";
if (isClosed()){
flowBar.classList.add("is-hidden");
fixedBar.classList.add("is-hidden");
} else {
flowBar.classList.remove("is-hidden");
fixedBar.classList.remove("is-hidden");
}
}
function updatePosition(){
if (!active) return;
if (!isMobile()){
fixedBar.style.display = "none";
return;
}
if (isClosed()){
flowBar.classList.add("is-hidden");
fixedBar.classList.add("is-hidden");
} else {
flowBar.classList.remove("is-hidden");
fixedBar.classList.remove("is-hidden");
}
var y = getScrollTop();
var headerH = getHeaderH();
if (uspCloneVisible()){
fixedBar.style.top = "calc(" + headerH + "px + 49px)";
fixedBar.style.display = "flex";
flowBar.classList.add("is-hidden"); // no layout shift
return;
}
if (y >= 49){
fixedBar.style.top = (headerH + getUspStickyOffset()) + "px";
fixedBar.style.display = "flex";
flowBar.classList.add("is-hidden");
return;
}
fixedBar.style.display = "none";
flowBar.classList.remove("is-hidden");
}
function onScroll(){
if (raf) return;
raf = requestAnimationFrame(function(){
raf = 0;
updatePosition();
});
}
function bindClose(){
document.addEventListener("click", function(e){
var btn = e.target.closest && e.target.closest("#header-specialday-bar .lgt-specialday-close, #header-specialday-bar-fixed .lgt-specialday-close");
if (!btn) return;
e.preventDefault();
e.stopPropagation();
closeFor30Min();
if (flowBar) flowBar.classList.add("is-hidden");
if (fixedBar) fixedBar.classList.add("is-hidden");
// if user stays on page, auto-restore after 30m
setTimeout(function(){
if (!isClosed()) updatePosition();
}, CLOSE_MS + 50);
}, true);
}
function boot(){
pickScroller();
// Desktop: show the flow bar (no fixed/sticky needed)
if (!isMobile()){
ensureBars();
bindClose();
activeCampaignInit();
return;
}
ensureBars();
bindClose();
// Wait a bit for USP bar injection script to run (it creates .lgt-uspbar-top)
var stopAt = Date.now() + 4000;
(function waitForUsp(){
var uspTop = document.querySelector(".lgt-uspbar-top");
if (uspTop || Date.now() > stopAt){
activeCampaignInit();
return;
}
setTimeout(waitForUsp, 60);
})();
}
function activeCampaignInit(){
var c = pickActiveCampaign();
applyCampaign(c);
updatePosition();
if (scrollIsWindow) if (scrollIsWindow) window.addEventListener("scroll", onScroll, {passive:true});
else if (scroller) scroller.addEventListener("scroll", onScroll, {passive:true});
else if (scroller) scroller.addEventListener("scroll", onScroll, {passive:true});
window.addEventListener("resize", onScroll, {passive:true});
}
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", boot);
else boot();
}
)();