PluginProbe
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor / 2.0.11
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor v2.0.11
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-filter / frontend.js

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

260 lines 12.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 var typoMap = [
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(typo, prefix, el) {
13 if (!typo || typeof typo !== 'object') return;
14 for (var i = 0; i < typoMap.length; i++) {
15 var v = typo[typoMap[i][0]];
16 if (v !== undefined && v !== '' && v !== null) el.style.setProperty(prefix + typoMap[i][1], String(v));
17 }
18 }
19
20 var PRESETS = {
21 none: { brightness: 100, contrast: 100, saturation: 100, hueRotate: 0, blur: 0, sepia: 0, grayscale: 0, invert: 0, opacity: 100 },
22 vivid: { brightness: 105, contrast: 120, saturation: 150, hueRotate: 0, blur: 0, sepia: 0, grayscale: 0, invert: 0, opacity: 100 },
23 dramatic: { brightness: 90, contrast: 140, saturation: 110, hueRotate: 0, blur: 0, sepia: 0, grayscale: 0, invert: 0, opacity: 100 },
24 vintage: { brightness: 105, contrast: 95, saturation: 75, hueRotate: 0, blur: 0, sepia: 40, grayscale: 15, invert: 0, opacity: 95 },
25 noir: { brightness: 100, contrast: 125, saturation: 0, hueRotate: 0, blur: 0, sepia: 0, grayscale: 100,invert: 0, opacity: 100 },
26 warm: { brightness: 108, contrast: 100, saturation: 110, hueRotate: 20, blur: 0, sepia: 20, grayscale: 0, invert: 0, opacity: 100 },
27 cool: { brightness: 103, contrast: 105, saturation: 95, hueRotate: -30, blur: 0, sepia: 0, grayscale: 10, invert: 0, opacity: 100 },
28 faded: { brightness: 112, contrast: 78, saturation: 60, hueRotate: 0, blur: 0, sepia: 15, grayscale: 10, invert: 0, opacity: 90 },
29 cinema: { brightness: 88, contrast: 130, saturation: 85, hueRotate: 0, blur: 0, sepia: 8, grayscale: 0, invert: 0, opacity: 100 },
30 matte: { brightness: 110, contrast: 85, saturation: 70, hueRotate: 0, blur: 0, sepia: 10, grayscale: 5, invert: 0, opacity: 88 },
31 duotone: { brightness: 100, contrast: 120, saturation: 0, hueRotate: 0, blur: 0, sepia: 60, grayscale: 40, invert: 0, opacity: 100 },
32 highkey: { brightness: 145, contrast: 80, saturation: 80, hueRotate: 0, blur: 0, sepia: 0, grayscale: 0, invert: 0, opacity: 100 },
33 lowkey: { brightness: 55, contrast: 130, saturation: 100, hueRotate: 0, blur: 0, sepia: 0, grayscale: 0, invert: 0, opacity: 100 },
34 neonpop: { brightness: 110, contrast: 130, saturation: 200, hueRotate: 45, blur: 0, sepia: 0, grayscale: 0, invert: 0, opacity: 100 }
35 };
36
37 var SLIDER_CONFIG = [
38 { key: 'brightness', label: 'Brightness', min: 0, max: 300, unit: '%' },
39 { key: 'contrast', label: 'Contrast', min: 0, max: 300, unit: '%' },
40 { key: 'saturation', label: 'Saturation', min: 0, max: 400, unit: '%' },
41 { key: 'hueRotate', label: 'Hue Rotate', min: -180, max: 180, unit: '°' },
42 { key: 'blur', label: 'Blur', min: 0, max: 20, unit: 'px' },
43 { key: 'sepia', label: 'Sepia', min: 0, max: 100, unit: '%' },
44 { key: 'grayscale', label: 'Grayscale', min: 0, max: 100, unit: '%' },
45 { key: 'invert', label: 'Invert', min: 0, max: 100, unit: '%' },
46 { key: 'opacity', label: 'Opacity', min: 0, max: 100, unit: '%' }
47 ];
48
49 function buildFilterString(values) {
50 var parts = [];
51 if (values.brightness !== 100) parts.push('brightness(' + values.brightness + '%)');
52 if (values.contrast !== 100) parts.push('contrast(' + values.contrast + '%)');
53 if (values.saturation !== 100) parts.push('saturate(' + values.saturation + '%)');
54 if (values.hueRotate !== 0) parts.push('hue-rotate(' + values.hueRotate + 'deg)');
55 if (values.blur !== 0) parts.push('blur(' + values.blur + 'px)');
56 if (values.sepia !== 0) parts.push('sepia(' + values.sepia + '%)');
57 if (values.grayscale !== 0) parts.push('grayscale(' + values.grayscale + '%)');
58 if (values.invert !== 0) parts.push('invert(' + values.invert + '%)');
59 if (values.opacity !== 100) parts.push('opacity(' + values.opacity + '%)');
60 return parts.length ? parts.join(' ') : 'none';
61 }
62
63 function initImageFilter(appEl) {
64 var raw = appEl.dataset.opts;
65 if (!raw) return;
66 var opts;
67 try { opts = JSON.parse(raw); } catch (e) { return; }
68
69 if (!opts.imageUrl) { appEl.remove(); return; }
70
71 var defaults = {
72 brightness: opts.brightness, contrast: opts.contrast,
73 saturation: opts.saturation, hueRotate: opts.hueRotate,
74 blur: opts.blur, sepia: opts.sepia,
75 grayscale: opts.grayscale, invert: opts.invert,
76 opacity: opts.opacity
77 };
78 var current = Object.assign({}, defaults);
79
80 // Build wrapper
81 var wrap = document.createElement('div');
82 wrap.className = 'bkbg-if-wrap';
83 typoCssVarsForEl(opts.captionTypo, '--bkbg-if-cp-', wrap);
84
85 // Figure
86 var figure = document.createElement('figure');
87 figure.className = 'bkbg-if-figure';
88 figure.style.borderRadius = (opts.borderRadius || 12) + 'px';
89 figure.style.overflow = 'hidden';
90 if (opts.maxWidth) {
91 figure.style.maxWidth = opts.maxWidth + 'px';
92 figure.style.marginLeft = 'auto';
93 figure.style.marginRight = 'auto';
94 }
95 if (opts.borderColor) {
96 figure.style.border = '2px solid ' + opts.borderColor;
97 }
98
99 var img = document.createElement('img');
100 img.src = opts.imageUrl;
101 img.alt = opts.imageAlt || '';
102 img.style.display = 'block';
103 img.style.width = '100%';
104 img.style.borderRadius = (opts.borderRadius || 12) + 'px';
105 if (opts.imageHeight) img.style.height = opts.imageHeight + 'px';
106 if (opts.objectFit) img.style.objectFit = opts.objectFit;
107 if (opts.blendMode && opts.blendMode !== 'normal') img.style.mixBlendMode = opts.blendMode;
108 img.style.transition = 'filter ' + (opts.transitionMs || 300) + 'ms ease';
109 img.style.filter = buildFilterString(defaults);
110 figure.appendChild(img);
111
112 if (opts.overlayColor && opts.overlayOpacity > 0) {
113 var overlay = document.createElement('div');
114 overlay.className = 'bkbg-if-overlay';
115 overlay.style.background = opts.overlayColor;
116 overlay.style.opacity = opts.overlayOpacity / 100;
117 overlay.style.borderRadius = (opts.borderRadius || 12) + 'px';
118 figure.appendChild(overlay);
119 }
120
121 if (opts.caption) {
122 var figcap = document.createElement('figcaption');
123 figcap.className = 'bkbg-if-caption';
124 figcap.textContent = opts.caption;
125 figcap.style.color = opts.captionColor || '#555';
126 if (opts.captionBg) figcap.style.background = opts.captionBg;
127 figure.appendChild(figcap);
128 }
129
130 wrap.appendChild(figure);
131
132 // Interactive controls
133 if (opts.showControls) {
134 var controls = document.createElement('div');
135 controls.className = 'bkbg-if-controls';
136
137 var top = document.createElement('div');
138 top.className = 'bkbg-if-controls-top';
139
140 var heading = document.createElement('h4');
141 heading.textContent = 'Filter Controls';
142 top.appendChild(heading);
143
144 var rightTools = document.createElement('div');
145 rightTools.style.display = 'flex';
146 rightTools.style.gap = '8px';
147 rightTools.style.alignItems = 'center';
148
149 if (opts.showPresets) {
150 var presetSel = document.createElement('select');
151 presetSel.className = 'bkbg-if-preset-select';
152 [
153 ['none', 'None'],['vivid','Vivid'],['dramatic','Dramatic'],['vintage','Vintage'],
154 ['noir','Noir'],['warm','Warm Glow'],['cool','Cool Ice'],['faded','Faded'],
155 ['cinema','Cinema'],['matte','Matte'],['duotone','Duotone'],['highkey','High Key'],
156 ['lowkey','Low Key'],['neonpop','Neon Pop']
157 ].forEach(function (p) {
158 var opt = document.createElement('option');
159 opt.value = p[0];
160 opt.textContent = p[1];
161 if (p[0] === opts.preset) opt.selected = true;
162 presetSel.appendChild(opt);
163 });
164 presetSel.addEventListener('change', function () {
165 var p = PRESETS[presetSel.value];
166 if (!p) return;
167 Object.assign(current, p);
168 applyFilter();
169 updateSliders();
170 });
171 rightTools.appendChild(presetSel);
172 }
173
174 if (opts.showReset) {
175 var resetBtn = document.createElement('button');
176 resetBtn.className = 'bkbg-if-reset-btn';
177 resetBtn.textContent = 'Reset';
178 resetBtn.addEventListener('click', function () {
179 Object.assign(current, defaults);
180 applyFilter();
181 updateSliders();
182 if (opts.showPresets) presetSel.value = opts.preset || 'none';
183 });
184 rightTools.appendChild(resetBtn);
185 }
186
187 top.appendChild(rightTools);
188 controls.appendChild(top);
189
190 // Sliders
191 var sliderGrid = document.createElement('div');
192 sliderGrid.className = 'bkbg-if-sliders';
193
194 var sliderEls = {};
195 var valEls = {};
196
197 SLIDER_CONFIG.forEach(function (cfg) {
198 var row = document.createElement('div');
199 row.className = 'bkbg-if-slider-row';
200
201 var labelRow = document.createElement('div');
202 labelRow.className = 'bkbg-if-slider-label';
203
204 var lbl = document.createElement('span');
205 lbl.textContent = cfg.label;
206 labelRow.appendChild(lbl);
207
208 var valEl = document.createElement('span');
209 valEl.textContent = current[cfg.key] + cfg.unit;
210 valEls[cfg.key] = valEl;
211 labelRow.appendChild(valEl);
212 row.appendChild(labelRow);
213
214 var slider = document.createElement('input');
215 slider.type = 'range';
216 slider.className = 'bkbg-if-slider';
217 slider.min = cfg.min;
218 slider.max = cfg.max;
219 slider.step = 1;
220 slider.value = current[cfg.key];
221 sliderEls[cfg.key] = slider;
222
223 slider.addEventListener('input', function () {
224 current[cfg.key] = parseFloat(slider.value);
225 valEl.textContent = current[cfg.key] + cfg.unit;
226 applyFilter();
227 if (opts.showPresets) presetSel.value = 'none';
228 });
229
230 row.appendChild(slider);
231 sliderGrid.appendChild(row);
232 });
233
234 controls.appendChild(sliderGrid);
235 wrap.appendChild(controls);
236
237 function updateSliders() {
238 SLIDER_CONFIG.forEach(function (cfg) {
239 sliderEls[cfg.key].value = current[cfg.key];
240 valEls[cfg.key].textContent = current[cfg.key] + cfg.unit;
241 });
242 }
243 }
244
245 function applyFilter() {
246 img.style.filter = buildFilterString(current);
247 }
248
249 appEl.parentNode.replaceChild(wrap, appEl);
250 }
251
252 document.addEventListener('DOMContentLoaded', function () {
253 document.querySelectorAll('.bkbg-if-app').forEach(initImageFilter);
254 });
255
256 if (document.readyState === 'complete' || document.readyState === 'interactive') {
257 document.querySelectorAll('.bkbg-if-app').forEach(initImageFilter);
258 }
259 })();
260