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 / thumbnail-gallery / frontend.js

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

337 lines 13.6 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 function buildGallery(appEl, o) {
5 if (!o.images || !o.images.length) return;
6
7 var images = o.images;
8 var current = 0;
9 var autoTimer = null;
10
11 var wrap = document.createElement('div');
12 wrap.className = 'bkbg-tgal-wrap';
13 wrap.style.paddingTop = (o.paddingTop || 0) + 'px';
14 wrap.style.paddingBottom = (o.paddingBottom || 0) + 'px';
15 if (o.bgColor) wrap.style.background = o.bgColor;
16
17 var inner = document.createElement('div');
18 inner.className = 'bkbg-tgal-inner';
19 inner.style.maxWidth = (o.maxWidth || 900) + 'px';
20 inner.style.margin = '0 auto';
21
22 var pos = o.thumbPosition || 'bottom';
23 var container = document.createElement('div');
24 container.className = 'bkbg-tgal-container pos-' + pos;
25 container.style.gap = '12px';
26
27 /* ── main image ── */
28 var main = document.createElement('div');
29 main.className = 'bkbg-tgal-main';
30 main.style.borderRadius = (o.mainBorderRadius || 12) + 'px';
31 main.style.overflow = 'hidden';
32 main.style.background = o.mainBg || '#000';
33 main.style.aspectRatio = (o.mainAspect || '16/9').replace('/', ' / ');
34 main.style.position = 'relative';
35
36 var mainImg = document.createElement('img');
37 mainImg.className = 'bkbg-tgal-main-img';
38 mainImg.src = images[0].url || '';
39 mainImg.alt = images[0].alt || '';
40 mainImg.style.objectFit = o.mainObjectFit || 'cover';
41 main.appendChild(mainImg);
42
43 /* caption */
44 var caption = null;
45 if (o.showCaptions) {
46 caption = document.createElement('div');
47 caption.className = 'bkbg-tgal-caption';
48 caption.style.background = o.captionBg || 'rgba(0,0,0,0.6)';
49 caption.style.color = o.captionColor || '#fff';
50 caption.textContent = images[0].caption || '';
51 if (!images[0].caption) caption.style.display = 'none';
52 main.appendChild(caption);
53 }
54
55 /* counter */
56 var counter = null;
57 if (o.showCounter) {
58 counter = document.createElement('div');
59 counter.className = 'bkbg-tgal-counter';
60 counter.style.background = o.counterBg || 'rgba(0,0,0,0.55)';
61 counter.style.color = o.counterColor || '#fff';
62 counter.textContent = '1 / ' + images.length;
63 main.appendChild(counter);
64 }
65
66 /* zoom */
67 if (o.showZoom) {
68 var zoom = document.createElement('button');
69 zoom.className = 'bkbg-tgal-zoom';
70 zoom.style.background = o.zoomIconBg || 'rgba(0,0,0,0.45)';
71 zoom.style.color = o.zoomIconColor || '#fff';
72 zoom.innerHTML = '➚';
73 zoom.setAttribute('aria-label', 'Zoom image');
74 zoom.addEventListener('click', function (e) {
75 e.stopPropagation();
76 openLightbox(current);
77 });
78 main.appendChild(zoom);
79 }
80
81 /* arrows */
82 if (o.showArrows && images.length > 1) {
83 var prevBtn = document.createElement('button');
84 prevBtn.className = 'bkbg-tgal-arrow prev';
85 prevBtn.style.background = o.arrowBg || 'rgba(0,0,0,0.45)';
86 prevBtn.style.color = o.arrowColor || '#fff';
87 prevBtn.innerHTML = '‹';
88 prevBtn.setAttribute('aria-label', 'Previous image');
89 prevBtn.addEventListener('click', function () { goTo((current - 1 + images.length) % images.length); });
90
91 var nextBtn = document.createElement('button');
92 nextBtn.className = 'bkbg-tgal-arrow next';
93 nextBtn.style.background = o.arrowBg || 'rgba(0,0,0,0.45)';
94 nextBtn.style.color = o.arrowColor || '#fff';
95 nextBtn.innerHTML = '›';
96 nextBtn.setAttribute('aria-label', 'Next image');
97 nextBtn.addEventListener('click', function () { goTo((current + 1) % images.length); });
98
99 main.appendChild(prevBtn);
100 main.appendChild(nextBtn);
101 }
102
103 /* ── thumbnail strip ── */
104 var strip = document.createElement('div');
105 strip.className = 'bkbg-tgal-strip';
106 strip.style.gap = (o.thumbGap || 8) + 'px';
107
108 var thumbEls = [];
109 var thumbW = (o.thumbSize || 72) * 1.4;
110 var thumbH = o.thumbSize || 72;
111 var isVert = pos === 'left' || pos === 'right';
112
113 images.forEach(function (img, idx) {
114 var thumb = document.createElement('div');
115 thumb.className = 'bkbg-tgal-thumb' + (idx === 0 ? ' is-active' : '');
116 thumb.style.width = (isVert ? thumbH : thumbW) + 'px';
117 thumb.style.height = thumbH + 'px';
118 thumb.style.borderRadius = (o.thumbBorderRadius || 6) + 'px';
119 thumb.style.backgroundImage = img.url ? 'url(' + img.url + ')' : 'none';
120 thumb.style.backgroundColor = o.thumbBg || '#e5e7eb';
121 thumb.style.border = (o.thumbActiveBorderWidth || 2) + 'px solid ' + (idx === 0 ? (o.thumbActiveBorder || '#6366f1') : 'transparent');
122 thumb.style.transition = 'border-color 0.15s, opacity 0.15s';
123 thumb.setAttribute('role', 'button');
124 thumb.setAttribute('tabindex', '0');
125 thumb.setAttribute('aria-label', img.title || img.alt || 'Image ' + (idx + 1));
126 thumb.addEventListener('click', function () { goTo(idx); });
127 thumb.addEventListener('keydown', function (e) { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); goTo(idx); } });
128 strip.appendChild(thumb);
129 thumbEls.push(thumb);
130 });
131
132 /* ── switch image ── */
133 function goTo(idx) {
134 if (idx === current || idx < 0 || idx >= images.length) return;
135 var prev = current;
136 current = idx;
137
138 var anim = o.animationType || 'fade';
139
140 if (anim === 'fade') {
141 mainImg.style.transition = 'opacity 0.3s ease';
142 mainImg.style.opacity = '0';
143 setTimeout(function () {
144 mainImg.src = images[idx].url || '';
145 mainImg.alt = images[idx].alt || '';
146 mainImg.style.opacity = '1';
147 }, 300);
148 } else {
149 /* slide */
150 mainImg.style.transition = 'transform 0.3s ease, opacity 0.3s ease';
151 var dir = idx > prev ? 1 : -1;
152 mainImg.style.transform = 'translateX(' + (-dir * 30) + 'px)';
153 mainImg.style.opacity = '0';
154 setTimeout(function () {
155 mainImg.src = images[idx].url || '';
156 mainImg.alt = images[idx].alt || '';
157 mainImg.style.transition = 'none';
158 mainImg.style.transform = 'translateX(' + (dir * 30) + 'px)';
159 mainImg.style.opacity = '0';
160 requestAnimationFrame(function () {
161 requestAnimationFrame(function () {
162 mainImg.style.transition = 'transform 0.3s ease, opacity 0.3s ease';
163 mainImg.style.transform = 'translateX(0)';
164 mainImg.style.opacity = '1';
165 });
166 });
167 }, 310);
168 }
169
170 if (caption) {
171 caption.textContent = images[idx].caption || '';
172 caption.style.display = images[idx].caption ? '' : 'none';
173 }
174 if (counter) {
175 counter.textContent = (idx + 1) + ' / ' + images.length;
176 }
177
178 /* update thumbs */
179 thumbEls.forEach(function (th, ti) {
180 th.classList.toggle('is-active', ti === idx);
181 th.style.border = (o.thumbActiveBorderWidth || 2) + 'px solid ' + (ti === idx ? (o.thumbActiveBorder || '#6366f1') : 'transparent');
182 });
183
184 /* scroll active thumb into view */
185 var activeTh = thumbEls[idx];
186 if (activeTh && activeTh.scrollIntoView) {
187 activeTh.scrollIntoView({ block: 'nearest', inline: 'nearest' });
188 }
189
190 /* reset autoplay timer */
191 if (o.autoPlay && autoTimer) {
192 clearTimeout(autoTimer);
193 scheduleAuto();
194 }
195 }
196
197 /* ── auto-play ── */
198 function scheduleAuto() {
199 autoTimer = setTimeout(function () {
200 goTo((current + 1) % images.length);
201 }, o.autoPlayDelay || 4000);
202 }
203
204 if (o.autoPlay && images.length > 1) {
205 scheduleAuto();
206 }
207
208 /* ── lightbox ── */
209 function openLightbox(startIdx) {
210 var lb = document.createElement('div');
211 lb.className = 'bkbg-tgal-lightbox';
212
213 var lbIdx = startIdx;
214
215 var lbImg = document.createElement('img');
216 lbImg.src = images[startIdx].url || '';
217 lbImg.alt = images[startIdx].alt || '';
218 lb.appendChild(lbImg);
219
220 var closeBtn = document.createElement('button');
221 closeBtn.className = 'bkbg-tgal-lb-close';
222 closeBtn.innerHTML = '&times;';
223 closeBtn.setAttribute('aria-label', 'Close');
224 closeBtn.addEventListener('click', function () { document.body.removeChild(lb); });
225 lb.appendChild(closeBtn);
226
227 if (images.length > 1) {
228 var lbPrev = document.createElement('button');
229 lbPrev.className = 'bkbg-tgal-lb-arrow prev';
230 lbPrev.innerHTML = '&#8249;';
231 lbPrev.setAttribute('aria-label', 'Previous');
232 lbPrev.addEventListener('click', function () {
233 lbIdx = (lbIdx - 1 + images.length) % images.length;
234 lbImg.src = images[lbIdx].url || '';
235 lbImg.alt = images[lbIdx].alt || '';
236 });
237
238 var lbNext = document.createElement('button');
239 lbNext.className = 'bkbg-tgal-lb-arrow next';
240 lbNext.innerHTML = '&#8250;';
241 lbNext.setAttribute('aria-label', 'Next');
242 lbNext.addEventListener('click', function () {
243 lbIdx = (lbIdx + 1) % images.length;
244 lbImg.src = images[lbIdx].url || '';
245 lbImg.alt = images[lbIdx].alt || '';
246 });
247
248 lb.appendChild(lbPrev);
249 lb.appendChild(lbNext);
250 }
251
252 lb.addEventListener('click', function (e) {
253 if (e.target === lb) document.body.removeChild(lb);
254 });
255
256 document.addEventListener('keydown', function lbKey(e) {
257 if (e.key === 'Escape') { if (document.body.contains(lb)) document.body.removeChild(lb); document.removeEventListener('keydown', lbKey); }
258 if (e.key === 'ArrowLeft') { lbIdx = (lbIdx - 1 + images.length) % images.length; lbImg.src = images[lbIdx].url || ''; lbImg.alt = images[lbIdx].alt || ''; }
259 if (e.key === 'ArrowRight') { lbIdx = (lbIdx + 1) % images.length; lbImg.src = images[lbIdx].url || ''; lbImg.alt = images[lbIdx].alt || ''; }
260 });
261
262 document.body.appendChild(lb);
263 }
264
265 /* ── assemble ── */
266 if (pos === 'top') {
267 container.appendChild(strip);
268 container.appendChild(main);
269 } else if (pos === 'left') {
270 container.appendChild(strip);
271 container.appendChild(main);
272 } else if (pos === 'right') {
273 container.appendChild(main);
274 container.appendChild(strip);
275 } else {
276 /* bottom (default) */
277 container.appendChild(main);
278 container.appendChild(strip);
279 }
280
281 inner.appendChild(container);
282 wrap.appendChild(inner);
283
284 appEl.parentNode.insertBefore(wrap, appEl);
285 appEl.style.display = 'none';
286 }
287
288 function init() {
289 document.querySelectorAll('.bkbg-tgal-app').forEach(function (appEl) {
290 if (appEl.dataset.rendered) return;
291 appEl.dataset.rendered = '1';
292
293 var opts;
294 try { opts = JSON.parse(appEl.dataset.opts || '{}'); } catch (e) { opts = {}; }
295
296 var o = Object.assign({
297 images: [],
298 thumbPosition: 'bottom',
299 thumbSize: 72,
300 thumbGap: 8,
301 thumbBorderRadius: 6,
302 mainAspect: '16/9',
303 mainBorderRadius: 12,
304 mainObjectFit: 'cover',
305 showCaptions: true,
306 showCounter: true,
307 showZoom: true,
308 showArrows: true,
309 animationType: 'fade',
310 autoPlay: false,
311 autoPlayDelay: 4000,
312 thumbActiveBorderWidth: 2,
313 maxWidth: 900,
314 paddingTop: 0,
315 paddingBottom: 0,
316 bgColor: '',
317 mainBg: '#000000',
318 captionBg: 'rgba(0,0,0,0.6)',
319 captionColor: '#ffffff',
320 counterBg: 'rgba(0,0,0,0.55)',
321 counterColor: '#ffffff',
322 thumbActiveBorder: '#6366f1',
323 thumbBg: '#e5e7eb',
324 arrowBg: 'rgba(0,0,0,0.45)',
325 arrowColor: '#ffffff',
326 zoomIconColor: '#ffffff',
327 zoomIconBg: 'rgba(0,0,0,0.45)'
328 }, opts);
329
330 buildGallery(appEl, o);
331 });
332 }
333
334 if (document.readyState !== 'loading') { init(); }
335 else { document.addEventListener('DOMContentLoaded', init); }
336 })();
337