Moe-Counter/assets/script.js

209 lines
5.8 KiB
JavaScript
Raw Permalink Normal View History

2024-10-20 16:19:35 +00:00
(function () {
const btn = document.getElementById('get');
const img = document.getElementById('result');
const code = document.getElementById('code');
2024-10-22 19:59:07 +00:00
const elements = {
name: document.getElementById('name'),
theme: document.getElementById('theme'),
padding: document.getElementById('padding'),
offset: document.getElementById('offset'),
2024-10-30 07:46:17 +00:00
align: document.getElementById('align'),
2024-10-22 19:59:07 +00:00
scale: document.getElementById('scale'),
pixelated: document.getElementById('pixelated'),
darkmode: document.getElementById('darkmode'),
num: document.getElementById('num'),
prefix: document.getElementById('prefix')
2024-10-22 19:59:07 +00:00
};
btn.addEventListener('click', throttle(handleButtonClick, 500));
code.addEventListener('click', selectCodeText);
const mainTitle = document.querySelector('#main_title i');
const themes = document.querySelector('#themes');
const moreTheme = document.querySelector('#more_theme');
mainTitle.addEventListener('click', throttle(() => party.sparkles(document.documentElement, { count: party.variation.range(40, 100) }), 1000));
moreTheme.addEventListener('click', scrollToThemes);
function handleButtonClick() {
2024-10-25 04:53:34 +00:00
const { name, theme, padding, offset, scale, pixelated, darkmode, num } = elements;
2024-10-22 19:59:07 +00:00
const nameValue = name.value.trim();
if (!nameValue) {
2024-10-20 16:19:35 +00:00
alert('Please input counter name.');
return;
}
const params = {
2024-10-22 19:59:07 +00:00
name: nameValue,
theme: theme.value || 'moebooru',
padding: padding.value || '7',
offset: offset.value || '0',
2024-10-30 07:46:17 +00:00
align: align.value || 'top',
2024-10-22 19:59:07 +00:00
scale: scale.value || '1',
pixelated: pixelated.checked ? '1' : '0',
darkmode: darkmode.value || 'auto'
};
2024-10-20 16:19:35 +00:00
2024-10-25 04:53:34 +00:00
if (num.value > 0) {
params.num = num.value;
}
if (prefix.value !== '') {
params.prefix = prefix.value;
}
2024-10-25 04:53:34 +00:00
2024-10-20 16:19:35 +00:00
const query = new URLSearchParams(params).toString();
2024-10-22 19:59:07 +00:00
const imgSrc = `${__global_data.site}/@${nameValue}?${query}`;
img.src = `${imgSrc}&_=${Math.random()}`;
btn.setAttribute('disabled', '');
2024-10-20 16:19:35 +00:00
2024-10-20 16:58:30 +00:00
img.onload = () => {
img.scrollIntoView({ block: 'start', behavior: 'smooth' });
code.textContent = imgSrc;
code.style.visibility = 'visible';
2024-10-22 19:59:07 +00:00
party.confetti(btn, { count: party.variation.range(20, 40) });
btn.removeAttribute('disabled');
};
2024-10-20 16:58:30 +00:00
2024-10-22 19:59:07 +00:00
img.onerror = async () => {
try {
2024-10-25 04:53:34 +00:00
const res = await fetch(img.src);
2024-10-22 19:59:07 +00:00
if (!res.ok) {
const { message } = await res.json();
alert(message);
}
} finally {
btn.removeAttribute('disabled');
}
2024-10-20 16:58:30 +00:00
};
2024-10-22 19:59:07 +00:00
}
2024-10-20 16:19:35 +00:00
2024-10-22 19:59:07 +00:00
function selectCodeText(e) {
e.preventDefault();
e.stopPropagation();
2024-10-20 16:19:35 +00:00
const target = e.target;
2024-10-22 19:59:07 +00:00
const range = document.createRange();
const selection = window.getSelection();
2024-10-20 16:19:35 +00:00
2024-10-22 19:59:07 +00:00
range.selectNodeContents(target);
selection.removeAllRanges();
selection.addRange(range);
}
2024-10-20 16:19:35 +00:00
2024-10-22 19:59:07 +00:00
function scrollToThemes() {
2024-10-20 16:19:35 +00:00
if (!themes.hasAttribute('open')) {
party.sparkles(moreTheme.querySelector('h3'), { count: party.variation.range(20, 40) });
themes.scrollIntoView({ block: 'start', behavior: 'smooth' });
}
2024-10-22 19:59:07 +00:00
}
2024-10-20 16:19:35 +00:00
function throttle(fn, threshold = 250) {
2024-10-22 19:59:07 +00:00
let last, deferTimer;
2024-10-20 16:19:35 +00:00
return function (...args) {
const now = Date.now();
if (last && now < last + threshold) {
clearTimeout(deferTimer);
deferTimer = setTimeout(() => {
last = now;
2024-10-22 19:59:07 +00:00
fn.apply(this, args);
2024-10-20 16:19:35 +00:00
}, threshold);
} else {
last = now;
2024-10-22 19:59:07 +00:00
fn.apply(this, args);
2024-10-20 16:19:35 +00:00
}
};
}
})();
2024-10-22 19:59:07 +00:00
// Lazy Load
2024-10-21 04:22:51 +00:00
(() => {
function lazyLoad(options = {}) {
2024-10-22 19:59:07 +00:00
const { selector = 'img[data-src]:not([src])', loading = '', failed = '', rootMargin = '200px', threshold = 0.01 } = options;
2024-10-21 04:22:51 +00:00
const images = document.querySelectorAll(selector);
const observer = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
observer.unobserve(img);
2024-10-22 19:59:07 +00:00
img.onerror = failed ? () => { img.src = failed; img.setAttribute('data-failed', ''); } : null;
2024-10-21 04:22:51 +00:00
img.src = img.getAttribute('data-src');
2024-10-22 19:59:07 +00:00
img.removeAttribute('data-loading');
2024-10-21 04:22:51 +00:00
}
});
}, { rootMargin, threshold });
images.forEach(img => {
if (loading) {
img.src = loading;
img.setAttribute('data-loading', '');
}
observer.observe(img);
});
}
const lazyLoadOptions = {
selector: 'img[data-src]:not([src])',
loading: `${__global_data.site}/img/loading.svg`,
failed: `${__global_data.site}/img/failed.svg`,
2024-10-21 04:22:51 +00:00
rootMargin: '200px',
threshold: 0.01
};
2024-10-22 19:59:07 +00:00
document.readyState === 'loading'
? document.addEventListener("DOMContentLoaded", () => lazyLoad(lazyLoadOptions))
: lazyLoad(lazyLoadOptions);
2024-10-21 04:22:51 +00:00
})();
2024-10-20 16:19:35 +00:00
2024-10-22 19:59:07 +00:00
// Back to top
2024-10-20 16:19:35 +00:00
(() => {
2024-10-22 19:59:07 +00:00
let isShow = false, lock = false;
2024-10-20 16:19:35 +00:00
const btn = document.querySelector('.back-to-top');
const handleScroll = () => {
if (lock) return;
if (document.body.scrollTop >= 1000) {
if (!isShow) {
btn.classList.add('load');
isShow = true;
}
2024-10-22 19:59:07 +00:00
} else if (isShow) {
btn.classList.remove('load');
isShow = false;
2024-10-20 16:19:35 +00:00
}
};
const handleClick = () => {
lock = true;
btn.classList.add('ani-leave');
window.scrollTo({ top: 0, behavior: 'smooth' });
setTimeout(() => {
btn.classList.remove('ani-leave');
btn.classList.add('leaved');
}, 390);
setTimeout(() => btn.classList.add('ending'), 120);
setTimeout(() => btn.classList.remove('load'), 1500);
setTimeout(() => {
lock = false;
isShow = false;
btn.classList.remove('leaved', 'ending');
}, 2000);
};
window.addEventListener('scroll', handleScroll);
btn.addEventListener('click', handleClick);
})();
2024-10-22 19:59:07 +00:00
2024-10-25 04:53:34 +00:00
// Prevent safari gesture
2024-10-22 19:59:07 +00:00
(() => {
document.addEventListener('gesturestart', e => e.preventDefault());
})();