PageSourceSearch

https://axoi.studio/Public/axoi-page.js

js axoi.studio collected 2026-10-08 06:02:22 UTC 3,858 bytes, 111 lines download raw bytes

1/* axoi. studio — slide page content between nav items; nav stays fixed */
2(function () {
3  const ORDER = ['index.html', 'services.html', 'work.html', 'about.html', 'contact.html', 'launch.html', 'thank-you.html'];
4  const DURATION = 220;
5  const reduce = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
6
7  function pageKey(href) {
8    try {
9      const u = new URL(href, location.href);
10      if (u.origin !== location.origin) return null;
11      let path = u.pathname.split('/').pop() || 'index.html';
12      if (path === '' || path === '/') path = 'index.html';
13      if (!/\.html?$/i.test(path)) return null;
14      return path;
15    } catch (_) {
16      return null;
17    }
18  }
19
20  function currentKey() {
21    return pageKey(location.href) || 'index.html';
22  }
23
24  function direction(from, to) {
25    const a = ORDER.indexOf(from);
26    const b = ORDER.indexOf(to);
27    if (a === -1 || b === -1 || a === b) return 'forward';
28    return b > a ? 'forward' : 'back';
29  }
30
31  /* Wrap everything except the fixed nav (and scripts) so transforms never move the bar. */
32  function ensureShell() {
33    let shell = document.querySelector('.page-shell');
34    if (shell) return shell;
35    shell = document.createElement('div');
36    shell.className = 'page-shell';
37    const nav = document.querySelector('body > .nav');
38    const keep = new Set([nav]);
39    document.querySelectorAll('body > script').forEach((el) => keep.add(el));
40    [...document.body.children]
41      .filter((el) => !keep.has(el))
42      .forEach((el) => shell.appendChild(el));
43    if (nav) nav.after(shell);
44    else document.body.prepend(shell);
45    return shell;
46  }
47
48  const shell = ensureShell();
49
50  function clearTransition() {
51    document.documentElement.classList.remove('nav-pending');
52    document.body.classList.remove('is-paging');
53    shell.classList.remove('page-leave', 'page-leave-back', 'page-enter', 'page-enter-back');
54  }
55
56  function go(href, dir) {
57    try { sessionStorage.setItem('axoi-nav-dir', dir); } catch (_) {}
58    if (reduce) {
59      location.href = href;
60      return;
61    }
62    document.body.classList.add('is-paging');
63    shell.classList.remove('page-enter', 'page-enter-back');
64    shell.classList.add(dir === 'back' ? 'page-leave-back' : 'page-leave');
65    window.setTimeout(() => { location.href = href; }, DURATION);
66  }
67
68  /* Enter only when arriving via our leave transition.
69     Add enter class before clearing nav-pending so opacity stays 0 (no flash). */
70  if (!reduce) {
71    let dir = null;
72    try {
73      dir = sessionStorage.getItem('axoi-nav-dir');
74      sessionStorage.removeItem('axoi-nav-dir');
75    } catch (_) {}
76    if (dir) {
77      const enterClass = dir === 'back' ? 'page-enter-back' : 'page-enter';
78      shell.classList.add(enterClass);
79      shell.addEventListener('animationend', () => {
80        shell.classList.remove('page-enter', 'page-enter-back');
81      }, { once: true });
82    }
83  }
84  document.documentElement.classList.remove('nav-pending');
85
86  /* Back-forward cache can restore a page mid-leave (opacity 0). */
87  window.addEventListener('pageshow', (e) => {
88    if (e.persisted) clearTransition();
89  });
90
91  document.addEventListener('click', (e) => {
92    if (e.defaultPrevented || e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;
93    const a = e.target.closest('a[href]');
94    if (!a) return;
95    if (a.target === '_blank' || a.hasAttribute('download')) return;
96
97    const href = a.getAttribute('href');
98    if (!href || href.startsWith('#') || href.startsWith('mailto:') || href.startsWith('tel:')) return;
99
100    const to = pageKey(href);
101    if (!to) return;
102
103    const from = currentKey();
104    if (to === from) return;
105
106    e.preventDefault();
107    const nav = document.querySelector('.nav');
108    if (nav) nav.classList.remove('mobile-open');
109    go(a.href, direction(from, to));
110  });
111})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.