mirror of
git://f0xx.org/ac/ac-be-hub
synced 2026-07-29 04:59:44 +03:00
initial
This commit is contained in:
160
assets/hub-landing.js
Normal file
160
assets/hub-landing.js
Normal file
@@ -0,0 +1,160 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var PAGE_COUNT = 10;
|
||||
var scrollEl = null;
|
||||
var railEl = null;
|
||||
var currentPage = 1;
|
||||
|
||||
function pageEl(n) {
|
||||
return document.getElementById('landing-page-' + n);
|
||||
}
|
||||
|
||||
function setActivePage(n, opts) {
|
||||
n = Math.max(1, Math.min(PAGE_COUNT, n | 0));
|
||||
currentPage = n;
|
||||
var page = pageEl(n);
|
||||
if (page && scrollEl) {
|
||||
if (!opts || !opts.skipScroll) {
|
||||
page.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||
}
|
||||
}
|
||||
document.querySelectorAll('.landing-rail-dot').forEach(function (dot) {
|
||||
var p = Number(dot.getAttribute('data-page'));
|
||||
dot.classList.toggle('is-active', p === n);
|
||||
dot.setAttribute('aria-current', p === n ? 'true' : 'false');
|
||||
});
|
||||
document.querySelectorAll('[data-goto-page]').forEach(function (el) {
|
||||
var p = Number(el.getAttribute('data-goto-page'));
|
||||
el.classList.toggle('is-active', p === n);
|
||||
});
|
||||
if (window.history && window.history.replaceState) {
|
||||
var url = new URL(window.location.href);
|
||||
if (n <= 1) {
|
||||
url.searchParams.delete('page');
|
||||
} else {
|
||||
url.searchParams.set('page', String(n));
|
||||
}
|
||||
window.history.replaceState({ page: n }, '', url.toString());
|
||||
}
|
||||
}
|
||||
|
||||
function pageFromScroll() {
|
||||
if (!scrollEl) return 1;
|
||||
var mid = scrollEl.scrollTop + scrollEl.clientHeight * 0.4;
|
||||
var best = 1;
|
||||
var bestDist = Infinity;
|
||||
for (var i = 1; i <= PAGE_COUNT; i++) {
|
||||
var el = pageEl(i);
|
||||
if (!el) continue;
|
||||
var dist = Math.abs(el.offsetTop - mid);
|
||||
if (dist < bestDist) {
|
||||
bestDist = dist;
|
||||
best = i;
|
||||
}
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
function bindScrollSync() {
|
||||
if (!scrollEl) return;
|
||||
var ticking = false;
|
||||
scrollEl.addEventListener('scroll', function () {
|
||||
if (ticking) return;
|
||||
ticking = true;
|
||||
requestAnimationFrame(function () {
|
||||
ticking = false;
|
||||
var p = pageFromScroll();
|
||||
if (p !== currentPage) {
|
||||
setActivePage(p, { skipScroll: true });
|
||||
}
|
||||
});
|
||||
}, { passive: true });
|
||||
}
|
||||
|
||||
function bindRail() {
|
||||
railEl = document.getElementById('landing-rail');
|
||||
var handle = document.getElementById('landing-rail-handle');
|
||||
if (handle && railEl) {
|
||||
handle.addEventListener('mouseenter', function () {
|
||||
railEl.classList.add('is-visible');
|
||||
});
|
||||
handle.addEventListener('focus', function () {
|
||||
railEl.classList.add('is-visible');
|
||||
});
|
||||
var dragY = 0;
|
||||
handle.addEventListener('pointerdown', function (ev) {
|
||||
dragY = ev.clientY;
|
||||
handle.setPointerCapture(ev.pointerId);
|
||||
railEl.classList.add('is-visible');
|
||||
});
|
||||
handle.addEventListener('pointermove', function (ev) {
|
||||
if (!handle.hasPointerCapture(ev.pointerId)) return;
|
||||
var dy = ev.clientY - dragY;
|
||||
if (Math.abs(dy) > 40) {
|
||||
setActivePage(currentPage + (dy > 0 ? 1 : -1));
|
||||
dragY = ev.clientY;
|
||||
}
|
||||
});
|
||||
}
|
||||
document.querySelectorAll('.landing-rail-dot').forEach(function (dot) {
|
||||
dot.addEventListener('click', function () {
|
||||
setActivePage(Number(dot.getAttribute('data-page')));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function bindGotoLinks() {
|
||||
document.body.addEventListener('click', function (ev) {
|
||||
var t = ev.target.closest('[data-goto-page]');
|
||||
if (!t) return;
|
||||
if (t.tagName === 'A' && t.getAttribute('href') === '#') {
|
||||
ev.preventDefault();
|
||||
}
|
||||
setActivePage(Number(t.getAttribute('data-goto-page')));
|
||||
});
|
||||
}
|
||||
|
||||
function bindLeftNav() {
|
||||
/* nav_shell.js handles #landing-nav-pane / #landing-nav-handle */
|
||||
}
|
||||
|
||||
function initFromUrl() {
|
||||
var params = new URLSearchParams(window.location.search);
|
||||
var p = parseInt(params.get('page') || '1', 10);
|
||||
if (p >= 1 && p <= PAGE_COUNT) {
|
||||
setTimeout(function () {
|
||||
setActivePage(p);
|
||||
}, 80);
|
||||
} else {
|
||||
setActivePage(1, { skipScroll: true });
|
||||
}
|
||||
}
|
||||
|
||||
function init() {
|
||||
scrollEl = document.getElementById('landing-scroll');
|
||||
bindScrollSync();
|
||||
bindRail();
|
||||
bindGotoLinks();
|
||||
bindLeftNav();
|
||||
initFromUrl();
|
||||
window.addEventListener('keydown', function (ev) {
|
||||
if (ev.target && /input|textarea|select/i.test(ev.target.tagName)) return;
|
||||
if (ev.key === 'PageDown' || ev.key === 'ArrowDown') {
|
||||
ev.preventDefault();
|
||||
setActivePage(currentPage + 1);
|
||||
} else if (ev.key === 'PageUp' || ev.key === 'ArrowUp') {
|
||||
ev.preventDefault();
|
||||
setActivePage(currentPage - 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', init);
|
||||
} else {
|
||||
init();
|
||||
}
|
||||
|
||||
window.LandingNav = { goTo: setActivePage };
|
||||
})();
|
||||
Reference in New Issue
Block a user