PageSourceSearch

https://sndnmovie.com/wp-content/plugins/continuous-image-carousel…ontinuous-lightbox-modern.js?ver=1788331060

js sndnmovie.com collected 2026-09-25 01:32:23 UTC 6,150 bytes, 168 lines download raw bytes

1/**
2 * Continuous Image Carousel With Lightbox — modern lightbox
3 * Dependency-free replacement for the vendored FancyBox 1.3.6 fork.
4 * Opt-in via the "Lightbox Engine" setting; legacy engine is untouched.
5 */
6(function () {
7    'use strict';
8
9    var overlay, imgEl, captionEl, closeBtn, prevBtn, nextBtn;
10    var currentGroup = [];
11    var currentIndex = 0;
12    var lastFocused = null;
13
14    function buildOverlay() {
15        if (overlay) {
16            return;
17        }
18        overlay = document.createElement('div');
19        overlay.className = 'cicwl-modern-lightbox-overlay';
20        overlay.setAttribute('role', 'dialog');
21        overlay.setAttribute('aria-modal', 'true');
22        overlay.innerHTML =
23            '<button type="button" class="cicwl-modern-lightbox-close" aria-label="Close">&times;</button>' +
24            '<button type="button" class="cicwl-modern-lightbox-prev" aria-label="Previous image">&#10094;</button>' +
25            '<div class="cicwl-modern-lightbox-stage">' +
26                '<img class="cicwl-modern-lightbox-img" alt="" />' +
27                '<div class="cicwl-modern-lightbox-caption"></div>' +
28            '</div>' +
29            '<button type="button" class="cicwl-modern-lightbox-next" aria-label="Next image">&#10095;</button>';
30        document.body.appendChild(overlay);
31
32        imgEl = overlay.querySelector('.cicwl-modern-lightbox-img');
33        captionEl = overlay.querySelector('.cicwl-modern-lightbox-caption');
34        closeBtn = overlay.querySelector('.cicwl-modern-lightbox-close');
35        prevBtn = overlay.querySelector('.cicwl-modern-lightbox-prev');
36        nextBtn = overlay.querySelector('.cicwl-modern-lightbox-next');
37
38        closeBtn.addEventListener('click', close);
39        prevBtn.addEventListener('click', function () { show(currentIndex - 1); });
40        nextBtn.addEventListener('click', function () { show(currentIndex + 1); });
41        overlay.addEventListener('click', function (e) {
42            if (e.target === overlay) {
43                close();
44            }
45        });
46
47        var touchStartX = null;
48        overlay.addEventListener('touchstart', function (e) {
49            touchStartX = e.changedTouches[0].clientX;
50        }, { passive: true });
51        overlay.addEventListener('touchend', function (e) {
52            if (touchStartX === null) {
53                return;
54            }
55            var dx = e.changedTouches[0].clientX - touchStartX;
56            if (Math.abs(dx) > 40) {
57                dx < 0 ? show(currentIndex + 1) : show(currentIndex - 1);
58            }
59            touchStartX = null;
60        }, { passive: true });
61    }
62
63    function show(index) {
64        if (!currentGroup.length) {
65            return;
66        }
67        currentIndex = (index + currentGroup.length) % currentGroup.length;
68        var item = currentGroup[currentIndex];
69        imgEl.src = item.src;
70        imgEl.alt = item.caption || '';
71        captionEl.innerHTML = item.caption || '';
72        captionEl.style.display = item.caption ? '' : 'none';
73        var multi = currentGroup.length > 1;
74        prevBtn.style.display = multi ? '' : 'none';
75        nextBtn.style.display = multi ? '' : 'none';
76    }
77
78    function open(group, index) {
79        buildOverlay();
80        currentGroup = group;
81        lastFocused = document.activeElement;
82        show(index);
83        overlay.classList.add('is-open');
84        document.body.style.overflow = 'hidden';
85        closeBtn.focus();
86        document.addEventListener('keydown', onKeydown);
87    }
88
89    function close() {
90        if (!overlay) {
91            return;
92        }
93        overlay.classList.remove('is-open');
94        document.body.style.overflow = '';
95        document.removeEventListener('keydown', onKeydown);
96        if (lastFocused && lastFocused.focus) {
97            lastFocused.focus();
98        }
99    }
100
101    function onKeydown(e) {
102        if (e.key === 'Escape') {
103            close();
104            return;
105        }
106        if (e.key === 'ArrowLeft') {
107            show(currentIndex - 1);
108            return;
109        }
110        if (e.key === 'ArrowRight') {
111            show(currentIndex + 1);
112            return;
113        }
114        if (e.key === 'Tab') {
115            var focusable = [closeBtn, prevBtn, nextBtn];
116            var idx = focusable.indexOf(document.activeElement);
117            e.preventDefault();
118            if (e.shiftKey) {
119                focusable[idx <= 0 ? focusable.length - 1 : idx - 1].focus();
120            } else {
121                focusable[idx === focusable.length - 1 ? 0 : idx + 1].focus();
122            }
123        }
124    }
125
126    function collectGroup(trigger) {
127        var container = (trigger.closest && trigger.closest('.cicwl-slider-wrap')) || document;
128        var rel = trigger.getAttribute('rel');
129        var nodes = Array.prototype.slice.call(container.querySelectorAll('[data-cicwl-lightbox-src]'));
130        var seen = {};
131        var group = [];
132        nodes.forEach(function (node) {
133            if (rel && node.getAttribute('rel') !== rel) {
134                return;
135            }
136            var src = node.getAttribute('data-cicwl-lightbox-src');
137            // The modern carousel clones its item set for a seamless loop —
138            // de-duplicate so each image appears once in the lightbox group.
139            if (seen[src]) {
140                return;
141            }
142            seen[src] = true;
143            group.push({
144                src: src,
145                caption: node.getAttribute('data-cicwl-lightbox-caption') || ''
146            });
147        });
148        return group;
149    }
150
151    document.addEventListener('click', function (e) {
152        var trigger = e.target.closest && e.target.closest('[data-cicwl-lightbox-src]');
153        if (!trigger) {
154            return;
155        }
156        e.preventDefault();
157        var group = collectGroup(trigger);
158        var src = trigger.getAttribute('data-cicwl-lightbox-src');
159        var index = -1;
160        for (var i = 0; i < group.length; i++) {
161            if (group[i].src === src) {
162                index = i;
163                break;
164            }
165        }
166        open(group, index < 0 ? 0 : index);
167    });
168})();

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.