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 / course-lesson / frontend.js

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

301 lines 12.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 map = {
4 family: 'font-family', weight: 'font-weight', style: 'font-style',
5 transform: 'text-transform', decoration: 'text-decoration',
6 sizeDesktop: 'font-size-d', sizeTablet: 'font-size-t', sizeMobile: 'font-size-m',
7 sizeUnit: null,
8 lineHeightDesktop: 'line-height-d', lineHeightTablet: 'line-height-t', lineHeightMobile: 'line-height-m',
9 lineHeightUnit: null,
10 letterSpacingDesktop: 'letter-spacing-d', letterSpacingTablet: 'letter-spacing-t', letterSpacingMobile: 'letter-spacing-m',
11 letterSpacingUnit: null,
12 wordSpacingDesktop: 'word-spacing-d', wordSpacingTablet: 'word-spacing-t', wordSpacingMobile: 'word-spacing-m',
13 wordSpacingUnit: null
14 };
15 var sizeU = typo.sizeUnit || 'px';
16 var lhU = typo.lineHeightUnit || '';
17 var lsU = typo.letterSpacingUnit || 'px';
18 var wsU = typo.wordSpacingUnit || 'px';
19 Object.keys(map).forEach(function (k) {
20 var css = map[k]; if (!css) return;
21 var v = typo[k]; if (v === undefined || v === '' || v === null) return;
22 if (/size|spacing/i.test(k)) {
23 var u = /letterSpacing/.test(k) ? lsU : /wordSpacing/.test(k) ? wsU : /lineHeight/.test(k) ? lhU : sizeU;
24 v = v + u;
25 }
26 el.style.setProperty(prefix + css, v);
27 });
28 }
29
30 (function () {
31 'use strict';
32
33 function mk(tag, cls, styles) {
34 var d = document.createElement(tag);
35 if (cls) d.className = cls;
36 if (styles) Object.keys(styles).forEach(function (k) { d.style[k] = styles[k]; });
37 return d;
38 }
39 function tx(tag, cls, text, styles) {
40 var d = mk(tag, cls, styles);
41 d.textContent = text;
42 return d;
43 }
44 function ap(parent) {
45 Array.prototype.slice.call(arguments, 1).forEach(function (c) { if (c) parent.appendChild(c); });
46 return parent;
47 }
48
49 var resourceIcon = { article: '📄', video: '🎥', download: '⬇️', exercise: '✏️', link: '🔗' };
50 var diffInfo = {
51 beginner: { label: '🟢 Beginner', bg: '#dcfce7', color: '#14532d' },
52 intermediate: { label: '🟡 Intermediate', bg: '#fef9c3', color: '#713f12' },
53 advanced: { label: '🔴 Advanced', bg: '#fee2e2', color: '#991b1b' }
54 };
55
56 function sectionBoxStyle(type, a) {
57 if (type === 'tip') return { background: a.tipBg, color: a.tipColor, borderLeftColor: a.tipBorder };
58 if (type === 'warning') return { background: a.warningBg, color: a.warningColor, borderLeftColor: a.warningBorder };
59 if (type === 'note') return { background: a.noteBg, color: a.noteColor, borderLeftColor: a.noteBorder };
60 return null;
61 }
62
63 function sectionIcon(type) {
64 if (type === 'tip') return '💡 ';
65 if (type === 'warning') return '⚠️ ';
66 if (type === 'note') return '📝 ';
67 return '';
68 }
69
70 function pill(text, bg, color) {
71 var s = tx('span', 'bkbg-cl-pill', text);
72 s.style.background = bg;
73 s.style.color = color;
74 return s;
75 }
76
77 function sectionHead(label, accentColor) {
78 var h = tx('div', 'bkbg-cl-section-head', label);
79 h.style.color = accentColor;
80 h.style.borderBottomColor = accentColor;
81 return h;
82 }
83
84 function buildBlock(appEl) {
85 if (appEl.dataset.rendered) return;
86 appEl.dataset.rendered = '1';
87
88 var a = Object.assign({
89 lessonTitle: '', moduleTitle: '', showModule: true,
90 lessonNumber: '', showLessonNumber: true,
91 duration: '', showDuration: true,
92 difficulty: 'intermediate', showDifficulty: true,
93 instructor: '', showInstructor: true,
94 prerequisites: [], showPrerequisites: true, prerequisitesLabel: 'Prerequisites',
95 objectives: [], showObjectives: true, objectivesLabel: "What You'll Learn",
96 intro: '', showIntro: true,
97 sections: [], showSections: true,
98 resources: [], showResources: true, resourcesLabel: 'Resources',
99 prevLesson: '', prevLessonUrl: '#', nextLesson: '', nextLessonUrl: '#', showNav: true,
100 fontSize: 15, titleFontSize: 26, lineHeight: 170, borderRadius: 12,
101 bgColor: '#ffffff', borderColor: '#e5e7eb', headerBg: '#0f172a',
102 headerColor: '#ffffff', metaColor: '#94a3b8',
103 introBg: '#f0f9ff', introColor: '#0369a1',
104 objectiveBg: '#f0fdf4', objectiveColor: '#14532d', objectiveDot: '#22c55e',
105 prereqBg: '#f8fafc', prereqColor: '#374151', prereqDot: '#94a3b8',
106 textColor: '#374151', headingColor: '#111827',
107 tipBg: '#fefce8', tipColor: '#713f12', tipBorder: '#fbbf24',
108 warningBg: '#fff7ed', warningColor: '#9a3412', warningBorder: '#f97316',
109 noteBg: '#eff6ff', noteColor: '#1e40af', noteBorder: '#3b82f6',
110 resourceBg: '#f8fafc', accentColor: '#3b82f6', navBg: '#f8fafc'
111 }, JSON.parse(appEl.dataset.opts || '{}'));
112
113 var lh = (a.lineHeight / 100).toFixed(2);
114 var diff = diffInfo[a.difficulty] || diffInfo.intermediate;
115
116 var wrap = mk('div', 'bkbg-cl-wrap');
117 wrap.style.border = '1px solid ' + a.borderColor;
118 wrap.style.borderRadius = a.borderRadius + 'px';
119 wrap.style.overflow = 'hidden';
120 wrap.style.background = a.bgColor;
121 typoCssVarsForEl(a.typoTitle, '--bkbg-cles-ttl-', wrap);
122 typoCssVarsForEl(a.typoBody, '--bkbg-cles-body-', wrap);
123
124 // ---- Header ----
125 var header = mk('div', 'bkbg-cl-header');
126 header.style.background = a.headerBg;
127
128 // Breadcrumb
129 var breadcrumb = mk('div', 'bkbg-cl-breadcrumb');
130 if (a.showModule && a.moduleTitle) {
131 var mod = tx('span', 'bkbg-cl-module', a.moduleTitle);
132 mod.style.color = a.metaColor;
133 ap(breadcrumb, mod);
134 }
135 if (a.showModule && a.showLessonNumber) {
136 var sep = tx('span', 'bkbg-cl-sep', '/');
137 sep.style.color = a.metaColor;
138 ap(breadcrumb, sep);
139 }
140 if (a.showLessonNumber && a.lessonNumber) {
141 var lnum = tx('span', 'bkbg-cl-lesson-num', a.lessonNumber);
142 lnum.style.color = a.metaColor;
143 ap(breadcrumb, lnum);
144 }
145 ap(header, breadcrumb);
146
147 var titleEl = tx('h2', 'bkbg-cl-title', a.lessonTitle);
148 titleEl.style.color = a.headerColor;
149 ap(header, titleEl);
150
151 var meta = mk('div', 'bkbg-cl-meta');
152 if (a.showDuration && a.duration) ap(meta, pill('' + a.duration, 'rgba(255,255,255,.1)', '#cbd5e1'));
153 if (a.showDifficulty) ap(meta, pill(diff.label, diff.bg, diff.color));
154 if (a.showInstructor && a.instructor) ap(meta, pill('👤 ' + a.instructor, 'rgba(255,255,255,.1)', '#cbd5e1'));
155 ap(header, meta);
156 ap(wrap, header);
157
158 // ---- Body ----
159 var body = mk('div', 'bkbg-cl-body');
160
161 // Intro
162 if (a.showIntro && a.intro) {
163 var introDiv = mk('div', 'bkbg-cl-intro');
164 introDiv.style.background = a.introBg;
165 var introP = tx('p', '', a.intro);
166 introP.style.color = a.introColor;
167 introP.style.lineHeight = lh;
168 ap(introDiv, introP);
169 ap(body, introDiv);
170 }
171
172 // Objectives + Prerequisites
173 if (a.showObjectives || a.showPrerequisites) {
174 var learnRow = mk('div', 'bkbg-cl-learn-row');
175 var cols = (a.showObjectives && a.showPrerequisites) ? 2 : 1;
176 learnRow.style.gridTemplateColumns = cols === 2 ? '1fr 1fr' : '1fr';
177
178 if (a.showObjectives && a.objectives.length > 0) {
179 var objCard = mk('div', 'bkbg-cl-obj-card');
180 objCard.style.background = a.objectiveBg;
181 ap(objCard, sectionHead(a.objectivesLabel, a.accentColor));
182 var objList = mk('ul', 'bkbg-cl-list');
183 a.objectives.forEach(function (obj) {
184 var li = mk('li', 'bkbg-cl-list-item');
185 var dot = tx('span', 'bkbg-cl-list-dot', '');
186 dot.style.color = a.objectiveDot;
187 var txt = tx('span', '', obj);
188 txt.style.color = a.objectiveColor;
189 ap(li, dot, txt);
190 ap(objList, li);
191 });
192 ap(objCard, objList);
193 ap(learnRow, objCard);
194 }
195
196 if (a.showPrerequisites && a.prerequisites.length > 0) {
197 var preCard = mk('div', 'bkbg-cl-prereq-card');
198 preCard.style.background = a.prereqBg;
199 ap(preCard, sectionHead(a.prerequisitesLabel, a.accentColor));
200 var preList = mk('ul', 'bkbg-cl-list');
201 a.prerequisites.forEach(function (p) {
202 var li = mk('li', 'bkbg-cl-list-item');
203 var dot = tx('span', 'bkbg-cl-list-dot', '');
204 dot.style.color = a.prereqDot;
205 var txt = tx('span', '', p);
206 txt.style.color = a.prereqColor;
207 ap(li, dot, txt);
208 ap(preList, li);
209 });
210 ap(preCard, preList);
211 ap(learnRow, preCard);
212 }
213 ap(body, learnRow);
214 }
215
216 // Content Sections
217 if (a.showSections && a.sections.length > 0) {
218 var contentWrap = mk('div');
219 ap(contentWrap, sectionHead('Lesson Content', a.accentColor));
220 var secGrid = mk('div', 'bkbg-cl-sections');
221 a.sections.forEach(function (sec) {
222 var isBox = sec.type !== 'text';
223 var boxStyle = sectionBoxStyle(sec.type, a);
224 var secDiv = mk('div', isBox ? 'bkbg-cl-section bkbg-cl-section-box' : 'bkbg-cl-section');
225 if (boxStyle) {
226 Object.keys(boxStyle).forEach(function (k) { secDiv.style[k] = boxStyle[k]; });
227 }
228 var heading = tx('h4', '', sectionIcon(sec.type) + sec.heading);
229 heading.style.color = isBox ? 'inherit' : a.headingColor;
230 var content = tx('p', '', sec.content);
231 content.style.color = isBox ? 'inherit' : a.textColor;
232 content.style.lineHeight = lh;
233 ap(secDiv, heading, content);
234 ap(secGrid, secDiv);
235 });
236 ap(contentWrap, secGrid);
237 ap(body, contentWrap);
238 }
239
240 // Resources
241 if (a.showResources && a.resources.length > 0) {
242 var resWrap = mk('div');
243 ap(resWrap, sectionHead(a.resourcesLabel, a.accentColor));
244 var resGrid = mk('div', 'bkbg-cl-resources');
245 a.resources.forEach(function (r) {
246 var link = mk('a', 'bkbg-cl-resource');
247 link.href = r.url || '#';
248 link.target = '_blank';
249 link.rel = 'noopener noreferrer';
250 link.style.background = a.resourceBg;
251 link.style.borderLeftColor = a.accentColor;
252 var icon = tx('span', 'bkbg-cl-resource-icon', resourceIcon[r.type] || '🔗');
253 var title = tx('span', 'bkbg-cl-resource-title', r.title);
254 title.style.color = a.accentColor;
255 ap(link, icon, title);
256 ap(resGrid, link);
257 });
258 ap(resWrap, resGrid);
259 ap(body, resWrap);
260 }
261
262 ap(wrap, body);
263
264 // ---- Nav ----
265 if (a.showNav) {
266 var nav = mk('div', 'bkbg-cl-nav');
267 nav.style.background = a.navBg;
268 nav.style.borderTopColor = a.borderColor;
269
270 var prevDiv = mk('div', 'bkbg-cl-nav-prev');
271 var prevLabel = tx('div', 'bkbg-cl-nav-label', '← Previous');
272 var prevTitle = mk('a', 'bkbg-cl-nav-title');
273 prevTitle.href = a.prevLessonUrl || '#';
274 prevTitle.textContent = a.prevLesson;
275 prevTitle.style.color = a.accentColor;
276 ap(prevDiv, prevLabel, prevTitle);
277
278 var nextDiv = mk('div', 'bkbg-cl-nav-next');
279 var nextLabel = tx('div', 'bkbg-cl-nav-label', 'Next →');
280 var nextTitle = mk('a', 'bkbg-cl-nav-title');
281 nextTitle.href = a.nextLessonUrl || '#';
282 nextTitle.textContent = a.nextLesson;
283 nextTitle.style.color = a.accentColor;
284 ap(nextDiv, nextLabel, nextTitle);
285
286 ap(nav, prevDiv, nextDiv);
287 ap(wrap, nav);
288 }
289
290 appEl.innerHTML = '';
291 appEl.appendChild(wrap);
292 }
293
294 function init() {
295 document.querySelectorAll('.bkbg-course-lesson-app').forEach(buildBlock);
296 }
297
298 if (document.readyState !== 'loading') { init(); }
299 else { document.addEventListener('DOMContentLoaded', init); }
300 })();
301