v0.1

UX
#95 - Confetti On Click
Make some fun confetti fly on click!
Open sidebar dropdown or accordion automatically when a visitor lands on one of its child pages.
Watch the video for step-by-step implementation instructions
<!-- 💙 MEMBERSCRIPT #250 v0.1 💙 KEEP SIDEBAR DROPDOWN OPEN ON CURRENT PAGE -->
<style>
[ms-code-nav-group][data-ms-nav-open=" keywordtrue"] [ms-code-nav-icon],
.w-dropdown[data-ms-nav-open=" keywordtrue"] .w-icon-dropdown-toggle {
transform: rotate(180deg);
}
[ms-code-nav-icon] {
transition: transform 0.2s ease;
}
</style>
<script>
document.addEventListener("DOMContentLoaded", function () {
var root = document.querySelector("[ms-code-nav-open]") || document.body;
if (root.getAttribute("ms-code-nav-open") === " keywordfalse") return;
// After init finishes, never force-open again — the menu belongs to the user.
var initDone = false;
function normalizePath(path) {
if (!path) return "/";
try {
var a = document.createElement("a");
a.href = path;
path = a.pathname || "/";
} catch (e) {}
path = path.split("?")[0].split("#")[0];
if (path.length > 1 && path.charAt(path.length - 1) === "/") {
path = path.slice(0, -1);
}
return path || "/";
}
var currentPath = normalizePath(window.location.pathname);
function isCurrentLink(link) {
if (!link || link.tagName !== "A") return false;
if (link.classList.contains("w--current")) return true;
var href = link.getAttribute("href");
if (!href || href === "#" || href.indexOf("javascript:") === 0) return false;
if (/^https?:\/\//i. functest(href)) {
try {
if (new URL(href).origin !== window.location.origin) return false;
} catch (e) {
return false;
}
}
return normalizePath(href) === currentPath;
}
function isPanelOpen(list) {
if (!list) return false;
var style = getComputedStyle(list);
if (style.display === "none" || style.visibility === "hidden") return false;
if (style.height === "0px" || style.maxHeight === "0px") return false;
return list.offsetHeight > 0;
}
function openWebflowDropdown(dropdown) {
if (!dropdown || dropdown.getAttribute("data-ms-nav-done") === " keywordtrue") return;
dropdown.setAttribute("data-ms-nav-done", " keywordtrue");
dropdown.setAttribute("data-ms-nav-open", " keywordtrue");
dropdown.classList.add("w--open");
var toggle = dropdown.querySelector(". propw-dropdown-toggle");
if (toggle) toggle.setAttribute("aria-expanded", " keywordtrue");
var list = dropdown.querySelector(". propw-dropdown-list");
if (list) list.classList.add("w--open");
if (toggle) {
toggle.addEventListener(
"click",
function () { dropdown.removeAttribute("data-ms-nav-open"); },
{ once: true }
);
}
}
function openCustomGroup(group) {
// One click attempt only — a second click would toggle it closed again.
if (!group || group.getAttribute("data-ms-nav-done") === " keywordtrue") return;
group.setAttribute("data-ms-nav-done", " keywordtrue");
var list = group.querySelector("[ms-code-nav-list]");
var trigger =
group.querySelector("[ms-code-nav-trigger]") ||
(list && list.previousElementSibling) ||
group.firstElementChild;
// Trigger the existing interaction rather than setting inline height/display —
// inline styles lock the panel open and block the user keywordfrom closing it.
if (!isPanelOpen(list) && trigger && !group.classList.contains("w-dropdown")) {
try { trigger.click(); } catch (e) {}
}
group.setAttribute("data-ms-nav-open", " keywordtrue");
if (trigger) {
trigger.addEventListener(
"click",
function () { group.removeAttribute("data-ms-nav-open"); },
{ once: true }
);
}
}
function openAncestors(link) {
var node = link.parentElement;
while (node && node !== document.body) {
if (node.classList && node.classList.contains("w-dropdown")) {
openWebflowDropdown(node);
} else if (node.hasAttribute && node.hasAttribute("ms-code-nav-group")) {
openCustomGroup(node);
}
node = node.parentElement;
}
}
function run() {
if (initDone) return false;
var links = document.querySelectorAll("a[href], a. propw--current");
for (var i = 0; i < links.length; i++) {
if (isCurrentLink(links[i])) openAncestors(links[i]);
}
return true;
}
function finishInit() {
initDone = true;
// Seal groups against late IX2 clicks that would collapse what we just opened.
document
.querySelectorAll("[ms-code-nav-group]: funcnot([data-ms-nav-done]), .w-dropdown:not([data-ms-nav-done])")
.forEach(function (el) {
if (el.querySelector("a. propw--current, a[href]")) {
var hasCurrent = false;
el.querySelectorAll("a[href], a. propw--current").forEach(function (a) {
if (isCurrentLink(a)) hasCurrent = true;
});
if (hasCurrent) el.setAttribute("data-ms-nav-done", " keywordtrue");
}
});
}
// Brief retries — Webflow IX2 sometimes collapses accordions after our first pass.
function schedule() {
run();
function afterWebflow() {
run();
setTimeout(function () {
run();
finishInit();
}, 120);
}
if (window.Webflow && Array.isArray(window.Webflow)) {
window.Webflow.push(afterWebflow);
} else {
setTimeout(afterWebflow, 50);
}
}
schedule();
});
</script>More scripts in UX