PageSourceSearch

https://spacewaves2.net/template/default/js/site-header.js

js spacewaves2.net collected 2026-09-26 03:39:17 UTC 8,158 bytes, 259 lines download raw bytes

1(function () {
2  var btn = document.getElementById('nav-toggle');
3  var nav = document.getElementById('site-nav');
4  var backdrop = document.getElementById('nav-backdrop');
5  if (!btn || !nav) return;
6  var labelOpen = btn.getAttribute('data-aria-label-open') || 'Open menu';
7  var labelClose = btn.getAttribute('data-aria-label-close') || 'Close menu';
8  function setMenuAria(open) {
9    btn.setAttribute('aria-expanded', open ? 'true' : 'false');
10    btn.setAttribute('aria-label', open ? labelClose : labelOpen);
11  }
12  function setMenuOpen(open) {
13    nav.classList.toggle('open', open);
14    btn.classList.toggle('open', open);
15    setMenuAria(open);
16    if (backdrop) {
17      backdrop.hidden = !open;
18      backdrop.setAttribute('aria-hidden', open ? 'false' : 'true');
19      document.body.classList.toggle('nav-menu-open', open);
20    }
21    if (open) {
22      nav.querySelectorAll('.nav-dropdown').forEach(function (drop) {
23        drop.classList.add('is-open');
24        var toggle = drop.querySelector('.nav-dropdown__toggle');
25        if (toggle) toggle.setAttribute('aria-expanded', 'true');
26      });
27    }
28  }
29  btn.addEventListener('click', function () {
30    setMenuOpen(!nav.classList.contains('open'));
31  });
32  if (backdrop) {
33    backdrop.addEventListener('click', function () {
34      setMenuOpen(false);
35    });
36  }
37  document.addEventListener('click', function (e) {
38    if (!nav.classList.contains('open')) return;
39    if (btn.contains(e.target) || nav.contains(e.target)) return;
40    if (backdrop && backdrop.contains(e.target)) return;
41    setMenuOpen(false);
42  });
43})();
44(function () {
45  var wrap = document.getElementById('nav-search-wrap');
46  var input = document.getElementById('nav-game-search');
47  var list = document.getElementById('nav-search-listbox');
48  if (!wrap || !input || !list) return;
49  var noResults = wrap.getAttribute('data-no-results') || 'No matching games';
50  var allGames = [];
51  var loaded = false;
52  var loadTimer = null;
53  function loadData(cb) {
54    if (loaded) {
55      cb();
56      return;
57    }
58    fetch('/data/games.json', { credentials: 'same-origin' })
59      .then(function (r) {
60        return r.ok ? r.json() : Promise.reject();
61      })
62      .then(function (data) {
63        allGames = data && Array.isArray(data.games) ? data.games : [];
64        loaded = true;
65        cb();
66      })
67      .catch(function () {
68        allGames = [];
69        loaded = true;
70        cb();
71      });
72  }
73  function norm(s) {
74    return String(s || '').toLowerCase();
75  }
76  function showDropdown(show) {
77    list.hidden = !show;
78    input.setAttribute('aria-expanded', show ? 'true' : 'false');
79  }
80  window.SpaceWavesSearchClose = function () {
81    list.innerHTML = '';
82    showDropdown(false);
83  };
84  function fillList(hits) {
85    list.innerHTML = '';
86    hits.forEach(function (g) {
87      var a = document.createElement('a');
88      a.className = 'nav-search__opt';
89      a.href = g.url || '#';
90      a.setAttribute('role', 'option');
91      var img = document.createElement('img');
92      img.src = g.image || '';
93      img.alt = '';
94      img.width = 28;
95      img.height = 28;
96      img.loading = 'lazy';
97      var span = document.createElement('span');
98      span.textContent = g.name || g.slug || '';
99      a.appendChild(img);
100      a.appendChild(span);
101      list.appendChild(a);
102    });
103  }
104  function updatePanel() {
105    var q = norm(input.value).trim();
106    loadData(function () {
107      var hits;
108      if (q.length < 1) {
109        hits = allGames;
110      } else {
111        hits = allGames
112          .filter(function (g) {
113            return norm(g.name).indexOf(q) >= 0 || norm(g.slug).indexOf(q.replace(/\s+/g, '-')) >= 0;
114          })
115          .slice(0, 14);
116      }
117      if (q.length >= 1 && !hits.length) {
118        list.innerHTML = '';
119        var empty = document.createElement('div');
120        empty.className = 'nav-search__empty';
121        empty.textContent = noResults;
122        list.appendChild(empty);
123        showDropdown(true);
124        return;
125      }
126      if (!hits.length) {
127        list.innerHTML = '';
128        showDropdown(false);
129        return;
130      }
131      fillList(hits);
132      showDropdown(true);
133    });
134  }
135  function debounceUpdate() {
136    clearTimeout(loadTimer);
137    loadTimer = setTimeout(updatePanel, 100);
138  }
139  input.addEventListener('input', debounceUpdate);
140  input.addEventListener('focus', function () {
141    updatePanel();
142  });
143  input.addEventListener('click', function () {
144    updatePanel();
145  });
146  document.addEventListener('click', function (e) {
147    if (!wrap.contains(e.target)) {
148      list.innerHTML = '';
149      showDropdown(false);
150    }
151  });
152  input.addEventListener('keydown', function (e) {
153    if (e.key === 'Escape') {
154      list.innerHTML = '';
155      showDropdown(false);
156      input.blur();
157    }
158  });
159})();
160(function () {
161  var nav = document.getElementById('site-nav');
162  if (!nav) return;
163  var path = (location.pathname || '/').replace(/\/index\.html$/i, '/').toLowerCase();
164  if (path.length >
164 1 && path.charAt(path.length - 1) === '/') {
165    path = path.slice(0, -1);
166  }
167  var langRoots = ['pt-br', 'nl', 'sv', 'es', 'fr', 'de'];
168  var i;
169  for (i = 0; i < langRoots.length; i++) {
170    var root = '/' + langRoots[i];
171    if (path === root) {
172      path = '/';
173      break;
174    }
175    if (path.indexOf(root + '/') === 0) {
176      path = path.slice(root.length) || '/';
177      break;
178    }
179  }
180  var links = nav.querySelectorAll('.nav-link');
181  var best = null;
182  var bestLen = -1;
183  links.forEach(function (a) {
184    var href = (a.getAttribute('href') || '').split('?')[0].split('#')[0].toLowerCase();
185    if (!href) return;
186    if (href.length > 1 && href.charAt(href.length - 1) === '/') {
187      href = href.slice(0, -1);
188    }
189    var extra = (a.getAttribute('data-nav-match') || '').split(',');
190    var matched = false;
191    if (href === '/') {
192      matched = path === '/';
193    } else {
194      matched = path === href || path.indexOf(href + '/') === 0;
195    }
196    extra.forEach(function (raw) {
197      var m = String(raw || '').trim().toLowerCase();
198      if (!m) return;
199      if (m.length > 1 && m.charAt(m.length - 1) === '/') m = m.slice(0, -1);
200      if (path === m || path.indexOf(m + '/') === 0) matched = true;
201    });
202    if (matched && href.length > bestLen) {
203      best = a;
204      bestLen = href.length;
205    }
206  });
207  if (best) {
208    links.forEach(function (a) {
209      a.classList.remove('active');
210      a.removeAttribute('aria-current');
211    });
212    best.classList.add('active');
213    best.setAttribute('aria-current', 'page');
214  }
215  nav.querySelectorAll('.nav-dropdown__item[href]').forEach(function (item) {
216    var href = (item.getAttribute('href') || '').replace(/\/+$/, '') || '/';
217    var onItem = path === href || path.indexOf(href + '/') === 0;
218    item.classList.toggle('is-active', onItem);
219    if (onItem) item.setAttribute('aria-current', 'page');
220    else item.removeAttribute('aria-current');
221  });
222})();
223(function () {
224  function isHoverDevice() {
225    try {
226      return window.matchMedia('(hover: hover) and (pointer: fine)').matches;
227    } catch (e) {
228      return true;
229    }
230  }
231  document.querySelectorAll('.nav-dropdown').forEach(function (drop) {
232    var toggle = drop.querySelector('.nav-dropdown__toggle');
233    var trigger = drop.querySelector('.nav-dropdown__trigger');
234    function setOpen(open) {
235      drop.classList.toggle('is-open', !!open);
236      if (toggle) toggle.setAttribute('aria-expanded', open ? 'true' : 'false');
237    }
238    function flip(e) {
239      e.preventDefault();
240      e.stopPropagation();
241      setOpen(!drop.classList.contains('is-open'));
242      if (toggle) toggle.blur();
243    }
244    if (toggle) toggle.addEventListener('click', flip);
245    // More Games has no link: clicking the label also toggles the menu
246    if (trigger && trigger.tagName !== 'A') {
247      trigger.addEventListener('click', flip);
248      trigger.style.cursor = 'pointer';
249    }
250    drop.addEventListener('mouseenter', function () {
251      if (!isHoverDevice()) return;
252      setOpen(true);
253    });
254    drop.addEventListener('mouseleave', function () {
255      if (!isHoverDevice()) return;
256      setOpen(false);
257    });
258  });
259})();

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.