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 / sticky-two-col / frontend.js

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

266 lines 13.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 (function () {
2 var _typoKeys = {
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(el, obj, prefix) {
11 if (!obj || typeof obj !== 'object') return;
12 Object.keys(_typoKeys).forEach(function (k) {
13 var v = obj[k];
14 if (v === undefined || v === '' || v === null) return;
15 if (k === 'sizeDesktop' || k === 'sizeTablet' || k === 'sizeMobile') v = v + (obj.sizeUnit || 'px');
16 else if (k === 'lineHeightDesktop' || k === 'lineHeightTablet' || k === 'lineHeightMobile') v = v + (obj.lineHeightUnit || '');
17 else if (k === 'letterSpacingDesktop' || k === 'letterSpacingTablet' || k === 'letterSpacingMobile') v = v + (obj.letterSpacingUnit || 'px');
18 else if (k === 'wordSpacingDesktop' || k === 'wordSpacingTablet' || k === 'wordSpacingMobile') v = v + (obj.wordSpacingUnit || 'px');
19 el.style.setProperty(prefix + _typoKeys[k], String(v));
20 });
21 }
22
23 function init() {
24 document.querySelectorAll('.bkbg-s2c-app').forEach(function (appEl) {
25 if (appEl.dataset.rendered) return;
26 appEl.dataset.rendered = '1';
27 var opts;
28 try { opts = JSON.parse(appEl.dataset.opts || '{}'); } catch (e) { opts = {}; }
29 var o = Object.assign({
30 items: [], stickyPosition: 'right', splitRatio: '50-50',
31 stickyOffset: 80, imageRadius: 16, showDivider: true, showProgressBar: true,
32 iconSize: 36, gap: 80, paddingTop: 0, paddingBottom: 0,
33 bgColor: '', panelBg: '#f8f8fc', eyebrowColor: '#6366f1',
34 titleColor: '#111827', textColor: '#6b7280', iconBg: '#ede9fe',
35 dividerColor: '#e5e7eb', accentColor: '#6366f1'
36 }, opts);
37
38 var items = o.items || [];
39 if (!items.length) { appEl.style.display = 'none'; return; }
40
41 var ratioMap = { '50-50': [50, 50], '45-55': [45, 55], '55-45': [55, 45], '40-60': [40, 60], '60-40': [60, 40] };
42 var ratio = ratioMap[o.splitRatio] || [50, 50];
43 var isStickRight = o.stickyPosition === 'right';
44
45 function mk(tag, cls, style) {
46 var n = document.createElement(tag);
47 if (cls) n.className = cls;
48 if (style) Object.assign(n.style, style);
49 return n;
50 }
51
52 /* Section */
53 var section = mk('div', 'bkbg-s2c-section', {
54 background: o.bgColor || '',
55 paddingTop: o.paddingTop + 'px',
56 paddingBottom: o.paddingBottom + 'px'
57 });
58 typoCssVarsForEl(section, o.eyebrowTypo, '--bks2c-eb-');
59 typoCssVarsForEl(section, o.titleTypo, '--bks2c-tt-');
60 typoCssVarsForEl(section, o.bodyTypo, '--bks2c-bd-');
61 section.style.setProperty('--bks2c-title-fw', o.titleFontWeight || '800');
62 section.style.setProperty('--bks2c-title-lh', String(o.titleLineHeight || 1.2));
63 section.style.setProperty('--bks2c-body-lh', String(o.bodyLineHeight || 1.7));
64
65 var shell = mk('div', 'bkbg-s2c-shell');
66
67 /* Sticky panel */
68 var stickyColW = (isStickRight ? ratio[1] : ratio[0]);
69 var scrollColW = (isStickRight ? ratio[0] : ratio[1]);
70
71 var stickyCol = mk('div', 'bkbg-s2c-sticky', {
72 width: stickyColW + '%',
73 top: o.stickyOffset + 'px'
74 });
75
76 var panelImg = mk('div', 'bkbg-s2c-panel-img', {
77 borderRadius: o.imageRadius + 'px',
78 background: o.panelBg
79 });
80
81 var firstItem = items[0] || {};
82 var stickyImg = null;
83 var stickyPlaceholder = null;
84
85 if (firstItem.imageUrl) {
86 stickyImg = document.createElement('img');
87 stickyImg.src = firstItem.imageUrl;
88 stickyImg.alt = firstItem.imageAlt || '';
89 panelImg.appendChild(stickyImg);
90 } else {
91 stickyPlaceholder = mk('div', 'bkbg-s2c-panel-placeholder', {
92 background: ((firstItem.accentColor || o.accentColor) + '15'),
93 minHeight: '280px'
94 });
95 var _IP0 = window.bkbgIconPicker;
96 var _t0 = firstItem.iconType || 'custom-char';
97 if (_IP0 && _t0 !== 'custom-char') {
98 var _n0 = _IP0.buildFrontendIcon(_t0, firstItem.icon, firstItem.iconDashicon, firstItem.iconImageUrl, firstItem.iconDashiconColor);
99 if (_n0) stickyPlaceholder.appendChild(_n0); else stickyPlaceholder.textContent = firstItem.icon || '🖼️';
100 } else { stickyPlaceholder.textContent = firstItem.icon || '🖼️'; }
101 panelImg.appendChild(stickyPlaceholder);
102 }
103
104 stickyCol.appendChild(panelImg);
105
106 /* Progress bar */
107 var progressBar = null;
108 var progressFill = null;
109 if (o.showProgressBar) {
110 progressBar = mk('div', 'bkbg-s2c-progress', { marginTop: '16px' });
111 progressFill = mk('div', 'bkbg-s2c-progress-fill', { background: o.accentColor });
112 progressBar.appendChild(progressFill);
113 stickyCol.appendChild(progressBar);
114 }
115
116 /* Scrolling items column */
117 var scrollCol = mk('div', 'bkbg-s2c-scroll', {
118 width: scrollColW + '%',
119 borderLeft: isStickRight && o.showDivider ? ('1px solid ' + o.dividerColor) : 'none',
120 borderRight: !isStickRight && o.showDivider ? ('1px solid ' + o.dividerColor) : 'none',
121 paddingLeft: isStickRight && o.showDivider ? '0' : '0'
122 });
123
124 var itemEls = [];
125 var activeIdx = 0;
126
127 function updateSticky(idx) {
128 activeIdx = idx;
129 var it = items[idx];
130 var accent = it.accentColor || o.accentColor;
131
132 /* update progress */
133 if (progressFill) {
134 progressFill.style.width = ((idx + 1) / items.length * 100) + '%';
135 progressFill.style.background = accent;
136 }
137
138 /* update image */
139 if (it.imageUrl) {
140 if (!stickyImg) {
141 stickyImg = document.createElement('img');
142 stickyImg.style.cssText = 'width:100%;height:100%;object-fit:cover;display:block;transition:opacity 0.4s ease;border-radius:' + o.imageRadius + 'px';
143 if (stickyPlaceholder) { panelImg.replaceChild(stickyImg, stickyPlaceholder); stickyPlaceholder = null; }
144 else { panelImg.appendChild(stickyImg); }
145 }
146 panelImg.classList.add('fading');
147 setTimeout(function () {
148 stickyImg.src = it.imageUrl;
149 stickyImg.alt = it.imageAlt || '';
150 panelImg.classList.remove('fading');
151 }, 200);
152 } else {
153 if (!stickyPlaceholder) {
154 stickyPlaceholder = mk('div', 'bkbg-s2c-panel-placeholder', { minHeight: '280px' });
155 if (stickyImg) { panelImg.replaceChild(stickyPlaceholder, stickyImg); stickyImg = null; }
156 else { panelImg.appendChild(stickyPlaceholder); }
157 }
158 var _IP2 = window.bkbgIconPicker;
159 var _pType = it.iconType || 'custom-char';
160 if (_IP2 && _pType !== 'custom-char') {
161 stickyPlaceholder.innerHTML = '';
162 var _pn = _IP2.buildFrontendIcon(_pType, it.icon, it.iconDashicon, it.iconImageUrl, it.iconDashiconColor);
163 if (_pn) stickyPlaceholder.appendChild(_pn); else stickyPlaceholder.textContent = it.icon || '🖼️';
164 } else { stickyPlaceholder.textContent = it.icon || '🖼️'; }
165 stickyPlaceholder.style.background = accent + '15';
166 }
167
168 /* update items active state */
169 itemEls.forEach(function (info, i) {
170 var isAct = i === idx;
171 var iAccent = items[i].accentColor || o.accentColor;
172 info.el.classList.toggle('active', isAct);
173 if (isStickRight) {
174 info.el.style.borderLeft = '3px solid ' + (isAct ? iAccent : 'transparent');
175 info.el.style.paddingLeft = '24px';
176 } else {
177 info.el.style.borderRight = '3px solid ' + (isAct ? iAccent : 'transparent');
178 info.el.style.paddingRight = '24px';
179 }
180 info.icon.style.background = isAct ? (iAccent + '20') : o.iconBg;
181 info.eyebrow.style.color = isAct ? iAccent : o.textColor;
182 });
183 }
184
185 items.forEach(function (it, idx) {
186 var accent = it.accentColor || o.accentColor;
187 var wrapper = mk('div', 'bkbg-s2c-item' + (idx === 0 ? ' active' : ''), {
188 paddingBottom: idx < items.length - 1 ? o.gap + 'px' : '28px',
189 paddingTop: '28px',
190 borderLeft: isStickRight ? ('3px solid ' + (idx === 0 ? accent : 'transparent')) : 'none',
191 paddingLeft: isStickRight ? '24px' : '0',
192 borderRight: !isStickRight ? ('3px solid ' + (idx === 0 ? accent : 'transparent')) : 'none',
193 paddingRight: !isStickRight ? '24px' : '0'
194 });
195
196 var inner = mk('div', 'bkbg-s2c-item-inner');
197
198 var iconEl = mk('div', 'bkbg-s2c-icon', {
199 width: o.iconSize + 'px',
200 height: o.iconSize + 'px',
201 background: idx === 0 ? (accent + '20') : o.iconBg,
202 fontSize: Math.round(o.iconSize * 0.55) + 'px'
203 });
204 var _IP = window.bkbgIconPicker;
205 var _iType = it.iconType || 'custom-char';
206 if (_IP && _iType !== 'custom-char') {
207 var _in = _IP.buildFrontendIcon(_iType, it.icon, it.iconDashicon, it.iconImageUrl, it.iconDashiconColor);
208 if (_in) iconEl.appendChild(_in); else iconEl.textContent = it.icon || '';
209 } else { iconEl.textContent = it.icon || ''; }
210 inner.appendChild(iconEl);
211
212 var textWrap = mk('div', 'bkbg-s2c-item-text');
213 var eyebrow = mk('div', 'bkbg-s2c-eyebrow', { color: idx === 0 ? accent : o.textColor });
214 eyebrow.textContent = it.eyebrow || '';
215 textWrap.appendChild(eyebrow);
216
217 var titleEl = mk('h3', 'bkbg-s2c-title', { color: o.titleColor });
218 titleEl.innerHTML = it.title || '';
219 textWrap.appendChild(titleEl);
220
221 var textEl = mk('p', 'bkbg-s2c-text', { color: o.textColor });
222 textEl.innerHTML = it.text || '';
223 textWrap.appendChild(textEl);
224
225 inner.appendChild(textWrap);
226 wrapper.appendChild(inner);
227 scrollCol.appendChild(wrapper);
228 itemEls.push({ el: wrapper, icon: iconEl, eyebrow: eyebrow });
229 });
230
231 /* IntersectionObserver */
232 var obs = new IntersectionObserver(function (entries) {
233 entries.forEach(function (entry) {
234 if (entry.isIntersecting) {
235 var idx = itemEls.findIndex(function (info) { return info.el === entry.target; });
236 if (idx < 0) {
237 /* IE-safe fallback */
238 for (var j = 0; j < itemEls.length; j++) {
239 if (itemEls[j].el === entry.target) { idx = j; break; }
240 }
241 }
242 if (idx >= 0) updateSticky(idx);
243 }
244 });
245 }, { threshold: 0.5 });
246
247 itemEls.forEach(function (info) { obs.observe(info.el); });
248
249 if (isStickRight) {
250 shell.appendChild(scrollCol);
251 shell.appendChild(stickyCol);
252 } else {
253 shell.appendChild(stickyCol);
254 shell.appendChild(scrollCol);
255 }
256
257 section.appendChild(shell);
258 updateSticky(0);
259 appEl.parentNode.insertBefore(section, appEl);
260 });
261 }
262
263 if (document.readyState !== 'loading') { init(); }
264 else { document.addEventListener('DOMContentLoaded', init); }
265 })();
266