Skip to content

Instantly share code, notes, and snippets.

@effervescentia
Created October 4, 2023 20:23
Show Gist options
  • Save effervescentia/c8c55c2265e17f488967fd04f78b6410 to your computer and use it in GitHub Desktop.
Save effervescentia/c8c55c2265e17f488967fd04f78b6410 to your computer and use it in GitHub Desktop.
marquee-ify
const IGNORED_TAGS = ['svg', 'NOSCRIPT', 'SCRIPT', 'BUTTON', 'CODE', 'IMG', 'VIDEO', 'A', 'LINK', 'META'];
const MAX_COUNTER = 2;
let counter = 0;
function delay(timeout) {
return new Promise(resolve => setTimeout(resolve, timeout));
}
function randomScroll(direction, origin) {
let scroll = Math.floor(Math.random() * 10) + 10;
switch (direction) {
case 'left':
case 'right':
scroll ^= origin.scrollWidth ? Math.log(origin.scrollWidth) : 1;
case 'up':
case 'down':
scroll ^= origin.scrollHeight ? Math.log(origin.scrollHeight) : 1;
}
return scroll;
}
function randomDelay() {
return Math.floor(Math.random() * 3) * 1000;
}
function randomDirection() {
switch (Math.floor(Math.random() * 4)) {
case 0: return 'left';
case 1: return 'up';
case 2: return 'right';
case 3: return 'down';
}
}
function captureElements(parent = document.body, depth = 0) {
return [
...(parent === document.body ? [] : [[parent, depth]]),
...Array
.from(parent.children)
.filter(el => !IGNORED_TAGS.includes(el.tagName))
.flatMap(el => captureElements(el, depth + 1)),
];
}
function findMostDepth(elements) {
const counts = elements.reduce((acc, [, depth]) => {
acc[depth] = (acc[depth] ?? 0) + 1;
return acc;
}, {});
const [depth] = Object.entries(counts).reduce((acc, count) => {
if (acc[1] < count[1]) return count;
return acc;
});
return Number(depth);
}
const elementsWithDepth = captureElements();
const mostDepth = findMostDepth(elementsWithDepth);
const elements = elementsWithDepth
.filter(([el]) => !el.tagName.includes('-'))
.map(([el, depth]) => [el, depth + (depth === mostDepth ? 100 : 0) + Math.random()])
.sort(([, lhs], [, rhs]) => rhs - lhs)
.map(([el]) => el);
for (const origin of elements) {
const target = document.createElement('marquee');
origin.getAttributeNames().forEach(name => target.setAttribute(name, origin.getAttribute(name)));
const direction = randomDirection();
target.setAttribute('direction', direction);
target.setAttribute('scrollamount', randomScroll(direction, origin));
target.setAttribute('scrolldelay', randomDelay());
if (origin.scrollHeight) {
target.style.height = `${origin.scrollHeight}px`;
}
if (origin.scrollWidth) {
target.style.width = `${origin.scrollWidth}px`;
}
if (window.getComputedStyle(origin).display !== 'inline') {
target.style.display = window.getComputedStyle(origin).display;
}
Array.from(origin.children).forEach(child => {
origin.removeChild(child);
target.appendChild(child);
});
const parent = origin.parentElement;
parent.removeChild(origin);
parent.appendChild(target);
await delay(10);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment