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 / knowledge-check / frontend.js

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

275 lines 11.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 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 shuffle(arr) {
26 var a = arr.slice();
27 for (var i = a.length - 1; i > 0; i--) {
28 var j = Math.floor(Math.random() * (i + 1));
29 var t = a[i]; a[i] = a[j]; a[j] = t;
30 }
31 return a;
32 }
33
34 function init() {
35 document.querySelectorAll('.bkbg-kc-app').forEach(function (appEl) {
36 if (appEl.dataset.rendered) return;
37 appEl.dataset.rendered = '1';
38
39 var opts;
40 try { opts = JSON.parse(appEl.dataset.opts || '{}'); } catch (e) { opts = {}; }
41 var o = Object.assign({
42 question: '',
43 options: [],
44 explanation: '',
45 showExplanation: true,
46 revealLabel: 'Reveal Answer',
47 correctLabel: '✓ Correct!',
48 incorrectLabel: '✗ Incorrect',
49 allowRetry: true,
50 retryLabel: 'Try Again',
51 shuffleOptions: false,
52 showIcon: true,
53 icon: '💡',
54 difficulty: '',
55 topic: '',
56 style: 'card',
57 borderRadius: 12,
58 bgColor: '#f8fafc',
59 borderColor: '#e2e8f0',
60 questionColor: '#0f172a',
61 optionBg: '#ffffff',
62 optionColor: '#334155',
63 optionBorderColor: '#cbd5e1',
64 correctBg: '#dcfce7',
65 correctColor: '#15803d',
66 incorrectBg: '#fee2e2',
67 incorrectColor: '#b91c1c',
68 accentColor: '#6366f1',
69 explanationBg: '#eff6ff',
70 explanationColor: '#1e40af',
71 revealBg: '#6366f1',
72 revealColor: '#ffffff'
73 }, opts);
74
75 var options = o.shuffleOptions ? shuffle(o.options) : o.options.slice();
76 var revealed = false;
77 var selected = null;
78
79 // ── build block ──────────────────────────────────────────────────────
80 var block = document.createElement('div');
81 block.className = 'bkbg-kc-block bkbg-kc-style-' + o.style;
82 block.style.background = o.bgColor;
83 block.style.borderColor = o.borderColor;
84 block.style.borderRadius = o.borderRadius + 'px';
85 typoCssVarsForEl(block, o.questionTypo, '--bkbg-kc-q-');
86 typoCssVarsForEl(block, o.optionTypo, '--bkbg-kc-o-');
87 typoCssVarsForEl(block, o.resultTypo, '--bkbg-kc-r-');
88
89 // Header
90 var header = document.createElement('div');
91 header.className = 'bkbg-kc-header';
92 if (o.showIcon && o.icon) {
93 var iconEl = document.createElement('span');
94 iconEl.className = 'bkbg-kc-icon';
95 iconEl.textContent = o.icon;
96 header.appendChild(iconEl);
97 }
98 if (o.topic || o.difficulty) {
99 var meta = document.createElement('div');
100 meta.className = 'bkbg-kc-meta';
101 if (o.topic) {
102 var topicEl = document.createElement('span');
103 topicEl.className = 'bkbg-kc-topic';
104 topicEl.textContent = o.topic;
105 topicEl.style.color = o.accentColor;
106 topicEl.style.borderColor = o.accentColor;
107 meta.appendChild(topicEl);
108 }
109 if (o.difficulty) {
110 var diffEl = document.createElement('span');
111 diffEl.className = 'bkbg-kc-difficulty';
112 diffEl.textContent = o.difficulty;
113 meta.appendChild(diffEl);
114 }
115 header.appendChild(meta);
116 }
117 block.appendChild(header);
118
119 // Question
120 var qEl = document.createElement('p');
121 qEl.className = 'bkbg-kc-question';
122 qEl.textContent = o.question;
123 qEl.style.color = o.questionColor;
124 block.appendChild(qEl);
125
126 // Options
127 var optionsWrap = document.createElement('div');
128 optionsWrap.className = 'bkbg-kc-options';
129
130 var optEls = options.map(function (opt, i) {
131 var label = document.createElement('div');
132 label.className = 'bkbg-kc-option';
133 label.style.background = o.optionBg;
134 label.style.color = o.optionColor;
135 label.style.borderColor = o.optionBorderColor;
136 label.style.borderRadius = Math.max(0, o.borderRadius - 4) + 'px';
137 label.setAttribute('role', 'button');
138 label.setAttribute('tabindex', '0');
139
140 var letter = document.createElement('span');
141 letter.className = 'bkbg-kc-opt-letter';
142 letter.textContent = String.fromCharCode(65 + i);
143 letter.style.background = o.accentColor;
144 letter.style.color = '#fff';
145
146 var txt = document.createElement('span');
147 txt.className = 'bkbg-kc-opt-text';
148 txt.textContent = opt.text;
149
150 label.appendChild(letter);
151 label.appendChild(txt);
152 optionsWrap.appendChild(label);
153
154 function pick() {
155 if (revealed) return;
156 selected = i;
157 optEls.forEach(function (el, j) {
158 el.classList.toggle('is-selected', j === i);
159 el.style.background = j === i ? o.optionBg : o.optionBg;
160 el.style.borderColor = j === i ? o.accentColor : o.optionBorderColor;
161 });
162 }
163
164 label.addEventListener('click', pick);
165 label.addEventListener('keydown', function (e) {
166 if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); pick(); }
167 });
168
169 return label;
170 });
171
172 block.appendChild(optionsWrap);
173
174 // Result badge
175 var resultEl = document.createElement('div');
176 resultEl.className = 'bkbg-kc-result';
177 block.appendChild(resultEl);
178
179 // Explanation
180 var explEl = document.createElement('div');
181 explEl.className = 'bkbg-kc-explanation';
182 explEl.style.background = o.explanationBg;
183 explEl.style.color = o.explanationColor;
184 explEl.style.borderRadius = Math.max(0, o.borderRadius - 4) + 'px';
185 if (o.showExplanation && o.explanation) {
186 var explStrong = document.createElement('strong');
187 explStrong.textContent = 'Explanation: ';
188 explEl.appendChild(explStrong);
189 explEl.appendChild(document.createTextNode(o.explanation));
190 }
191 block.appendChild(explEl);
192
193 // Actions
194 var actionsEl = document.createElement('div');
195 actionsEl.className = 'bkbg-kc-actions';
196
197 var revealBtn = document.createElement('button');
198 revealBtn.className = 'bkbg-kc-reveal-btn';
199 revealBtn.textContent = o.revealLabel;
200 revealBtn.style.background = o.revealBg;
201 revealBtn.style.color = o.revealColor;
202 revealBtn.style.borderRadius = Math.max(0, o.borderRadius - 2) + 'px';
203
204 var retryBtn = document.createElement('button');
205 retryBtn.className = 'bkbg-kc-retry-btn';
206 retryBtn.textContent = o.retryLabel;
207 retryBtn.style.borderRadius = Math.max(0, o.borderRadius - 2) + 'px';
208
209 actionsEl.appendChild(revealBtn);
210 if (o.allowRetry) actionsEl.appendChild(retryBtn);
211 block.appendChild(actionsEl);
212
213 function reveal() {
214 revealed = true;
215 revealBtn.style.display = 'none';
216
217 optEls.forEach(function (el, i) {
218 var opt = options[i];
219 if (opt.correct) {
220 el.style.background = o.correctBg;
221 el.style.color = o.correctColor;
222 el.style.borderColor = o.correctColor;
223 el.classList.add('is-correct');
224 el.querySelector('.bkbg-kc-opt-letter').style.background = o.correctColor;
225 } else if (i === selected) {
226 el.style.background = o.incorrectBg;
227 el.style.color = o.incorrectColor;
228 el.style.borderColor = o.incorrectColor;
229 el.classList.add('is-incorrect');
230 el.querySelector('.bkbg-kc-opt-letter').style.background = o.incorrectColor;
231 }
232 });
233
234 var isCorrect = selected !== null && options[selected] && options[selected].correct;
235 resultEl.textContent = isCorrect ? o.correctLabel : o.incorrectLabel;
236 resultEl.style.color = isCorrect ? o.correctColor : o.incorrectColor;
237 resultEl.classList.add('is-visible');
238
239 if (o.showExplanation && o.explanation) {
240 explEl.classList.add('is-visible');
241 }
242
243 if (o.allowRetry) {
244 retryBtn.classList.add('is-visible');
245 }
246 }
247
248 function retry() {
249 revealed = false;
250 selected = null;
251 revealBtn.style.display = '';
252 retryBtn.classList.remove('is-visible');
253 resultEl.classList.remove('is-visible');
254 explEl.classList.remove('is-visible');
255 optEls.forEach(function (el, i) {
256 el.className = 'bkbg-kc-option';
257 el.style.background = o.optionBg;
258 el.style.color = o.optionColor;
259 el.style.borderColor = o.optionBorderColor;
260 el.querySelector('.bkbg-kc-opt-letter').style.background = o.accentColor;
261 });
262 }
263
264 revealBtn.addEventListener('click', reveal);
265 retryBtn.addEventListener('click', retry);
266
267 appEl.parentNode.insertBefore(block, appEl);
268 appEl.style.display = 'none';
269 });
270 }
271
272 if (document.readyState !== 'loading') { init(); }
273 else { document.addEventListener('DOMContentLoaded', init); }
274 })();
275