PageSourceSearch

https://quickstyle.com/assets/js/main.js

js quickstyle.com collected 2026-10-06 17:51:59 UTC 4,988 bytes, 117 lines download raw bytes

1document.addEventListener('DOMContentLoaded', function () {
2
3    /* ── Scroll shadow ─────────────────────────── */
4    const header = document.getElementById('site-header');
5    if (header) {
6        window.addEventListener('scroll', () => {
7            header.classList.toggle('scrolled', window.scrollY > 20);
8        }, { passive: true });
9    }
10
11    /* ── Hamburger ─────────────────────────────── */
12    const hamburger = document.getElementById('hamburger');
13    const nav = document.getElementById('hdr-nav');
14    if (hamburger && nav) {
15        hamburger.addEventListener('click', () => {
16            const open = nav.classList.toggle('is-open');
17            hamburger.classList.toggle('is-open', open);
18            hamburger.setAttribute('aria-expanded', open);
19            document.body.style.overflow = open ? 'hidden' : '';
20        });
21        document.addEventListener('keydown', e => {
22            if (e.key === 'Escape' && nav.classList.contains('is-open')) {
23                nav.classList.remove('is-open');
24                hamburger.classList.remove('is-open');
25                document.body.style.overflow = '';
26            }
27        });
28    }
29
30    /* ── Mobile dropdowns ──────────────────────── */
31    document.querySelectorAll('.nav-link--drop').forEach(link => {
32        link.addEventListener('click', () => {
33            if (window.innerWidth > 900) return;
34            const item = link.closest('.nav-item');
35            const wasOpen = item.classList.contains('is-open');
36            document.querySelectorAll('.nav-item').forEach(i => i.classList.remove('is-open'));
37            if (!wasOpen) item.classList.add('is-open');
38        });
39    });
40
41    window.addEventListener('resize', () => {
42        if (window.innerWidth > 900 && nav) {
43            nav.classList.remove('is-open');
44            hamburger && hamburger.classList.remove('is-open');
45            document.body.style.overflow = '';
46            document.querySelectorAll('.nav-item').forEach(i => i.classList.remove('is-open'));
47        }
48    });
49
50    /* ── Active nav ────────────────────────────── */
51    const path = window.location.pathname;
52    document.querySelectorAll('.nav-link').forEach(link => {
53        const href = link.getAttribute('href');
54        if (href && href.length > 4 && path.includes(href)) {
55            link.closest('.nav-item')?.classList.add('active');
56        }
57    });
58
59    /* ── Language modal ────────────────────────── */
60    const backdrop = document.getElementById('lang-modal-backdrop');
61    if (backdrop) {
62        // Set session flag then navigate
63        backdrop.querySelectorAll('.lang-option').forEach(el => {
64            el.addEventListener('click', function(e) {
65                e.preventDefault();
66                const href = this.getAttribute('href');
67                // Tell server to set session so modal doesn't show again this session
68                fetch('/set-lang-session.php').finally(() => {
69                    window.location.href = href;
70                });
71            });
72        });
73
74        // Dismiss on backdrop click (without setting session — will show again on reload)
75        backdrop.addEventListener('click', e => {
76            if (e.target === backdrop) fadeOut(backdrop);
77        });
78
79        // Dismiss on Escape
80        document.addEventListener('keydown', e => {
81            if (e.key === 'Escape') fadeOut(backdrop);
82        });
83    }
84
85    /* ── Lang toggle — smooth page transition ─── */
86    document.querySelectorAll('.lang-toggle').forEach(toggle => {
87        toggle.addEventListener('click', function(e) {
88            e.preventDefault();
89            const href = this.getAttribute('href');
90            // Fade page out then navigate
91            document.body.style.transition = 'opacity 0.3s ease';
92            document.body.style.opacity = '0';
93            setTimeout(() => { window.location.href = href; }, 300);
94        });
95    });
96
97    /* ── Helpers ───────────────────────────────── */
98    function fadeOut(el) {
99        el.style.transition = 'opacity 0.35s ease';
100        el.style.opacity = '0';
101        el.style.pointerEvents = 'none';
102        setTimeout(() => { el.style.display = 'none'; }, 360);
103    }
104
105    function setCookie(name, value, days) {
106        const expires = new Date(Date.now() + days * 864e5).toUTCString();
107        document.cookie = name + '=' + value + '; expires=' + expires + '; path=/';
108    }
109
110    function getCookie(name) {
111        return document.cookie.split('; ').reduce((r, v) => {
112            const parts = v.split('=');
113            return parts[0] === name ? parts[1] : r;
114        }, null);
115    }
116
117});

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.