PageSourceSearch

https://www.kvetnice.eu/js/pure/progres_gallery/progres_gallery.js?v=21

js kvetnice.eu collected 2026-09-24 10:15:30 UTC 16,317 bytes, 506 lines download raw bytes

1(function (window, document) {
2    'use strict';
3
4    var SELECTOR = '.magnific, .lightbox';
5    var STYLE_ID = 'progres-gallery-styles';
6    var ARROW_LEFT = '/images/universal/arrow-left-white.svg';
7    var ARROW_RIGHT = '/images/universal/arrow-right-white.svg';
8    var IMAGE_EXTENSIONS = /\.(avif|bmp|gif|jpe?g|png|svg|webp)(?:[?#].*)?$/i;
9    var VIDEO_PATTERNS = [
10        /youtube\.com/i,
11        /youtu\.be/i,
12        /vimeo\.com/i,
13        /\.mp4(?:[?#].*)?$/i,
14        /\.webm(?:[?#].*)?$/i,
15        /\.ogg(?:[?#].*)?$/i
16    ];
17
18    var state = {
19        initialized: false,
20        isOpen: false,
21        items: [],
22        index: 0,
23        lastTrigger: null,
24        renderId: 0
25    };
26
27    var dom = {};
28
29    function injectStyles() {
30        if (document.getElementById(STYLE_ID)) {
31            return;
32        }
33
34        var style = document.createElement('style');
35        style.id = STYLE_ID;
36        style.textContent = [
37            'body.progres-gallery-open{overflow:hidden;}',
38            '.pg-lightbox{position:fixed;inset:0;z-index:9999;display:none;padding:16px;background:rgba(8,11,16,.92);backdrop-filter:blur(3px);}',
39            '.pg-lightbox.pg-is-open{display:flex;align-items:center;justify-content:center;}',
40            '.pg-lightbox__dialog{position:relative;width:min(100%,1240px);height:min(calc(100vh - 32px),920px);display:flex;flex-direction:column;}',
41            '.pg-lightbox__close{position:absolute;top:0;right:0;z-index:3;width:48px;height:48px;border:0;border-radius:999px;background:rgba(255,255,255,.14);color:#fff;font-size:34px;line-height:1;cursor:pointer;transition:background-color .2s ease;}',
42            '.pg-lightbox__close:hover,.pg-lightbox__close:focus{background:rgba(255,255,255,.24);outline:none;}',
43            '.pg-lightbox__stage{position:relative;flex:1;display:flex;align-items:center;justify-content:center;padding:56px 72px 24px;}',
44            '.pg-lightbox__figure{position:relative;display:flex;align-items:center;justify-content:center;width:100%;height:100%;margin:0;}',
45            '.pg-lightbox__image{display:block;max-width:100%;max-height:100%;width:auto;height:auto;object-fit:contain;cursor:pointer;box-shadow:0 18px 50px rgba(0,0,0,.35);}',
46            '.pg-lightbox__status{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);padding:10px 16px;border-radius:999px;background:rgba(0,0,0,.45);color:#fff;font-size:14px;letter-spacing:.02em;}',
47            '.pg-lightbox__status[hidden]{display:none;}',
48            '.pg-lightbox__nav{position:absolute;top:50%;transform:translateY(-50%);z-index:2;display:flex;align-items:center;justify-content:center;width:56px;height:56px;border:0;border-radius:999px;background:rgba(255,255,255,.14);cursor:pointer;transition:background-color .2s ease;}',
49            '.pg-lightbox__nav:hover,.pg-lightbox__nav:focus{background:rgba(255,255,255,.24);outline:none;}',
50            '.pg-lightbox__nav[hidden]{display:none;}',
51            '.pg-lightbox__nav img{display:block;width:22px;height:22px;}',
52            '.pg-lightbox__nav--prev{left:0;}',
53            '.pg-lightbox__nav--next{right:0;}',
54            '.pg-lightbox__footer{min-height:28px;display:flex;align-items:center;justify-content:center;padding:0 72px 8px;color:#fff;text-align:center;}',
55            '.pg-lightbox__meta{display:flex;flex-direction:column;gap:6px;align-items:center;max-width:100%;}',
56            '.pg-lightbox__counter{font-size:15px;font-weight:600;letter-spacing:.02em;}',
57            '.pg-lightbox__caption{font-size:14px;line-height:1.4;color:rgba(255,255,255,.86);}',
58            '.pg-lightbox__caption:empty{display:none;}',
59            '@media (max-width: 767px){',
60            '.pg-lightbox{padding:12px;}',
61            '.pg-lightbox__dialog{height:calc(100vh - 24px);}',
62            '.pg-lightbox__close{top:4px;right:4px;width:44px;height:44px;font-size:30px;}',
63            '.pg-lightbox__stage{padding:52px 8px 18px;}',
64            '.pg-lightbox__nav{width:44px;height:44px;background:rgba(255,255,255,.18);}',
65            '.pg-lightbox__nav--prev{left:4px;}',
66            '.pg-lightbox__nav--next{right:4px;}',
67            '.pg-lightbox__nav img{width:18px;height:18px;}',
68            '.pg-lightbox__footer{padding:0 12px 4px;}',
69            '.pg-lightbox__counter{font-size:14px;}',
70            '.pg-lightbox__caption{font-size:13px;}',
71            '}'
72        ].join('');
73
74        document.head.appendChild(style);
75    }
76
77    function ensureDom() {
78        if (dom.overlay) {
79            return;
80        }
81
82        dom.overlay = document.createElement('div');
83        dom.overlay.className = 'pg-lightbox';
84        dom.overlay.setAttribute('aria-hidden', 'true');
85
86        dom.dialog = document.createElement('div');
87        dom.dialog.className = 'pg-lightbox__dialog';
88        dom.dialog.setAttribute('role', 'dialog');
89        dom.dialog.setAttribute('aria-modal', 'true');
90        dom.dialog.setAttribute('aria-label', 'Fotogalerie');
91        dom.dialog.tabIndex = -1;
92
93        dom.close = document.createElement('button');
94        dom.close.type = 'button';
95        dom.close.className = 'pg-lightbox__close';
96        dom.close.setAttribute('aria-label', 'Zavřít galerii');
97        dom.close.innerHTML = '×';
98
99        dom.stage = document.createElement('div');
100        dom.stage.className = 'pg-lightbox__stage';
101
102        dom.prev = createNavButton('pg-lightbox__nav pg-lightbox__nav--prev', 'Předchozí fotografie', ARROW_LEFT);
103        dom.next = createNavButton('pg-lightbox__nav pg-lightbox__nav--next', 'Další fotografie', ARROW_RIGHT);
104
105        dom.figure = document.createElement('figure');
106        dom.figure.className = 'pg-lightbox__figure';
107
108        dom.status = document.createElement('div');
109        dom.status.className = 'pg-lightbox__status';
110        dom.status.hidden = true;
111
112        dom.image = document.createElement('img');
113        dom.image.className = 'pg-lightbox__image';
114        dom.image.alt = '';
115        dom.image.draggable = false;
116
117        dom.footer = document.createElement('div');
118        dom.footer.className = 'pg-lightbox__footer';
119
120        dom.meta = document.createElement('div');
121        dom.meta.className = 'pg-lightbox__meta';
122
123        dom.counter = document.createElement('div');
124        dom.counter.className = 'pg-lightbox__counter';
125
126        dom.caption = document.createElement('div');
127        dom.caption.className = 'pg-lightbox__caption';
128
129        dom.figure.appendChild(dom.status);
130        dom.figure.appendChild(dom.image);
131        dom.stage.appendChild(dom.prev);
132        dom.stage.appendChild(dom.figure);
133        dom.stage.appendChild(dom.next);
134        dom.meta.appendChild(dom.counter);
135        dom.meta.appendChild(dom.caption);
136        dom.footer.appendChild(dom.meta);
137        dom.dialog.appendChild(dom.close);
138        dom.dialog.appendChild(dom.stage);
139        dom.dialog.appendChild(dom.footer);
140        dom.overlay.appendChild(dom.dialog);
141        document.body.appendChild(dom.overlay);
142    }
143
144    function createNavButton(className, label, iconPath) {
145        var button = document.createElement('button');
146        var image = document.createElement('img');
147
148        button.type = 'button';
149        button.className = className;
150        button.setAttribute('aria-label', label);
151
152        image.src = iconPath;
153        image.alt = '';
154        image.width = 22;
155        image.height = 22;
156
157        button.appendChild(image);
158        return button;
159    }
160
161    function init() {
162        if (state.initialized) {
163            return;
164        }
165
166        injectStyles();
167        ensureDom();
168        bindEvents();
169
170        state.initialized = true;
171    }
172
173    function bindEvents() {
174        document.addEventListener('click', onDocumentClick);
175        document.addEventListener('keydown', onDocumentKeydown);
176        dom.close.addEventListener('click', close);
177        dom.prev.addEventListener('click', showPrev);
178        dom.next.addEventListener('click', showNext);
179
180        dom.overlay.addEventListener('click', function (event) {
181            if (event.target === dom.overlay) {
182                close();
183            }
184        });
185
186        dom.image.addEventListener('click', function () {
187            if (state.items.length > 1) {
188                showNext();
189            }
190        });
191    }
192
193    function onDocumentClick(event) {
194        var trigger = closest(event.target, SELECTOR);
195
196        if (!trigger || event.defaultPrevented) {
197            return;
198        }
199
200        if (!isPrimaryActivation(event)) {
201            return;
202        }
203
204        if (!isSupportedImageLink(trigger)) {
205            return;
206        }
207
208        event.preventDefault();
209
210        var group = getGroup(trigger);
211        var index = indexOfLink(group, trigger);
212
213        if (!group.length || index < 0) {
214            return;
215        }
216
217        open(group, index, trigger);
218    }
219
220    function onDocumentKeydown(event) {
221        if (!state.isOpen) {
222            return;
223        }
224
225        if (event.key === 'Escape') {
226            event.preventDefault();
227            close();
228            return;
229        }
230
231        if (event.key === 'ArrowLeft') {
232            event.preventDefault();
233            showPrev();
234            return;
235        }
236
237        if (event.key === 'ArrowRight') {
238            event.preventDefault();
239            showNext();
240        }
241    }
242
243    function isPrimaryActivation(event) {
244        return event.button === 0 && !event.metaKey && !event.ctrlKey && !event.shiftKey && !event.altKey;
245    }
246
247    function isSupportedImageLink(link) {
248        if (!link || hasClass(link, 'magnific-video')) {
249            return false;
250        }
251
252        var href = getHref(link);
253
254        if (!href) {
255            return false;
256        }
257
258        if (/^(#|javascript:|mailto:|tel:)/i.test(href)) {
259            return false;
260        }
261
262        for (var i = 0; i < VIDEO_PATTERNS.length; i += 1) {
263            if (VIDEO_PATTERNS[i].test(href)) {
264                return false;
265            }
266        }
267
268        if (IMAGE_EXTENSIONS.test(href)) {
269            return true;
270        }
271
272        if (/\/images\//i.test(href)) {
273            return true;
274        }
275
276        if (/\/progres\/lib\/images(?:_setitem)?\.php/i.test(href)) {
277            return true;
278        }
279
280        return false;
281    }
282
283    function getGroup(trigger) {
284        var rel = (trigger.getAttribute('rel') || '').trim();
285        var candidates;
286        var gallery;
287
288        if (rel) {
289            candidates = filterLinks(document.querySelectorAll(SELECTOR), function (link) {
290                return isSupportedImageLink(link) && (link.getAttribute('rel') || '').trim() === rel;
291            });
292            if (candidates.length) {
293                return candidates;
294            }
295        }
296
297        gallery = closest(trigger, '.gallery');
298        if (gallery) {
299            candidates = filterLinks(gallery.querySelectorAll(SELECTOR), isSupportedImageLink);
300            if (candidates.length) {
301                return candidates;
302            }
303        }
304
305        candidates = filterLinks(document.querySelectorAll(SELECTOR), isSupportedImageLink);
306        return candidates.length ? candidates : [trigger];
307    }
308
309    function open(items, index, trigger) {
310        state.items = items;
311        state.index = index;
312        state.isOpen = true;
313        state.lastTrigger = trigger || null;
314
315        document.body.classList.add('progres-gallery-open');
316        dom.overlay.classList.add('pg-is-open');
317        dom.overlay.setAttribute('aria-hidden', 'false');
318
319        render();
320        dom.dialog.focus();
321    }
322
323    function close() {
324        if (!state.isOpen) {
325            return;
326        }
327
328        state.renderId += 1;
329        state.isOpen = false;
330        state.items = [];
331        state.index = 0;
332        dom.overlay.classList.remove('pg-is-open');
333        dom.overlay.setAttribute('aria-hidden', 'true');
334        document.body.classList.remove('progres-gallery-open');
335
336        hideStatus();
337        dom.image.removeAttribute('src');
338        dom.image.alt = '';
339        dom.caption.textContent = '';
340
341        if (state.lastTrigger && typeof state.lastTrigger.focus === 'function') {
342            state.lastTrigger.focus();
343        }
344    }
345
346    function showPrev() {
347        if (!state.items.length) {
348            return;
349        }
350
351        state.index = (state.index - 1 + state.items.length) % state.items.length;
352        render();
353    }
354
355    function showNext() {
356        if (!state.items.length) {
357            return;
358        }
359
360        state.index = (state.index + 1) % state.items.length;
361        render();
362    }
363
364    function render() {
365        var item = state.items[state.index];
366        var imageSrc = getHref(item);
367        var caption = getCaption(item);
368        var preloadImage = new Image();
369        var renderId = state.renderId + 1;
370
371        state.renderId = renderId;
372
373        dom.counter.textContent = (state.index + 1) + ' / ' + state.items.length;
374        dom.caption.textContent = caption;
375        dom.prev.hidden = state.items.length < 2;
376        dom.next.hidden = state.items.length < 2;
377        dom.image.style.visibility = 'hidden';
378        dom.image.alt = caption;
379
380        showStatus('Načítám...');
381
382        preloadImage.onload = function () {
383            if (!state.isOpen || renderId !== state.renderId) {
384                return;
385            }
386
387            dom.image.src = imageSrc;
388            dom.image.style.visibility = 'visible';
389            hideStatus();
390            preloadNeighbours();
391        };
392
393        preloadImage.onerror = function () {
394            if (!state.isOpen || renderId !== state.renderId) {
395                return;
396            }
397
398            dom.image.removeAttribute('src');
399            dom.image.style.visibility = 'hidden';
400            showStatus('Obrázek se nepodařilo načíst.');
401        };
402
403        preloadImage.src = imageSrc;
404    }
405
406    function preloadNeighbours() {
407        if (state.items.length < 2) {
408            return;
409        }
410
411        preloadItem((state.index + 1) % state.items.length);
412        preloadItem((state.index - 1 + state.items.length) % state.items.length);
413    }
414
415    function preloadItem(index) {
416        var href = getHref(state.items[index]);
417        if (!href) {
418            return;
419        }
420
421        var image = new Image();
422        image.src = href;
423    }
424
425    function showStatus(message) {
426        dom.status.textContent = message;
427        dom.status.hidden = false;
428    }
429
430    function hideStatus() {
431        dom.status.hidden = true;
432        dom.status.textContent = '';
433    }
434
435    function getCaption(link) {
436        if (!link) {
437            return '';
438        }
439
440        var title = (link.getAttribute('title') || '').trim();
441        if (title) {
442            return title;
443        }
444
445        var image = link.querySelector('img');
446        if (image && image.getAttribute('alt')) {
447            return image.getAttribute('alt').trim();
448        }
449
450        return (link.textContent || '').trim();
451    }
452
453    function getHref(link) {
454        if (!link) {
455            return '';
456        }
457
458        return (link.getAttribute('data-mfp-src') || link.getAttribute('href') || '').trim();
459    }
460
461    function filterLinks(nodeList, predicate) {
462        var output = [];
463
464        for (var i = 0; i < nodeList.length; i += 1) {
465            if (predicate(nodeList[i])) {
466                output.push(nodeList[i]);
467            }
468        }
469
470        return output;
471    }
472
473    function indexOfLink(items, trigger) {
474        for (var i = 0; i < items.length; i += 1) {
475            if (items[i] === trigger) {
476                return i;
477            }
478        }
479
480        return -1;
481    }
482
483    function closest(element, selector) {
484        while (element && element !== document) {
485            if (matches(element, selector)) {
486                return element;
487            }
488            element = element.parentNode;
489        }
490
491        return null;
492    }
493
494    function matches(element, selector) {
495        var matcher = element.matches || element.msMatchesSelector || element.webkitMatchesSelector;
496        return !!matcher && matcher.call(element, selector);
497    }
498
499    function hasClass(element, className) {
500        return !!element.classList && element.classList.contains(className);
501    }
502
503    window.ProgresGallery = {
504        init: init
505    };
506}(window, document));

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.