PageSourceSearch

https://serial-studio.com/js/gallery.js?v=165106eb19

js serial-studio.com collected 2026-10-02 11:56:17 UTC 4,905 bytes, 157 lines download raw bytes

1(function () {
2  'use strict';
3
4  var grid = document.getElementById('galleryGrid');
5  var loading = document.getElementById('galleryLoading');
6  var empty = document.getElementById('galleryEmpty');
7  var error = document.getElementById('galleryError');
8
9  var lightbox = document.getElementById('screenshot-lightbox');
10  var lightboxImg = lightbox && lightbox.querySelector('.lightbox-image');
11  var lightboxCounter = lightbox && lightbox.querySelector('.lightbox-counter');
12  var lightboxClose = lightbox && lightbox.querySelector('.lightbox-close');
13  var lightboxPrev = lightbox && lightbox.querySelector('.lightbox-prev');
14  var lightboxNext = lightbox && lightbox.querySelector('.lightbox-next');
15
16  var screenshots = [];
17  var lightboxIndex = 0;
18
19  function setHidden(el, hidden) {
20    if (!el) return;
21    if (hidden) el.setAttribute('hidden', '');
22    else el.removeAttribute('hidden');
23  }
24
25  function visibleScreenshots() {
26    return screenshots;
27  }
28
29  function renderGrid() {
30    var items = visibleScreenshots();
31    grid.innerHTML = '';
32    setHidden(empty, items.length > 0);
33
34    items.forEach(function (s, index) {
35      var card = document.createElement('article');
36      card.className = 'gallery-card';
37
38      var thumb = document.createElement('button');
39      thumb.type = 'button';
40      thumb.className = 'gallery-thumb';
41      thumb.setAttribute('aria-label', 'Open ' + s.title + ' at full size');
42
43      var img = document.createElement('img');
44      img.src = s.file;
45      img.alt = s.alt || s.title;
46      img.loading = 'lazy';
47      thumb.appendChild(img);
48
49      thumb.addEventListener('click', function () {
50        openLightbox(index);
51      });
52
53      var body = document.createElement('div');
54      body.className = 'gallery-body';
55
56      var h3 = document.createElement('h3');
57      h3.className = 'gallery-title';
58      h3.textContent = s.title;
59      body.appendChild(h3);
60
61      var desc = document.createElement('p');
62      desc.className = 'gallery-desc';
63      desc.textContent = s.description;
64      body.appendChild(desc);
65
66      if (Array.isArray(s.tags) && s.tags.length) {
67        var tagList = document.createElement('ul');
68        tagList.className = 'gallery-tags';
69        s.tags.forEach(function (t) {
70          var li = document.createElement('li');
71          li.className = 'gallery-tag';
72          li.setAttribute('data-tag', t);
73          li.textContent = t;
74          tagList.appendChild(li);
75        });
76        body.appendChild(tagList);
77      }
78
79      if (s.helpAnchor) {
80        var link = document.createElement('a');
81        link.className = 'gallery-link';
82        link.href = 'help#' + s.helpAnchor;
83        link.innerHTML = (s.helpLabel || 'Read more') +
84          ' <span class="icon icon-ui-arrow-right" aria-hidden="true"></span>';
85        body.appendChild(link);
86      }
87
88      card.appendChild(thumb);
89      card.appendChild(body);
90      grid.appendChild(card);
91    });
92  }
93
94  function openLightbox(index) {
95    if (!lightbox || !lightboxImg) return;
96    var items = visibleScreenshots();
97    if (!items.length) return;
98    lightboxIndex = ((index % items.length) + items.length) % items.length;
99    var s = items[lightboxIndex];
100    lightboxImg.src = s.file;
101    lightboxImg.alt = s.alt || s.title;
102    lightboxCounter.textContent = (lightboxIndex + 1) + ' / ' + items.length;
103    lightbox.classList.add('active');
104    document.body.style.overflow = 'hidden';
105  }
106
107  function closeLightbox() {
108    lightbox.classList.remove('active');
109    document.body.style.overflow = '';
110    lightboxImg.src = '';
111  }
112
113  function step(delta) {
114    var items = visibleScreenshots();
115    if (!items.length) return;
116    openLightbox(lightboxIndex + delta);
117  }
118
119  if (lightbox && lightboxImg) {
120    lightboxClose.addEventListener('click', closeLightbox);
121    lightboxPrev.addEventListener('click', function () { step(-1); });
122    lightboxNext.addEventListener('click', function () { step(1); });
123    lightbox.addEventListener('click', function (e) {
124      if (e.target === lightbox) closeLightbox();
125    });
126    document.addEventListener('keydown', function (e) {
127      if (!lightbox.classList.contains('active')) return;
128      if (e.key === 'Escape') closeLightbox();
129      else if (e.key === 'ArrowLeft') step(-1);
130      else if (e.key === 'ArrowRight') step(1);
131    });
132  }
133
134  function init() {
135    var inline = document.getElementById('gallery-data');
136    if (!inline) {
137      setHidden(loading, true);
138      setHidden(error, false);
139      return;
140    }
141    try {
142      var data = JSON.parse(inline.textContent);
143      screenshots = (data && data.screenshots) || [];
144      setHidden(loading, true);
145      renderGrid();
146    } catch (e) {
147      setHidden(loading, true);
148      setHidden(error, false);
149    }
150  }
151
152  if (document.readyState === 'loading') {
153    document.addEventListener('DOMContentLoaded', init);
154  } else {
155    init();
156  }
157})();

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.