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 / rotating-image-tiles / frontend.js

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

187 lines 7.8 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 var _typoKeys = {
5 family:'font-family', weight:'font-weight', style:'font-style',
6 decoration:'text-decoration', transform:'text-transform',
7 sizeDesktop:'font-size-d', sizeTablet:'font-size-t', sizeMobile:'font-size-m',
8 lineHeightDesktop:'line-height-d', lineHeightTablet:'line-height-t', lineHeightMobile:'line-height-m',
9 letterSpacingDesktop:'letter-spacing-d', letterSpacingTablet:'letter-spacing-t', letterSpacingMobile:'letter-spacing-m',
10 wordSpacingDesktop:'word-spacing-d', wordSpacingTablet:'word-spacing-t', wordSpacingMobile:'word-spacing-m'
11 };
12 function typoCssVarsForEl(el, obj, prefix) {
13 if (!obj || typeof obj !== 'object') return;
14 Object.keys(_typoKeys).forEach(function (k) {
15 var v = obj[k];
16 if (v === undefined || v === '' || v === null) return;
17 if (k === 'sizeDesktop' || k === 'sizeTablet' || k === 'sizeMobile') v = v + (obj.sizeUnit || 'px');
18 else if (k === 'lineHeightDesktop' || k === 'lineHeightTablet' || k === 'lineHeightMobile') v = v + (obj.lineHeightUnit || '');
19 else if (k === 'letterSpacingDesktop' || k === 'letterSpacingTablet' || k === 'letterSpacingMobile') v = v + (obj.letterSpacingUnit || 'px');
20 else if (k === 'wordSpacingDesktop' || k === 'wordSpacingTablet' || k === 'wordSpacingMobile') v = v + (obj.wordSpacingUnit || 'px');
21 el.style.setProperty(prefix + _typoKeys[k], String(v));
22 });
23 }
24
25 document.querySelectorAll('.bkbg-rit-app').forEach(function (app) {
26 var o;
27 try { o = JSON.parse(app.dataset.opts || '{}'); } catch (e) { return; }
28
29 var tiles = Array.isArray(o.tiles) ? o.tiles : [];
30 var columns = o.columns || 3;
31 var tileWidth = o.tileWidth || 300;
32 var tileHeight = o.tileHeight || 200;
33 var tileRadius = o.tileRadius || 16;
34 var flipDuration = o.flipDuration || 600;
35 var staggerDelay = o.staggerDelay || 300;
36 var autoFlip = !!o.autoFlip;
37 var autoInterval = o.autoInterval || 3000;
38 var flipOnHover = !!o.flipOnHover;
39 var flipAxis = o.flipAxis === 'X' ? 'X' : 'Y';
40 var showLabel = !!o.showLabel;
41 var labelSize = o.labelSize || 14;
42 var labelColor = o.labelColor || '#ffffff';
43 var labelBg = o.labelBg || 'rgba(0,0,0,0.5)';
44 var gap = o.gap || 16;
45
46 var reducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
47
48 /* ── Build grid ── */
49 var grid = document.createElement('div');
50 grid.className = 'bkbg-rit-grid bkbg-rit-axis-' + flipAxis.toLowerCase();
51 grid.style.gridTemplateColumns = 'repeat(' + columns + ', 1fr)';
52 grid.style.gap = gap + 'px';
53
54 typoCssVarsForEl(app, o.labelTypo, '--bkrit-lt-');
55
56 var tileElements = [];
57
58 tiles.forEach(function (tile, idx) {
59 /* outer wrapper (perspective) */
60 var wrapper = document.createElement('div');
61 wrapper.className = 'bkbg-rit-tile';
62 wrapper.style.width = tileWidth + 'px';
63 wrapper.style.height = tileHeight + 'px';
64 wrapper.style.borderRadius = tileRadius + 'px';
65 wrapper.style.maxWidth = '100%';
66
67 /* flip inner */
68 var inner = document.createElement('div');
69 inner.className = 'bkbg-rit-inner';
70 inner.style.transitionDuration = (reducedMotion ? 0 : flipDuration) + 'ms';
71
72 /* front face */
73 var front = document.createElement('div');
74 front.className = 'bkbg-rit-front';
75 front.style.borderRadius = tileRadius + 'px';
76 if (tile.frontUrl) {
77 front.style.backgroundImage = 'url(' + tile.frontUrl + ')';
78 } else {
79 front.style.background = tile.frontBg || '#6366f1';
80 }
81
82 /* back face */
83 var back = document.createElement('div');
84 back.className = 'bkbg-rit-back';
85 back.style.borderRadius = tileRadius + 'px';
86 if (tile.backUrl) {
87 back.style.backgroundImage = 'url(' + tile.backUrl + ')';
88 } else {
89 back.style.background = tile.backBg || '#a5b4fc';
90 }
91
92 /* label (on back face) */
93 if (showLabel && tile.label) {
94 var label = document.createElement('div');
95 label.className = 'bkbg-rit-label';
96 label.textContent = tile.label;
97 label.style.color = labelColor;
98 label.style.background = labelBg;
99 back.appendChild(label);
100 }
101
102 inner.appendChild(front);
103 inner.appendChild(back);
104 wrapper.appendChild(inner);
105 grid.appendChild(wrapper);
106
107 tileElements.push({ wrapper: wrapper, inner: inner, flipped: false });
108
109 /* flip on hover */
110 if (flipOnHover && !reducedMotion) {
111 wrapper.addEventListener('mouseenter', function () {
112 inner.classList.add('bkbg-rit-flipped');
113 tileElements[idx].flipped = true;
114 });
115 wrapper.addEventListener('mouseleave', function () {
116 inner.classList.remove('bkbg-rit-flipped');
117 tileElements[idx].flipped = false;
118 });
119 }
120
121 /* click to flip toggle */
122 wrapper.addEventListener('click', function () {
123 var tf = tileElements[idx];
124 tf.flipped = !tf.flipped;
125 tf.inner.classList.toggle('bkbg-rit-flipped', tf.flipped);
126 });
127 });
128
129 app.appendChild(grid);
130
131 /* ── Auto flip ── */
132 if (autoFlip && !reducedMotion) {
133 var currentIdx = 0;
134 var flipping = false;
135
136 function flipNext() {
137 if (flipping || tileElements.length === 0) return;
138 flipping = true;
139
140 var sequence = tileElements.map(function (_, i) { return i; });
141
142 sequence.forEach(function (i, order) {
143 setTimeout(function () {
144 tileElements[i].flipped = true;
145 tileElements[i].inner.classList.add('bkbg-rit-flipped');
146 }, order * staggerDelay);
147 });
148
149 var totalDelay = sequence.length * staggerDelay + flipDuration + 200;
150
151 setTimeout(function () {
152 sequence.forEach(function (i, order) {
153 setTimeout(function () {
154 tileElements[i].flipped = false;
155 tileElements[i].inner.classList.remove('bkbg-rit-flipped');
156 }, order * staggerDelay);
157 });
158
159 setTimeout(function () {
160 flipping = false;
161 }, sequence.length * staggerDelay + flipDuration);
162 }, totalDelay);
163 }
164
165 /* Use Intersection Observer to trigger only when visible */
166 var autoTimer = null;
167
168 function startAuto() {
169 if (autoTimer) return;
170 autoTimer = setInterval(flipNext, autoInterval + tileElements.length * staggerDelay + flipDuration * 2 + 600);
171 }
172 function stopAuto() {
173 if (autoTimer) { clearInterval(autoTimer); autoTimer = null; }
174 }
175
176 var observer = new IntersectionObserver(function (entries) {
177 entries.forEach(function (entry) {
178 if (entry.isIntersecting) { startAuto(); }
179 else { stopAuto(); }
180 });
181 }, { threshold: 0.1 });
182
183 observer.observe(app);
184 }
185 });
186 }());
187