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

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

338 lines 14.6 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 function buildMenu(appEl, o) {
26 var items = o.items || [];
27 if (!items.length) return;
28
29 /* ─ map each item to its closest L0 section index ─ */
30 var sectionMap = [];
31 var lastL0 = -1;
32 items.forEach(function (item, idx) {
33 if (item.level === 0) { lastL0 = idx; sectionMap[idx] = idx; }
34 else { sectionMap[idx] = lastL0; }
35 });
36
37 /* ─ determine which L0 sections have children ─ */
38 function sectionHasChildren(l0Idx) {
39 return items.some(function (it, i) { return i > l0Idx && it.level > 0 && sectionMap[i] === l0Idx; });
40 }
41
42 /* ─ open state: track which L0 sections are expanded ─ */
43 var openSections = {};
44 items.forEach(function (item, idx) {
45 if (item.level === 0 && o.defaultExpanded) openSections[idx] = true;
46 });
47
48 /* ─ active item ─ */
49 var activeIndex = (typeof o.activeIndex === 'number') ? o.activeIndex : -1;
50 /* try to auto-detect from current URL */
51 var currentHref = window.location.href;
52 items.forEach(function (item, idx) {
53 if (item.url && item.url !== '#' && currentHref.indexOf(item.url) !== -1) {
54 activeIndex = idx;
55 }
56 });
57
58 /* ─ outer wrap ─ */
59 var wrap = document.createElement('div');
60 wrap.className = 'bkbg-smnu-wrap';
61 wrap.style.paddingTop = (o.paddingTop || 0) + 'px';
62 wrap.style.paddingBottom = (o.paddingBottom || 0) + 'px';
63 if (o.bgColor) wrap.style.background = o.bgColor;
64 typoCssVarsForEl(wrap, o.headingTypo, '--bksmnu-ht-');
65 typoCssVarsForEl(wrap, o.itemTypo, '--bksmnu-it-');
66
67 /* ─ menu card ─ */
68 var menu = document.createElement('div');
69 menu.className = 'bkbg-smnu-menu style-' + (o.menuStyle || 'default');
70 menu.style.width = (o.width || 260) + 'px';
71 menu.style.maxWidth = '100%';
72 menu.style.background = o.menuBg || '#fff';
73 menu.style.border = '1px solid ' + (o.menuBorder || '#e5e7eb');
74 menu.style.borderRadius = (o.borderRadius || 8) + 'px';
75 menu.style.setProperty('--bkbg-smnu-border', o.menuBorder || '#e5e7eb');
76
77 /* ─ heading ─ */
78 if (o.showHeading && o.headingText) {
79 var heading = document.createElement('div');
80 heading.className = 'bkbg-smnu-heading';
81 heading.style.padding = (o.itemPaddingV || 8) + 'px ' + (o.itemPaddingH || 14) + 'px';
82 heading.style.color = o.headingColor || '#9ca3af';
83 heading.style.borderBottom = '1px solid ' + (o.dividerColor || '#e5e7eb');
84 heading.textContent = o.headingText;
85 menu.appendChild(heading);
86 }
87
88 /* ─ nav ─ */
89 var nav = document.createElement('nav');
90 nav.className = 'bkbg-smnu-nav';
91 nav.setAttribute('aria-label', o.headingText || 'Side menu');
92
93 /* ─ render all items (build DOM list) ─ */
94 var itemEls = []; /* {linkEl, childrenEl, arrowEl} per item */
95
96 items.forEach(function (item, idx) {
97 var isSection = item.level === 0;
98 var indent = item.level * 12;
99 var hasSectionChildren = isSection && sectionHasChildren(idx);
100
101 /* divider */
102 if (item.dividerBefore && o.showDividers) {
103 var div = document.createElement('div');
104 div.className = 'bkbg-smnu-divider';
105 div.style.background = o.dividerColor || '#e5e7eb';
106 div.style.margin = '6px ' + (o.itemPaddingH || 14) + 'px';
107 nav.appendChild(div);
108 }
109
110 /* link */
111 var link = document.createElement('a');
112 link.className = 'bkbg-smnu-item' + (idx === activeIndex ? ' is-active' : '');
113 link.href = item.url || '#';
114 link.style.paddingTop = (o.itemPaddingV || 8) + 'px';
115 link.style.paddingBottom = (o.itemPaddingV || 8) + 'px';
116 link.style.paddingRight = (o.itemPaddingH || 14) + 'px';
117 link.style.paddingLeft = ((o.itemPaddingH || 14) + indent) + 'px';
118 link.style.transition = 'background 0.15s, color 0.15s';
119
120 function applyActiveStyle(active) {
121 if (active) {
122 link.style.background = o.activeItemBg || '#ede9fe';
123 link.style.color = o.activeItemColor || '#6366f1';
124 link.style.fontWeight = '600';
125 link.style.borderLeft = '3px solid ' + (o.activeIndicatorColor || '#6366f1');
126 } else {
127 link.style.background = '';
128 link.style.color = isSection ? (o.sectionHeadingColor || '#111827') : (o.itemColor || '#374151');
129 link.style.fontWeight = isSection ? '700' : '400';
130 link.style.borderLeft = '3px solid transparent';
131 }
132 }
133 applyActiveStyle(idx === activeIndex);
134
135 link.addEventListener('mouseenter', function () {
136 if (!link.classList.contains('is-active')) {
137 link.style.background = o.itemHoverBg || '#f3f4f6';
138 link.style.color = o.itemHoverColor || '#111827';
139 }
140 });
141 link.addEventListener('mouseleave', function () {
142 if (!link.classList.contains('is-active')) {
143 link.style.background = '';
144 link.style.color = isSection ? (o.sectionHeadingColor || '#111827') : (o.itemColor || '#374151');
145 }
146 });
147
148 /* icon */
149 if (o.showIcons && item.icon) {
150 var icon = document.createElement('span');
151 icon.className = 'bkbg-smnu-icon';
152 var _IP = window.bkbgIconPicker;
153 var _iType = item.iconType || 'custom-char';
154 if (_IP && _iType !== 'custom-char') {
155 var _in = _IP.buildFrontendIcon(_iType, item.icon, item.iconDashicon, item.iconImageUrl, item.iconDashiconColor);
156 if (_in) icon.appendChild(_in); else icon.textContent = item.icon || '';
157 } else { icon.textContent = item.icon; }
158 link.appendChild(icon);
159 }
160
161 /* label */
162 var label = document.createElement('span');
163 label.className = 'bkbg-smnu-item-label';
164 label.textContent = item.label || '';
165 link.appendChild(label);
166
167 /* badge */
168 if (o.showBadges && item.badge) {
169 var badge = document.createElement('span');
170 badge.className = 'bkbg-smnu-badge';
171 badge.style.background = item.badgeColor || (o.badgeBg || '#6366f1');
172 badge.style.color = o.badgeColor || '#fff';
173 badge.textContent = item.badge;
174 link.appendChild(badge);
175 }
176
177 /* arrow for collapsible sections */
178 var arrowEl = null;
179 if (isSection && hasSectionChildren && o.collapsible) {
180 arrowEl = document.createElement('span');
181 arrowEl.className = 'bkbg-smnu-arrow' + (openSections[idx] ? ' is-open' : '');
182 arrowEl.style.color = o.arrowColor || '#9ca3af';
183 arrowEl.innerHTML = '▾';
184 link.appendChild(arrowEl);
185 }
186
187 nav.appendChild(link);
188
189 /* children container for L0 sections */
190 var childrenEl = null;
191 if (isSection && hasSectionChildren) {
192 childrenEl = document.createElement('div');
193 childrenEl.className = 'bkbg-smnu-children' + (openSections[idx] ? ' is-open' : '');
194 nav.appendChild(childrenEl);
195 }
196
197 itemEls.push({ linkEl: link, arrowEl: arrowEl, childrenEl: childrenEl, isSection: isSection, sectionIdx: sectionMap[idx] });
198 });
199
200 /* ─ re-parent L1/L2 items into their section's childrenEl ─ */
201 items.forEach(function (item, idx) {
202 if (item.level === 0) return;
203 var secIdx = sectionMap[idx];
204 if (secIdx < 0) return;
205 var secData = itemEls[secIdx];
206 if (!secData || !secData.childrenEl) return;
207
208 /* move link (and optional divider before it) into childrenEl */
209 var linkEl = itemEls[idx].linkEl;
210 if (linkEl.previousSibling && linkEl.previousSibling.classList && linkEl.previousSibling.classList.contains('bkbg-smnu-divider')) {
211 secData.childrenEl.appendChild(linkEl.previousSibling);
212 }
213 secData.childrenEl.appendChild(linkEl);
214 });
215
216 /* ─ click handlers for sections (collapse/expand) ─ */
217 items.forEach(function (item, idx) {
218 if (item.level !== 0) return;
219 var data = itemEls[idx];
220 var hasSectionChildren = sectionHasChildren(idx);
221
222 data.linkEl.addEventListener('click', function (e) {
223 /* toggle active */
224 if (!hasSectionChildren || !o.collapsible) {
225 e.preventDefault();
226 setActive(idx);
227 } else {
228 /* section heading: toggle children, do NOT navigate */
229 e.preventDefault();
230 toggleSection(idx);
231 }
232 });
233 });
234
235 /* ─ click handlers for L1/L2 nav items ─ */
236 items.forEach(function (item, idx) {
237 if (item.level === 0) return;
238 itemEls[idx].linkEl.addEventListener('click', function () {
239 setActive(idx);
240 });
241 });
242
243 function setActive(newIdx) {
244 itemEls.forEach(function (data, i) {
245 var isNow = i === newIdx;
246 if (isNow) { data.linkEl.classList.add('is-active'); }
247 else { data.linkEl.classList.remove('is-active'); }
248 var isSection = items[i].level === 0;
249 var active = data.linkEl.classList.contains('is-active');
250 if (active) {
251 data.linkEl.style.background = o.activeItemBg || '#ede9fe';
252 data.linkEl.style.color = o.activeItemColor || '#6366f1';
253 data.linkEl.style.fontWeight = '600';
254 data.linkEl.style.borderLeft = '3px solid ' + (o.activeIndicatorColor || '#6366f1');
255 } else {
256 data.linkEl.style.background = '';
257 data.linkEl.style.color = isSection ? (o.sectionHeadingColor || '#111827') : (o.itemColor || '#374151');
258 data.linkEl.style.fontWeight = isSection ? '700' : '400';
259 data.linkEl.style.borderLeft = '3px solid transparent';
260 }
261 });
262 }
263
264 function toggleSection(l0Idx) {
265 openSections[l0Idx] = !openSections[l0Idx];
266 var data = itemEls[l0Idx];
267 if (data.childrenEl) {
268 if (openSections[l0Idx]) {
269 data.childrenEl.classList.add('is-open');
270 } else {
271 data.childrenEl.classList.remove('is-open');
272 }
273 }
274 if (data.arrowEl) {
275 if (openSections[l0Idx]) { data.arrowEl.classList.add('is-open'); }
276 else { data.arrowEl.classList.remove('is-open'); }
277 }
278 }
279
280 menu.appendChild(nav);
281 wrap.appendChild(menu);
282
283 appEl.parentNode.insertBefore(wrap, appEl);
284 appEl.style.display = 'none';
285 }
286
287 function init() {
288 document.querySelectorAll('.bkbg-smnu-app').forEach(function (appEl) {
289 if (appEl.dataset.rendered) return;
290 appEl.dataset.rendered = '1';
291
292 var opts;
293 try { opts = JSON.parse(appEl.dataset.opts || '{}'); } catch (e) { opts = {}; }
294
295 var o = Object.assign({
296 items: [],
297 headingText: 'Documentation',
298 showHeading: true,
299 menuStyle: 'default',
300 collapsible: true,
301 defaultExpanded: true,
302 showIcons: true,
303 showBadges: true,
304 showDividers: true,
305 activeIndex: -1,
306 width: 260,
307 itemPaddingV: 8,
308 itemPaddingH: 14,
309 fontSize: 14,
310 headingSize: 11,
311 borderRadius: 8,
312 paddingTop: 0,
313 paddingBottom: 0,
314 bgColor: '',
315 menuBg: '#ffffff',
316 menuBorder: '#e5e7eb',
317 headingColor: '#9ca3af',
318 itemColor: '#374151',
319 itemHoverBg: '#f3f4f6',
320 itemHoverColor: '#111827',
321 activeItemBg: '#ede9fe',
322 activeItemColor: '#6366f1',
323 activeIndicatorColor: '#6366f1',
324 sectionHeadingColor: '#111827',
325 dividerColor: '#e5e7eb',
326 badgeBg: '#6366f1',
327 badgeColor: '#ffffff',
328 arrowColor: '#9ca3af'
329 }, opts);
330
331 buildMenu(appEl, o);
332 });
333 }
334
335 if (document.readyState !== 'loading') { init(); }
336 else { document.addEventListener('DOMContentLoaded', init); }
337 })();
338