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

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

226 lines 9.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 (function () {
2 var typoMap = [
3 ['family','font-family'],['weight','font-weight'],['style','font-style'],
4 ['decoration','text-decoration'],['transform','text-transform'],
5 ['sizeDesktop','font-size-d'],['sizeTablet','font-size-t'],['sizeMobile','font-size-m'],
6 ['lineHeightDesktop','line-height-d'],['lineHeightTablet','line-height-t'],['lineHeightMobile','line-height-m'],
7 ['letterSpacingDesktop','letter-spacing-d'],['letterSpacingTablet','letter-spacing-t'],['letterSpacingMobile','letter-spacing-m'],
8 ['wordSpacingDesktop','word-spacing-d'],['wordSpacingTablet','word-spacing-t'],['wordSpacingMobile','word-spacing-m']
9 ];
10 function typoCssVarsForEl(typo, prefix, el) {
11 if (!typo || typeof typo !== 'object') return;
12 for (var i = 0; i < typoMap.length; i++) {
13 var v = typo[typoMap[i][0]];
14 if (v !== undefined && v !== '' && v !== null) el.style.setProperty(prefix + typoMap[i][1], String(v));
15 }
16 }
17
18 function init() {
19 document.querySelectorAll('.bkbg-ir-app').forEach(function (appEl) {
20 if (appEl.dataset.rendered) return;
21 appEl.dataset.rendered = '1';
22
23 var opts;
24 try { opts = JSON.parse(appEl.dataset.opts || '{}'); } catch (e) { opts = {}; }
25
26 var o = Object.assign({
27 imageUrl: '',
28 imageAlt: '',
29 trigger: 'scroll',
30 direction: 'left',
31 revealStyle: 'sweep',
32 aspectRatio: '16-9',
33 borderRadius: 8,
34 showOverlayLabel: true,
35 overlayLabel: 'Hover to reveal',
36 revealedLabel: '',
37 showRevealedLabel: false,
38 caption: '',
39 showCaption: false,
40 overlayOpacity: 75,
41 animationDuration: 600,
42 revealOnce: true,
43 scrollThreshold: 30,
44 overlayBg: '#1e1b4b',
45 overlayTextColor: '#ffffff',
46 captionColor: '#6b7280',
47 labelSize: 18,
48 maxWidth: 0,
49 }, opts);
50
51 if (!o.imageUrl) return;
52
53 // Aspect ratio
54 var RATIO_MAP = {
55 '1-1': '100%',
56 '4-3': '75%',
57 '3-2': '66.67%',
58 '16-9': '56.25%',
59 '21-9': '42.86%',
60 '9-16': '177.78%',
61 };
62
63 // Figure
64 var figure = document.createElement('figure');
65 figure.className = 'bkbg-ir-figure';
66 figure.style.margin = '0';
67 figure.style.position = 'relative';
68 typoCssVarsForEl(o.labelTypo, '--bkbg-ir-lb-', figure);
69 typoCssVarsForEl(o.captionTypo, '--bkbg-ir-cp-', figure);
70
71 // Container
72 var container = document.createElement('div');
73 container.className = 'bkbg-ir-container trigger-' + o.trigger;
74 container.style.position = 'relative';
75 container.style.overflow = 'hidden';
76 container.style.borderRadius = o.borderRadius + 'px';
77 container.style.lineHeight = '0';
78 if (o.maxWidth > 0) {
79 container.style.maxWidth = o.maxWidth + 'px';
80 container.style.margin = '0 auto';
81 }
82
83 if (o.aspectRatio !== 'auto' && RATIO_MAP[o.aspectRatio]) {
84 container.classList.add('is-fixed-ratio');
85 container.style.paddingTop = RATIO_MAP[o.aspectRatio];
86 container.style.height = '0';
87 } else {
88 container.classList.add('is-auto-ratio');
89 }
90
91 // Image
92 var img = document.createElement('img');
93 img.src = o.imageUrl;
94 img.alt = o.imageAlt;
95 img.className = 'bkbg-ir-img style-' + o.revealStyle;
96 img.style.width = '100%';
97 img.style.height = '100%';
98 img.style.display = 'block';
99 img.style.objectFit = 'cover';
100 img.style.transitionDuration = o.animationDuration + 'ms';
101 if (o.aspectRatio !== 'auto') {
102 img.style.position = 'absolute';
103 img.style.top = '0';
104 img.style.left = '0';
105 }
106
107 // Overlay
108 var overlay = document.createElement('div');
109 overlay.className = 'bkbg-ir-overlay style-' + o.revealStyle;
110 overlay.style.position = 'absolute';
111 overlay.style.inset = '0';
112 overlay.style.background = o.overlayBg;
113 overlay.style.opacity = String(o.overlayOpacity / 100);
114 overlay.style.display = 'flex';
115 overlay.style.alignItems = 'center';
116 overlay.style.justifyContent = 'center';
117 overlay.style.transitionDuration = o.animationDuration + 'ms';
118
119 if (o.revealStyle === 'sweep') {
120 overlay.classList.add('dir-' + o.direction);
121 }
122
123 if (o.showOverlayLabel && o.overlayLabel) {
124 var labelEl = document.createElement('div');
125 labelEl.className = 'bkbg-ir-overlay-label';
126 labelEl.textContent = o.overlayLabel;
127 labelEl.style.color = o.overlayTextColor;
128 labelEl.style.pointerEvents = 'none';
129 overlay.appendChild(labelEl);
130 }
131
132 // Revealed label
133 var revealedLabelEl = null;
134 if (o.showRevealedLabel && o.revealedLabel) {
135 revealedLabelEl = document.createElement('div');
136 revealedLabelEl.className = 'bkbg-ir-revealed-label';
137 revealedLabelEl.textContent = o.revealedLabel;
138 revealedLabelEl.style.color = o.overlayTextColor;
139 revealedLabelEl.style.fontSize = o.labelSize + 'px';
140 revealedLabelEl.style.fontWeight = '600';
141 revealedLabelEl.style.position = 'absolute';
142 revealedLabelEl.style.bottom = '12px';
143 revealedLabelEl.style.left = '12px';
144 revealedLabelEl.style.right = '12px';
145 revealedLabelEl.style.textAlign = 'center';
146 revealedLabelEl.style.opacity = '0';
147 revealedLabelEl.style.transition = 'opacity 0.3s ease 0.3s';
148 revealedLabelEl.style.pointerEvents = 'none';
149 // Add semi-transparent background for readability
150 revealedLabelEl.style.background = 'rgba(0,0,0,0.4)';
151 revealedLabelEl.style.borderRadius = '4px';
152 revealedLabelEl.style.padding = '6px 10px';
153 }
154
155 container.appendChild(img);
156 container.appendChild(overlay);
157 if (revealedLabelEl) container.appendChild(revealedLabelEl);
158 figure.appendChild(container);
159
160 // Caption
161 if (o.showCaption && o.caption) {
162 var cap = document.createElement('figcaption');
163 cap.className = 'bkbg-ir-caption';
164 cap.textContent = o.caption;
165 cap.style.color = o.captionColor;
166 figure.appendChild(cap);
167 }
168
169 // Reveal function
170 var revealed = false;
171 function reveal() {
172 if (revealed && o.revealOnce) return;
173 revealed = true;
174 container.classList.add('is-revealed');
175 if (revealedLabelEl) revealedLabelEl.style.opacity = '1';
176 }
177 function unreveal() {
178 if (o.revealOnce) return;
179 revealed = false;
180 container.classList.remove('is-revealed');
181 if (revealedLabelEl) revealedLabelEl.style.opacity = '0';
182 }
183
184 // Trigger
185 if (o.trigger === 'hover') {
186 container.style.cursor = 'default';
187 container.addEventListener('mouseenter', reveal);
188 container.addEventListener('mouseleave', unreveal);
189 } else if (o.trigger === 'click') {
190 container.style.cursor = 'pointer';
191 container.addEventListener('click', function () {
192 if (revealed) { unreveal(); } else { reveal(); }
193 });
194 } else {
195 // Scroll — IntersectionObserver
196 var threshold = Math.max(0.05, Math.min(0.95, o.scrollThreshold / 100));
197 if ('IntersectionObserver' in window) {
198 var io = new IntersectionObserver(function (entries) {
199 entries.forEach(function (entry) {
200 if (entry.isIntersecting) {
201 reveal();
202 if (o.revealOnce) io.unobserve(container);
203 } else {
204 unreveal();
205 }
206 });
207 }, { threshold: threshold });
208 io.observe(container);
209 } else {
210 // Fallback: reveal immediately
211 reveal();
212 }
213 }
214
215 appEl.parentNode.insertBefore(figure, appEl);
216 appEl.style.display = 'none';
217 });
218 }
219
220 if (document.readyState !== 'loading') {
221 init();
222 } else {
223 document.addEventListener('DOMContentLoaded', init);
224 }
225 })();
226