PluginProbe
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor / 2.0.7
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor v2.0.7
2.0.13 2.0.12 2.0.11 2.0.10 2.0.9 trunk 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8
blockenberg / blocks / image-gallery / frontend.js

frontend.js in Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor 2.0.7, at blocks/image-gallery/frontend.js

171 lines 6.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 (function () {
2 'use strict';
3
4 /* ── Lightbox ──────────────────────────────────────────────────────────── */
5 var lb = null;
6 var lbImages = [];
7 var lbIndex = 0;
8
9 function createLightbox() {
10 if (lb) return lb;
11
12 var overlay = document.createElement('div');
13 overlay.className = 'bkbg-ig-lightbox';
14 overlay.setAttribute('role', 'dialog');
15 overlay.setAttribute('aria-modal', 'true');
16 overlay.setAttribute('aria-label', 'Image lightbox');
17
18 var inner = document.createElement('div');
19 inner.className = 'bkbg-ig-lb-inner';
20
21 var img = document.createElement('img');
22 img.className = 'bkbg-ig-lb-img';
23 img.alt = '';
24
25 var caption = document.createElement('div');
26 caption.className = 'bkbg-ig-lb-caption';
27
28 var closeBtn = document.createElement('button');
29 closeBtn.className = 'bkbg-ig-lb-close';
30 closeBtn.setAttribute('aria-label', 'Close lightbox');
31 closeBtn.innerHTML = '×';
32 closeBtn.addEventListener('click', closeLightbox);
33
34 var prevBtn = document.createElement('button');
35 prevBtn.className = 'bkbg-ig-lb-prev';
36 prevBtn.setAttribute('aria-label', 'Previous image');
37 prevBtn.innerHTML = '‹';
38 prevBtn.addEventListener('click', function () { navigate(-1); });
39
40 var nextBtn = document.createElement('button');
41 nextBtn.className = 'bkbg-ig-lb-next';
42 nextBtn.setAttribute('aria-label', 'Next image');
43 nextBtn.innerHTML = '›';
44 nextBtn.addEventListener('click', function () { navigate(1); });
45
46 var counter = document.createElement('div');
47 counter.className = 'bkbg-ig-lb-counter';
48
49 inner.appendChild(img);
50 inner.appendChild(caption);
51 overlay.appendChild(inner);
52 overlay.appendChild(closeBtn);
53 overlay.appendChild(prevBtn);
54 overlay.appendChild(nextBtn);
55 overlay.appendChild(counter);
56 document.body.appendChild(overlay);
57
58 overlay.addEventListener('click', function (e) {
59 if (e.target === overlay) closeLightbox();
60 });
61
62 document.addEventListener('keydown', function (e) {
63 if (!overlay.classList.contains('is-open')) return;
64 if (e.key === 'Escape') closeLightbox();
65 if (e.key === 'ArrowLeft') navigate(-1);
66 if (e.key === 'ArrowRight') navigate(1);
67 });
68
69 lb = { overlay: overlay, img: img, caption: caption, counter: counter, prevBtn: prevBtn, nextBtn: nextBtn };
70 return lb;
71 }
72
73 function openLightbox(images, index) {
74 lbImages = images;
75 lbIndex = index;
76 var l = createLightbox();
77 showImage(l);
78 l.overlay.classList.add('is-open');
79 document.body.style.overflow = 'hidden';
80 l.overlay.querySelector('.bkbg-ig-lb-close').focus();
81 }
82
83 function closeLightbox() {
84 if (!lb) return;
85 lb.overlay.classList.remove('is-open');
86 document.body.style.overflow = '';
87 }
88
89 function navigate(dir) {
90 lbIndex = (lbIndex + dir + lbImages.length) % lbImages.length;
91 showImage(lb);
92 }
93
94 function showImage(l) {
95 var entry = lbImages[lbIndex];
96 l.img.style.opacity = '0';
97 l.img.onload = function () { l.img.style.opacity = '1'; };
98 l.img.src = entry.url;
99 l.img.alt = entry.alt || '';
100 l.caption.textContent = entry.caption || '';
101 l.counter.textContent = (lbIndex + 1) + ' / ' + lbImages.length;
102 l.prevBtn.style.display = lbImages.length < 2 ? 'none' : '';
103 l.nextBtn.style.display = lbImages.length < 2 ? 'none' : '';
104 }
105
106 /* ── Init one gallery ──────────────────────────────────────────────────── */
107 function initGallery(wrapper) {
108 var grid = wrapper.querySelector('.bkbg-ig-grid');
109 if (!grid) return;
110
111 var useLightbox = grid.dataset.lightbox === '1';
112 var items = Array.from(wrapper.querySelectorAll('.bkbg-ig-item'));
113
114 /* Build image list for lightbox */
115 var imageList = items.map(function (item) {
116 var link = item.querySelector('.bkbg-ig-link');
117 var img = item.querySelector('.bkbg-ig-img');
118 var cap = item.querySelector('.bkbg-ig-caption');
119 return {
120 url : link ? link.href : (img ? img.src : ''),
121 alt : img ? (img.alt || '') : '',
122 caption: cap ? cap.textContent : ''
123 };
124 });
125
126 /* Attach lightbox click handlers */
127 if (useLightbox) {
128 items.forEach(function (item, idx) {
129 var link = item.querySelector('.bkbg-ig-lb-trigger');
130 if (!link) return;
131 link.addEventListener('click', function (e) {
132 e.preventDefault();
133 openLightbox(imageList, idx);
134 });
135 });
136 }
137
138 /* Filter bar */
139 var filterBtns = Array.from(wrapper.querySelectorAll('.bkbg-ig-filter-btn'));
140 if (filterBtns.length === 0) return;
141
142 filterBtns.forEach(function (btn) {
143 btn.addEventListener('click', function () {
144 var filter = btn.dataset.filter;
145 filterBtns.forEach(function (b) { b.classList.remove('is-active'); });
146 btn.classList.add('is-active');
147
148 items.forEach(function (item) {
149 if (filter === 'all' || item.dataset.category === filter) {
150 item.classList.remove('is-hidden');
151 } else {
152 item.classList.add('is-hidden');
153 }
154 });
155 });
156 });
157 }
158
159 /* ── Init all ────────────────────────────────────────────────────────── */
160 function initAll() {
161 var galleries = document.querySelectorAll('.bkbg-ig-wrapper');
162 galleries.forEach(initGallery);
163 }
164
165 if (document.readyState === 'loading') {
166 document.addEventListener('DOMContentLoaded', initAll);
167 } else {
168 initAll();
169 }
170 })();
171