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

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

273 lines 10.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 function typoCssVarsForEl(typo, prefix, el) {
2 if (!typo || typeof typo !== 'object') return;
3 var m = {
4 family: 'font-family',
5 weight: 'font-weight',
6 style: 'font-style',
7 decoration: 'text-decoration',
8 transform: 'text-transform',
9 sizeDesktop: 'font-size-d',
10 sizeTablet: 'font-size-t',
11 sizeMobile: 'font-size-m',
12 lineHeightDesktop: 'line-height-d',
13 lineHeightTablet: 'line-height-t',
14 lineHeightMobile: 'line-height-m',
15 letterSpacingDesktop: 'letter-spacing-d',
16 letterSpacingTablet: 'letter-spacing-t',
17 letterSpacingMobile: 'letter-spacing-m',
18 wordSpacingDesktop: 'word-spacing-d',
19 wordSpacingTablet: 'word-spacing-t',
20 wordSpacingMobile: 'word-spacing-m'
21 };
22 Object.keys(m).forEach(function (k) {
23 var v = typo[k];
24 if (v !== undefined && v !== '' && v !== null) {
25 el.style.setProperty(prefix + m[k], String(v));
26 }
27 });
28 }
29
30 document.addEventListener('DOMContentLoaded', function () {
31 document.querySelectorAll('.bkbg-ht-app').forEach(function (root) {
32 var opts = JSON.parse(root.dataset.opts || '{}');
33 initHorizontalTimeline(root, opts);
34 });
35 });
36
37 function initHorizontalTimeline(root, a) {
38 var items = a.items || [];
39 if (!items.length) return;
40
41 var containerH = a.containerHeight || 420;
42 var halfH = Math.round(containerH / 2);
43 var itemWidth = a.itemWidth || 220;
44 var itemGap = a.itemGap || 40;
45 var dotSize = a.dotSize || 16;
46 var trackPad = 48;
47
48 /* CSS vars */
49 root.style.setProperty('--ht-line-color', a.lineColor || '#6366f1');
50 root.style.setProperty('--ht-section-bg', a.sectionBg || '#f8fafc');
51
52 /* typography CSS vars */
53 typoCssVarsForEl(a.titleTypo, '--bkbg-ht-tt-', root);
54 typoCssVarsForEl(a.descTypo, '--bkbg-ht-desc-', root);
55 typoCssVarsForEl(a.dateTypo, '--bkbg-ht-date-', root);
56 /* legacy fallback vars */
57 if (a.titleFontSize && a.titleFontSize !== 13) root.style.setProperty('--bkbg-ht-tt-sz', a.titleFontSize + 'px');
58 if (a.titleFontWeight && a.titleFontWeight !== '600') root.style.setProperty('--bkbg-ht-tt-fw', a.titleFontWeight);
59 if (a.titleLineHeight && a.titleLineHeight !== 1.3) root.style.setProperty('--bkbg-ht-tt-lh', String(a.titleLineHeight));
60 if (a.descFontSize && a.descFontSize !== 11) root.style.setProperty('--bkbg-ht-desc-sz', a.descFontSize + 'px');
61 if (a.descLineHeight && a.descLineHeight !== 1.5) root.style.setProperty('--bkbg-ht-desc-lh', String(a.descLineHeight));
62 if (a.dateFontSize && a.dateFontSize !== 11) root.style.setProperty('--bkbg-ht-date-sz', a.dateFontSize + 'px');
63
64 /* section */
65 var section = document.createElement('div');
66 section.className = 'bkbg-ht-section';
67 section.style.cssText = 'background:' + (a.sectionBg || '#f8fafc') + ';padding:20px 0;';
68
69 /* track wrap */
70 var trackWrap = document.createElement('div');
71 trackWrap.className = 'bkbg-ht-track-wrap';
72 trackWrap.style.height = containerH + 'px';
73
74 /* line */
75 var line = document.createElement('div');
76 line.className = 'bkbg-ht-line';
77 line.style.cssText = 'top:' + halfH + 'px;height:' + (a.lineThickness || 3) + 'px;background:' + (a.lineColor || '#6366f1') + ';';
78 trackWrap.appendChild(line);
79
80 /* track */
81 var track = document.createElement('div');
82 track.className = 'bkbg-ht-track';
83 track.style.cssText = 'gap:' + itemGap + 'px;padding:0 ' + trackPad + 'px;height:' + containerH + 'px;min-width:max-content;';
84 trackWrap.appendChild(track);
85
86 /* build items */
87 items.forEach(function (item, idx) {
88 var isTop = a.layout === 'top' || (a.layout === 'alternating' ? idx % 2 === 0 : false);
89 if (a.layout === 'bottom') isTop = false;
90
91 var col = document.createElement('div');
92 col.className = 'bkbg-ht-item-col ' + (isTop ? 'bkbg-ht-top' : 'bkbg-ht-bottom');
93 col.style.cssText = 'height:' + containerH + 'px;width:' + itemWidth + 'px;';
94
95 /* card half-height = from center to top/bottom edge minus dot */
96 var cardAvailH = halfH - Math.round(dotSize / 2) - 8;
97
98 /* card */
99 var card = document.createElement('div');
100 card.className = 'bkbg-ht-card' + (a.animateOnScroll ? ' bkbg-ht-hidden' : '');
101 card.style.cssText = [
102 'width:' + itemWidth + 'px',
103 'max-height:' + (cardAvailH - 24) + 'px',
104 'overflow:hidden',
105 'background:' + (a.cardBg || '#fff'),
106 'border:1px solid ' + (a.cardBorderColor || '#e2e8f0'),
107 'border-radius:' + (a.cardRadius || 16) + 'px',
108 'padding:' + (a.cardPadding || 20) + 'px',
109 a.cardShadow ? 'box-shadow:0 4px 16px rgba(0,0,0,0.08)' : '',
110 'box-sizing:border-box',
111 ].filter(Boolean).join(';');
112
113 if (item.imageUrl) {
114 var img = document.createElement('img');
115 img.src = item.imageUrl;
116 img.className = 'bkbg-ht-card-img';
117 img.alt = item.title || '';
118 img.style.maxHeight = '80px';
119 card.appendChild(img);
120 }
121
122 if (a.showIcons && item.icon) {
123 var iconEl = document.createElement('div');
124 iconEl.className = 'bkbg-ht-card-icon';
125 iconEl.style.fontSize = (a.iconSize || 28) + 'px';
126 var _IP = window.bkbgIconPicker;
127 var _iType = item.iconType || 'custom-char';
128 if (_IP && _iType !== 'custom-char') {
129 var _in = _IP.buildFrontendIcon(_iType, item.icon, item.iconDashicon, item.iconImageUrl, item.iconDashiconColor);
130 if (_in) iconEl.appendChild(_in); else iconEl.textContent = item.icon || '';
131 } else {
132 iconEl.textContent = item.icon || '';
133 }
134 card.appendChild(iconEl);
135 }
136
137 if (a.showDates && item.date) {
138 var dateEl = document.createElement('div');
139 dateEl.className = 'bkbg-ht-card-date';
140 dateEl.style.color = a.dateColor || '#6366f1';
141 dateEl.textContent = item.date;
142 card.appendChild(dateEl);
143 }
144
145 if (item.title) {
146 var titleEl = document.createElement('div');
147 titleEl.className = 'bkbg-ht-card-title';
148 titleEl.style.color = a.titleColor || '#1e293b';
149 titleEl.textContent = item.title;
150 card.appendChild(titleEl);
151 }
152
153 if (item.description) {
154 var descEl = document.createElement('div');
155 descEl.className = 'bkbg-ht-card-desc';
156 descEl.style.color = a.descColor || '#64748b';
157 descEl.textContent = item.description;
158 card.appendChild(descEl);
159 }
160
161 /* connector rod */
162 var rod = document.createElement('div');
163 rod.className = 'bkbg-ht-connector';
164 rod.style.height = '8px';
165
166 /* dot */
167 var dot = document.createElement('div');
168 dot.className = 'bkbg-ht-dot';
169 dot.style.cssText = [
170 'width:' + dotSize + 'px',
171 'height:' + dotSize + 'px',
172 'background:' + (a.dotColor || '#6366f1'),
173 'border:3px solid ' + (a.dotBorderColor || '#fff'),
174 'box-shadow:0 0 0 3px ' + (a.dotColor || '#6366f1') + '33',
175 ].join(';');
176
177 if (isTop) {
178 col.appendChild(card);
179 col.appendChild(rod);
180 col.appendChild(dot);
181 } else {
182 col.appendChild(dot);
183 col.appendChild(rod);
184 col.appendChild(card);
185 }
186
187 /* spacer to fill remaining height */
188 col.style.justifyContent = isTop ? 'flex-start' : 'flex-end';
189
190 track.appendChild(col);
191 });
192
193 section.appendChild(trackWrap);
194
195 /* arrows */
196 if (a.showArrows) {
197 var arrowsDiv = document.createElement('div');
198 arrowsDiv.className = 'bkbg-ht-arrows';
199
200 var btnLeft = document.createElement('button');
201 var btnRight = document.createElement('button');
202 [btnLeft, btnRight].forEach(function (btn) {
203 btn.className = 'bkbg-ht-arrow';
204 btn.style.cssText = 'background:' + (a.arrowBg || '#6366f1') + ';color:' + (a.arrowColor || '#fff') + ';';
205 });
206 btnLeft.textContent = '';
207 btnRight.textContent = '';
208
209 btnLeft.addEventListener('click', function () {
210 trackWrap.scrollBy({ left: -(itemWidth + itemGap) * 2, behavior: 'smooth' });
211 });
212 btnRight.addEventListener('click', function () {
213 trackWrap.scrollBy({ left: (itemWidth + itemGap) * 2, behavior: 'smooth' });
214 });
215
216 arrowsDiv.appendChild(btnLeft);
217 arrowsDiv.appendChild(btnRight);
218 section.appendChild(arrowsDiv);
219 }
220
221 root.appendChild(section);
222
223 /* drag-to-scroll */
224 if (a.draggable !== false) {
225 var dragState = { active: false, startX: 0, scrollLeft: 0 };
226 trackWrap.addEventListener('mousedown', function (e) {
227 dragState.active = true;
228 dragState.startX = e.pageX - trackWrap.offsetLeft;
229 dragState.scrollLeft = trackWrap.scrollLeft;
230 trackWrap.classList.add('bkbg-ht-dragging');
231 });
232 document.addEventListener('mouseup', function () {
233 dragState.active = false;
234 trackWrap.classList.remove('bkbg-ht-dragging');
235 });
236 trackWrap.addEventListener('mousemove', function (e) {
237 if (!dragState.active) return;
238 e.preventDefault();
239 var x = e.pageX - trackWrap.offsetLeft;
240 var walk = (x - dragState.startX) * 1.4;
241 trackWrap.scrollLeft = dragState.scrollLeft - walk;
242 });
243 /* touch */
244 var touchStartX = 0, touchScrollLeft = 0;
245 trackWrap.addEventListener('touchstart', function (e) {
246 touchStartX = e.touches[0].pageX;
247 touchScrollLeft = trackWrap.scrollLeft;
248 }, { passive: true });
249 trackWrap.addEventListener('touchmove', function (e) {
250 var dx = touchStartX - e.touches[0].pageX;
251 trackWrap.scrollLeft = touchScrollLeft + dx;
252 }, { passive: true });
253 }
254
255 /* scroll-reveal */
256 if (a.animateOnScroll) {
257 var observer = new IntersectionObserver(function (entries) {
258 entries.forEach(function (entry) {
259 if (entry.isIntersecting) {
260 var idx = Array.from(track.children).indexOf(entry.target);
261 setTimeout(function () {
262 var card = entry.target.querySelector('.bkbg-ht-card');
263 if (card) { card.classList.remove('bkbg-ht-hidden'); card.classList.add('bkbg-ht-visible'); }
264 }, idx * 80);
265 observer.unobserve(entry.target);
266 }
267 });
268 }, { threshold: 0.1 });
269
270 track.querySelectorAll('.bkbg-ht-item-col').forEach(function (col) { observer.observe(col); });
271 }
272 }
273