| --- |
|
|
| --- |
|
|
| <div class="sidenote-container"> |
| <aside class="sidenote"> |
| <slot /> |
| </aside> |
| </div> |
|
|
| <script> |
| const initSidenotes = () => { |
| const containers = document.querySelectorAll(".sidenote-container"); |
| |
| containers.forEach((container) => { |
| |
| if (container.closest(".sidenote-wrapper")) { |
| return; |
| } |
| |
| |
| let previousElement = |
| container.previousElementSibling as HTMLElement | null; |
| |
| |
| if (!previousElement && container.parentNode) { |
| const parent = container.parentNode as HTMLElement; |
| |
| if (parent.children.length === 1 && parent.previousElementSibling) { |
| previousElement = parent.previousElementSibling as HTMLElement; |
| } |
| } |
| |
| if ( |
| previousElement && |
| previousElement.parentNode && |
| container.parentNode |
| ) { |
| |
| const wrapper = document.createElement("div"); |
| wrapper.className = "sidenote-wrapper"; |
| |
| const parent = container.parentNode; |
| |
| |
| if (previousElement.parentNode === parent) { |
| parent.insertBefore(wrapper, previousElement); |
| wrapper.appendChild(previousElement); |
| wrapper.appendChild(container); |
| } else { |
| |
| const prevParent = previousElement.parentNode; |
| prevParent.insertBefore(wrapper, previousElement); |
| wrapper.appendChild(previousElement); |
| parent.removeChild(container); |
| wrapper.appendChild(container); |
| } |
| |
| |
| wrapper.style.position = "relative"; |
| wrapper.style.display = "block"; |
| |
| |
| const sidenoteContainer = container as HTMLElement; |
| sidenoteContainer.style.position = "absolute"; |
| sidenoteContainer.style.top = "0"; |
| sidenoteContainer.style.right = "-292px"; |
| sidenoteContainer.style.width = "260px"; |
| |
| |
| sidenoteContainer.style.display = "block"; |
| sidenoteContainer.style.opacity = "0"; |
| |
| |
| requestAnimationFrame(() => { |
| requestAnimationFrame(() => { |
| sidenoteContainer.style.opacity = "1"; |
| }); |
| }); |
| } else { |
| |
| const sidenoteContainer = container as HTMLElement; |
| sidenoteContainer.style.display = "block"; |
| sidenoteContainer.style.opacity = "1"; |
| } |
| }); |
| }; |
| |
| |
| const verifyStylesApplied = () => { |
| const wrappers = document.querySelectorAll(".sidenote-wrapper"); |
| let allApplied = true; |
| |
| wrappers.forEach((wrapper) => { |
| const sidenote = wrapper.querySelector( |
| ".sidenote-container", |
| ) as HTMLElement; |
| if (sidenote) { |
| const computed = window.getComputedStyle(sidenote); |
| |
| if (computed.position !== "absolute" && window.innerWidth > 768) { |
| allApplied = false; |
| |
| sidenote.style.position = "absolute"; |
| sidenote.style.top = "0"; |
| sidenote.style.right = "-292px"; |
| sidenote.style.width = "260px"; |
| sidenote.style.display = "block"; |
| } |
| } |
| }); |
| |
| return allApplied; |
| }; |
| |
| |
| const startInit = () => { |
| |
| initSidenotes(); |
| |
| |
| setTimeout(() => { |
| verifyStylesApplied(); |
| }, 50); |
| |
| |
| |
| const containers = document.querySelectorAll(".sidenote-container"); |
| |
| if (containers.length === 0) { |
| |
| const observer = new MutationObserver((mutations, obs) => { |
| const newContainers = document.querySelectorAll(".sidenote-container"); |
| if (newContainers.length > 0) { |
| |
| initSidenotes(); |
| |
| setTimeout(() => { |
| verifyStylesApplied(); |
| }, 50); |
| |
| setTimeout(() => { |
| obs.disconnect(); |
| }, 5000); |
| } |
| }); |
| |
| |
| const targetNode = document.querySelector("main") || document.body; |
| if (targetNode) { |
| observer.observe(targetNode, { |
| childList: true, |
| subtree: true, |
| }); |
| } |
| |
| |
| setTimeout(() => { |
| observer.disconnect(); |
| }, 10000); |
| } |
| }; |
| |
| |
| const waitForFullLoad = () => { |
| |
| const idleOrTimeout = (callback: () => void, timeout: number) => { |
| if (typeof (window as any).requestIdleCallback === "function") { |
| (window as any).requestIdleCallback(callback, { timeout }); |
| } else { |
| setTimeout(callback, timeout); |
| } |
| }; |
| |
| if (document.readyState === "loading") { |
| |
| document.addEventListener( |
| "DOMContentLoaded", |
| () => { |
| idleOrTimeout(startInit, 300); |
| }, |
| { once: true }, |
| ); |
| |
| |
| window.addEventListener( |
| "load", |
| () => { |
| setTimeout(() => { |
| initSidenotes(); |
| verifyStylesApplied(); |
| }, 100); |
| }, |
| { once: true }, |
| ); |
| } else if (document.readyState === "interactive") { |
| |
| idleOrTimeout(startInit, 300); |
| |
| |
| window.addEventListener( |
| "load", |
| () => { |
| setTimeout(() => { |
| initSidenotes(); |
| verifyStylesApplied(); |
| }, 100); |
| }, |
| { once: true }, |
| ); |
| } else { |
| |
| idleOrTimeout(startInit, 300); |
| |
| |
| setTimeout(() => { |
| initSidenotes(); |
| verifyStylesApplied(); |
| }, 500); |
| } |
| }; |
| |
| waitForFullLoad(); |
| </script> |
|
|
| <style is:global> |
| .sidenote-wrapper { |
| |
| position: relative; |
| display: block; |
| } |
| |
| .sidenote-container { |
| |
| display: none; |
| margin: 0; |
| |
| transition: opacity 0.3s ease-in-out; |
| } |
| |
| .sidenote { |
| border-radius: 8px; |
| padding: 0 30px; |
| font-size: 0.9rem; |
| color: var(--muted-color); |
| margin: 0; |
| } |
| |
| @media (--bp-content-collapse) { |
| .sidenote-wrapper { |
| |
| position: static !important; |
| } |
| |
| .sidenote-container { |
| position: static !important; |
| width: auto !important; |
| right: auto !important; |
| top: auto !important; |
| margin-top: 8px; |
| |
| display: block !important; |
| opacity: 1 !important; |
| } |
| |
| .sidenote { |
| padding: 0; |
| } |
| } |
| </style> |
|
|