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

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

288 lines 12.9 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 function mk(tag, cls, styles) {
5 var d = document.createElement(tag);
6 if (cls) d.className = cls;
7 if (styles) Object.keys(styles).forEach(function (k) { d.style[k] = styles[k]; });
8 return d;
9 }
10 function tx(tag, cls, text, styles) {
11 var d = mk(tag, cls, styles);
12 d.textContent = text;
13 return d;
14 }
15 function ap(parent) {
16 Array.prototype.slice.call(arguments, 1).forEach(function (c) { if (c) parent.appendChild(c); });
17 return parent;
18 }
19 function mkA(href, text, color) {
20 var a = document.createElement('a');
21 a.href = href || '#';
22 a.textContent = text;
23 if (color) a.style.color = color;
24 return a;
25 }
26
27 function difficultyBadge(diff) {
28 var map = {
29 beginner: { label: '🟢 Beginner', bg: '#dcfce7', color: '#14532d' },
30 intermediate: { label: '🟡 Intermediate', bg: '#fef9c3', color: '#713f12' },
31 advanced: { label: '🟠 Advanced', bg: '#ffedd5', color: '#9a3412' },
32 expert: { label: '🔴 Expert', bg: '#fee2e2', color: '#991b1b' }
33 };
34 return map[diff] || map.beginner;
35 }
36
37 var typoKeys = [
38 ['family','font-family'],['weight','font-weight'],['style','font-style'],
39 ['decoration','text-decoration'],['transform','text-transform'],
40 ['sizeDesktop','font-size-d'],['sizeTablet','font-size-t'],['sizeMobile','font-size-m'],
41 ['lineHeightDesktop','line-height-d'],['lineHeightTablet','line-height-t'],['lineHeightMobile','line-height-m'],
42 ['letterSpacingDesktop','letter-spacing-d'],['letterSpacingTablet','letter-spacing-t'],['letterSpacingMobile','letter-spacing-m'],
43 ['wordSpacingDesktop','word-spacing-d'],['wordSpacingTablet','word-spacing-t'],['wordSpacingMobile','word-spacing-m']
44 ];
45 function typoCssVarsForEl(el, typo, prefix) {
46 if (!typo || typeof typo !== 'object') return;
47 var u = typo.sizeUnit || 'px';
48 typoKeys.forEach(function (pair) {
49 var v = typo[pair[0]];
50 if (v === undefined || v === '' || v === null) return;
51 var css = (typeof v === 'number' && pair[0].indexOf('size') !== -1) ? v + u
52 : (typeof v === 'number') ? String(v) : v;
53 el.style.setProperty(prefix + pair[1], css);
54 });
55 }
56
57 function init() {
58 document.querySelectorAll('.bkbg-kb-article-app').forEach(function (appEl) {
59 if (appEl.dataset.rendered) return;
60 appEl.dataset.rendered = '1';
61
62 var opts;
63 try { opts = JSON.parse(appEl.dataset.opts || '{}'); } catch (e) { opts = {}; }
64
65 var o = Object.assign({
66 articleTitle: 'Knowledge Base Article',
67 category: '',
68 subcategory: '',
69 showCategory: true,
70 difficulty: 'beginner',
71 showDifficulty: true,
72 lastUpdated: '',
73 showLastUpdated: true,
74 readTime: '',
75 showReadTime: true,
76 appliesTo: '',
77 showAppliesTo: true,
78 intro: '',
79 showIntro: true,
80 showToc: true,
81 tocLabel: 'In this article',
82 sections: [],
83 tags: [],
84 showTags: true,
85 relatedArticles: [],
86 showRelated: true,
87 relatedLabel: 'Related Articles',
88 helpfulYes: 0,
89 helpfulNo: 0,
90 showHelpful: true,
91 helpfulLabel: 'Was this article helpful?',
92 fontSize: 15,
93 titleFontSize: 26,
94 lineHeight: 175,
95 borderRadius: 10,
96 maxWidth: 820,
97 bgColor: '#ffffff',
98 borderColor: '#e2e8f0',
99 headerBg: '#f8fafc',
100 headerColor: '#0f172a',
101 categoryColor: '#64748b',
102 titleColor: '#0f172a',
103 textColor: '#374151',
104 tocBg: '#f1f5f9',
105 tocColor: '#1e293b',
106 tocLinkColor: '#2563eb',
107 headingColor: '#0f172a',
108 sectionBorderColor: '#e5e7eb',
109 infoBg: '#eff6ff',
110 infoColor: '#1e40af',
111 infoBorderColor: '#93c5fd',
112 warningBg: '#fffbeb',
113 warningColor: '#92400e',
114 warningBorderColor: '#fcd34d',
115 stepNumberBg: '#2563eb',
116 stepNumberColor: '#ffffff',
117 accentColor: '#2563eb',
118 tagBg: '#f1f5f9',
119 tagColor: '#475569',
120 helpfulYesBg: '#dcfce7',
121 helpfulYesColor: '#14532d',
122 helpfulNoBg: '#fee2e2',
123 helpfulNoColor: '#991b1b'
124 }, opts);
125
126 var br = (o.borderRadius || 10) + 'px';
127 var db = difficultyBadge(o.difficulty);
128
129 var block = mk('div', 'bkbg-kba-block', {
130 border: '1px solid ' + o.borderColor,
131 borderRadius: br,
132 overflow: 'hidden',
133 maxWidth: (o.maxWidth || 820) + 'px'
134 });
135 typoCssVarsForEl(block, o.titleTypo, '--bkbg-kba-tt-');
136 typoCssVarsForEl(block, o.bodyTypo, '--bkbg-kba-bd-');
137 block.style.setProperty('--bkbg-kba-sec-border', o.sectionBorderColor || '#e5e7eb');
138
139 // ── Header ─────────────────────────────────────────────
140 var header = mk('div', 'bkbg-kba-header', {
141 background: o.headerBg,
142 borderBottom: '1px solid ' + o.borderColor,
143 borderRadius: (o.borderRadius || 10) + 'px ' + (o.borderRadius || 10) + 'px 0 0'
144 });
145
146 if (o.showCategory && o.category) {
147 var bc = tx('div', 'bkbg-kba-breadcrumb', o.category + (o.subcategory ? '' + o.subcategory : ''), { color: o.categoryColor });
148 ap(header, bc);
149 }
150
151 var titleEl = tx('h2', 'bkbg-kba-title', o.articleTitle, { color: o.titleColor });
152 ap(header, titleEl);
153
154 var meta = mk('div', 'bkbg-kba-meta', { color: o.categoryColor });
155 if (o.showDifficulty) {
156 ap(meta, tx('span', 'bkbg-kba-difficulty', db.label, { background: db.bg, color: db.color }));
157 }
158 if (o.showReadTime && o.readTime) ap(meta, tx('span', null, '' + o.readTime));
159 if (o.showLastUpdated && o.lastUpdated) ap(meta, tx('span', null, '🗓 Updated ' + o.lastUpdated));
160 if (o.showAppliesTo && o.appliesTo) ap(meta, tx('span', null, '�
161 ' + o.appliesTo));
162 ap(header, meta);
163 ap(block, header);
164
165 // ── Body ───────────────────────────────────────────────
166 var body = mk('div', 'bkbg-kba-body', { background: o.bgColor, color: o.textColor });
167
168 if (o.showIntro && o.intro) {
169 ap(body, tx('p', 'bkbg-kba-intro', o.intro));
170 }
171
172 // TOC
173 if (o.showToc && o.sections && o.sections.length) {
174 var toc = mk('div', 'bkbg-kba-toc', { background: o.tocBg });
175 ap(toc, tx('span', 'bkbg-kba-toc-label', o.tocLabel || 'In this article', { color: o.tocColor }));
176 var tocList = mk('ol', 'bkbg-kba-toc-list');
177 o.sections.forEach(function (s, i) {
178 var li = document.createElement('li');
179 var a = mkA('#bkbg-kba-sec-' + i, s.heading, o.tocLinkColor);
180 li.appendChild(a);
181 tocList.appendChild(li);
182 });
183 ap(toc, tocList);
184 ap(body, toc);
185 }
186
187 // Sections
188 var stepNum = 0;
189 (o.sections || []).forEach(function (s, i) {
190 var isStep = s.type === 'step';
191 var isInfo = s.type === 'info';
192 var isWarn = s.type === 'warning';
193 if (isStep) stepNum++;
194
195 var cls = 'bkbg-kba-section' + (isInfo ? ' is-info' : isWarn ? ' is-warning' : '');
196 var sec = mk('div', cls);
197 sec.id = 'bkbg-kba-sec-' + i;
198
199 if (isInfo) { sec.style.background = o.infoBg; sec.style.color = o.infoColor; sec.style.borderLeftColor = o.infoBorderColor; }
200 if (isWarn) { sec.style.background = o.warningBg; sec.style.color = o.warningColor; sec.style.borderLeftColor = o.warningBorderColor; }
201
202 var hRow = mk('div', null, { display: 'flex', alignItems: 'center', gap: '10px', marginBottom: '10px' });
203 if (isStep) {
204 var numEl = tx('span', 'bkbg-kba-step-num', String(stepNum), { background: o.stepNumberBg, color: o.stepNumberColor });
205 ap(hRow, numEl);
206 }
207 var icon = isInfo ? '💡 ' : isWarn ? '⚠️ ' : '';
208 var hEl = tx('h3', 'bkbg-kba-section-heading', icon + s.heading, {
209 color: isInfo ? o.infoColor : isWarn ? o.warningColor : o.headingColor,
210 margin: '0',
211 fontSize: '17px',
212 fontWeight: '700'
213 });
214 ap(hRow, hEl);
215 ap(sec, hRow);
216
217 ap(sec, tx('p', 'bkbg-kba-section-content', s.content || '', { color: isInfo ? o.infoColor : isWarn ? o.warningColor : o.textColor }));
218 ap(body, sec);
219 });
220
221 ap(block, body);
222
223 // ── Tags ──────────────────────────────────────────────
224 if (o.showTags && o.tags && o.tags.length) {
225 var tagsDiv = mk('div', 'bkbg-kba-tags');
226 o.tags.forEach(function (t) {
227 if (!t) return;
228 ap(tagsDiv, tx('span', 'bkbg-kba-tag', t, { background: o.tagBg, color: o.tagColor }));
229 });
230 ap(block, tagsDiv);
231 }
232
233 // ── Related ───────────────────────────────────────────
234 if (o.showRelated && o.relatedArticles && o.relatedArticles.length) {
235 var rel = mk('div', 'bkbg-kba-related', { background: o.bgColor });
236 ap(rel, tx('span', 'bkbg-kba-related-label', o.relatedLabel || 'Related Articles', { color: o.headingColor }));
237 var relUl = mk('ul', 'bkbg-kba-related-list');
238 o.relatedArticles.forEach(function (r) {
239 if (!r.title) return;
240 var li = document.createElement('li');
241 var a = mkA(r.url || '#', r.title, o.accentColor);
242 li.appendChild(a);
243 relUl.appendChild(li);
244 });
245 ap(rel, relUl);
246 ap(block, rel);
247 }
248
249 // ── Helpful ───────────────────────────────────────────
250 if (o.showHelpful) {
251 var helpful = mk('div', 'bkbg-kba-helpful', { background: o.bgColor });
252 ap(helpful, tx('span', 'bkbg-kba-helpful-label', o.helpfulLabel || 'Was this article helpful?'));
253
254 var yesBtn = tx('button', 'bkbg-kba-helpful-btn', '👍 Yes (' + (o.helpfulYes || 0) + ')', { background: o.helpfulYesBg, color: o.helpfulYesColor });
255 var noBtn = tx('button', 'bkbg-kba-helpful-btn', '👎 No (' + (o.helpfulNo || 0) + ')', { background: o.helpfulNoBg, color: o.helpfulNoColor });
256
257 yesBtn.type = 'button';
258 noBtn.type = 'button';
259
260 var voted = false;
261 yesBtn.addEventListener('click', function () {
262 if (voted) return;
263 voted = true;
264 yesBtn.classList.add('is-voted');
265 yesBtn.textContent = '👍 Yes (' + ((o.helpfulYes || 0) + 1) + ')';
266 noBtn.disabled = true;
267 });
268 noBtn.addEventListener('click', function () {
269 if (voted) return;
270 voted = true;
271 noBtn.classList.add('is-voted');
272 noBtn.textContent = '👎 No (' + ((o.helpfulNo || 0) + 1) + ')';
273 yesBtn.disabled = true;
274 });
275
276 ap(helpful, yesBtn, noBtn);
277 ap(block, helpful);
278 }
279
280 appEl.parentNode.insertBefore(block, appEl);
281 appEl.style.display = 'none';
282 });
283 }
284
285 if (document.readyState !== 'loading') { init(); }
286 else { document.addEventListener('DOMContentLoaded', init); }
287 })();
288