@0m0g1/griot 0.1.19 → 0.1.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/blocks/BlockRenderer.js +43 -18
- package/src/viewer/Viewer.js +5 -0
package/package.json
CHANGED
|
@@ -432,42 +432,67 @@ function _renderQuiz(block, opts) {
|
|
|
432
432
|
submitBtn.textContent = 'Check answers';
|
|
433
433
|
submitBtn.addEventListener('click', () => {
|
|
434
434
|
let score = 0;
|
|
435
|
+
let answered = 0;
|
|
435
436
|
const answers = {};
|
|
437
|
+
|
|
436
438
|
questions.forEach((q, idx) => {
|
|
437
439
|
const qid = q.id || `q${idx}`;
|
|
438
440
|
const radios = form.querySelectorAll(`input[name="quiz_${block.id}_${qid}"]`);
|
|
439
441
|
let selected = null;
|
|
440
442
|
radios.forEach((r, i) => { if (r.checked) selected = i; });
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
if (
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
if (
|
|
448
|
-
|
|
443
|
+
|
|
444
|
+
// Only count attempted questions
|
|
445
|
+
if (selected !== null) {
|
|
446
|
+
answered++;
|
|
447
|
+
answers[qid] = selected;
|
|
448
|
+
const isCorrect = selected === q.correctOption;
|
|
449
|
+
if (isCorrect) score++;
|
|
450
|
+
|
|
451
|
+
const feedbackDiv = form.querySelector(`fieldset[data-index="${idx}"] .griot-quiz__feedback`);
|
|
452
|
+
if (feedbackDiv) {
|
|
453
|
+
if (isCorrect) {
|
|
454
|
+
feedbackDiv.textContent = '✓ Correct!';
|
|
455
|
+
feedbackDiv.className = 'griot-quiz__feedback griot-quiz__feedback--correct';
|
|
456
|
+
} else {
|
|
457
|
+
const correctAnswerText = q.options[q.correctOption];
|
|
458
|
+
feedbackDiv.innerHTML = `✗ Incorrect. Correct answer: ${escapeHtml(correctAnswerText)}. ${escapeHtml(q.explanation || '')}`;
|
|
459
|
+
feedbackDiv.className = 'griot-quiz__feedback griot-quiz__feedback--wrong';
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
} else {
|
|
463
|
+
// Unanswered — show skipped, don't penalise
|
|
464
|
+
const feedbackDiv = form.querySelector(`fieldset[data-index="${idx}"] .griot-quiz__feedback`);
|
|
465
|
+
if (feedbackDiv) {
|
|
466
|
+
feedbackDiv.textContent = '— Skipped';
|
|
449
467
|
feedbackDiv.className = 'griot-quiz__feedback griot-quiz__feedback--missing';
|
|
450
|
-
} else if (isCorrect) {
|
|
451
|
-
feedbackDiv.textContent = '✓ Correct!';
|
|
452
|
-
feedbackDiv.className = 'griot-quiz__feedback griot-quiz__feedback--correct';
|
|
453
|
-
} else {
|
|
454
|
-
const correctAnswerText = q.options[q.correctOption];
|
|
455
|
-
feedbackDiv.innerHTML = `✗ Incorrect. Correct answer: ${escapeHtml(correctAnswerText)}. ${escapeHtml(q.explanation || '')}`;
|
|
456
|
-
feedbackDiv.className = 'griot-quiz__feedback griot-quiz__feedback--wrong';
|
|
457
468
|
}
|
|
458
469
|
}
|
|
459
470
|
});
|
|
460
|
-
const totalScore = questions.length;
|
|
461
471
|
|
|
472
|
+
if (answered === 0) {
|
|
473
|
+
alert('Please answer at least one question.');
|
|
474
|
+
return;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
// Lock the form — prevent resubmit
|
|
478
|
+
form.querySelectorAll('input[type="radio"]').forEach(r => r.disabled = true);
|
|
479
|
+
submitBtn.disabled = true;
|
|
480
|
+
submitBtn.textContent = 'Submitted';
|
|
481
|
+
submitBtn.style.opacity = '0.5';
|
|
482
|
+
submitBtn.style.cursor = 'default';
|
|
483
|
+
|
|
484
|
+
// Show score
|
|
462
485
|
const existingScore = container.querySelector('.griot-quiz__score');
|
|
463
486
|
if (existingScore) existingScore.remove();
|
|
464
487
|
const scoreDiv = document.createElement('div');
|
|
465
488
|
scoreDiv.className = 'griot-quiz__score';
|
|
466
|
-
scoreDiv.textContent =
|
|
489
|
+
scoreDiv.textContent = answered < questions.length
|
|
490
|
+
? `You scored ${score} out of ${answered} answered (${questions.length - answered} skipped).`
|
|
491
|
+
: `You scored ${score} out of ${answered}.`;
|
|
467
492
|
container.appendChild(scoreDiv);
|
|
468
493
|
|
|
469
494
|
if (typeof opts.onQuizSubmit === 'function') {
|
|
470
|
-
opts.onQuizSubmit(block.id, score,
|
|
495
|
+
opts.onQuizSubmit(block.id, score, answered, answers);
|
|
471
496
|
}
|
|
472
497
|
});
|
|
473
498
|
|
package/src/viewer/Viewer.js
CHANGED
|
@@ -44,6 +44,10 @@ export class Viewer {
|
|
|
44
44
|
this._render();
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
+
setOnQuizSubmit(fn) {
|
|
48
|
+
this._options.onQuizSubmit = fn ?? null;
|
|
49
|
+
}
|
|
50
|
+
|
|
47
51
|
/** Scroll to block and briefly highlight it */
|
|
48
52
|
setHighlight(blockId, { scroll = true, behavior = 'smooth' } = {}) {
|
|
49
53
|
clearTimeout(this._hlTimer);
|
|
@@ -119,6 +123,7 @@ export class Viewer {
|
|
|
119
123
|
books: this._books,
|
|
120
124
|
onEventClick: this._options.onEventClick,
|
|
121
125
|
onCiteClick: this._options.onCiteClick,
|
|
126
|
+
onQuizSubmit: this._options.onQuizSubmit, // ← add this
|
|
122
127
|
};
|
|
123
128
|
|
|
124
129
|
for (const block of this._doc.blocks) {
|