From 6c0c911dbd640b6c58dc63b7bc1136a00f73b055 Mon Sep 17 00:00:00 2001 From: Daniel Onyejesi Date: Mon, 23 Mar 2026 22:03:54 -0400 Subject: [PATCH] Fix module init: defer all tab scripts until component HTML is loaded All JS modules were running immediately (IIFE/DOMContentLoaded) but tab HTML is lazy-loaded from /components/*.html, causing null errors on every addEventListener call. Each module now listens for tabChanged with its tab name and initializes once after the DOM is ready. Also: quiz question/explanation boxes changed to textarea for multi-line support; quiz display uses sanitizeHtml() so formatted text (bold, lists, etc.) renders correctly. --- public/js/chartReview.js | 5 +++++ public/js/hospitalCourse.js | 5 +++++ public/js/learningHub.js | 14 +++++++++----- public/js/liveEncounter.js | 5 +++++ public/js/milestones.js | 5 +++++ public/js/nextcloud.js | 5 +++++ public/js/shadess.js | 5 ++++- public/js/sickVisit.js | 5 ++++- public/js/soap.js | 5 +++++ public/js/voiceDictation.js | 5 +++++ public/js/wellVisit.js | 5 ++++- 11 files changed, 56 insertions(+), 8 deletions(-) diff --git a/public/js/chartReview.js b/public/js/chartReview.js index bbaab75..e7523a1 100644 --- a/public/js/chartReview.js +++ b/public/js/chartReview.js @@ -1,4 +1,8 @@ (function() { + var _inited = false; + document.addEventListener('tabChanged', function(e) { + if (e.detail.tab !== 'chart' || _inited) return; + _inited = true; var visitsContainer = document.getElementById('cr-visits-container'); var addVisitBtn = document.getElementById('cr-add-visit'); var labsContainer = document.getElementById('cr-labs-container'); @@ -165,4 +169,5 @@ }); console.log('✅ Chart Review module loaded'); + }); })(); diff --git a/public/js/hospitalCourse.js b/public/js/hospitalCourse.js index 5e8bee9..d6e0829 100644 --- a/public/js/hospitalCourse.js +++ b/public/js/hospitalCourse.js @@ -1,4 +1,8 @@ (function() { + var _inited = false; + document.addEventListener('tabChanged', function(e) { + if (e.detail.tab !== 'hospital' || _inited) return; + _inited = true; var notesContainer = document.getElementById('hc-notes-container'); var addNoteBtn = document.getElementById('hc-add-note'); var labsContainer = document.getElementById('hc-labs-container'); @@ -202,4 +206,5 @@ }); console.log('✅ Hospital Course module loaded'); + }); })(); diff --git a/public/js/learningHub.js b/public/js/learningHub.js index 615ac72..69e934e 100644 --- a/public/js/learningHub.js +++ b/public/js/learningHub.js @@ -299,7 +299,7 @@ 'Q' + (idx + 1) + '' + '' + typeLabel + '' + '' + - '

' + esc(q.question_text) + '

' + + '

' + sanitizeHtml(q.question_text) + '

' + '
' + optionsHtml + '
' + ''; }).join(''); @@ -359,11 +359,11 @@ explHtml += '
Correct answer: ' + esc(r.correctOptionText) + '
'; } if (r.generalExplanation) { - explHtml += '
Explanation: ' + esc(r.generalExplanation) + '
'; + explHtml += '
Explanation: ' + sanitizeHtml(r.generalExplanation) + '
'; } return '
' + - '
' + icon + ' Q' + (idx + 1) + ': ' + esc(r.questionText) + '
' + + '
' + icon + ' Q' + (idx + 1) + ': ' + sanitizeHtml(r.questionText) + '
' + explHtml + '
'; }).join(''); @@ -797,7 +797,7 @@ '' + '' + '' + - '' + + '' + '
' + '' + '
' + @@ -805,11 +805,15 @@ '' + '
' + '' + - '' + + '' + '
'; container.appendChild(block); + // Set textarea values after insertion (can't use value="" attr on textarea) + block.querySelector('.lh-q-text').value = existingQ ? existingQ.question_text || '' : ''; + block.querySelector('.lh-q-explanation').value = existingQ ? existingQ.explanation || '' : ''; + var optList = block.querySelector('.lh-options-list'); if (existingQ && existingQ.options && existingQ.options.length > 0) { existingQ.options.forEach(function(opt) { addOptionRow(optList, opt); }); diff --git a/public/js/liveEncounter.js b/public/js/liveEncounter.js index 1d21875..e8c0f7c 100644 --- a/public/js/liveEncounter.js +++ b/public/js/liveEncounter.js @@ -1,4 +1,8 @@ (function() { + var _inited = false; + document.addEventListener('tabChanged', function(e) { + if (e.detail.tab !== 'encounter' || _inited) return; + _inited = true; var recordBtn = document.getElementById('enc-record-btn'); var pauseBtn = document.getElementById('enc-pause-btn'); var indicator = document.getElementById('enc-recording-indicator'); @@ -152,4 +156,5 @@ } console.log('✅ Encounter module loaded'); + }); })(); diff --git a/public/js/milestones.js b/public/js/milestones.js index 274c8ae..2451c60 100644 --- a/public/js/milestones.js +++ b/public/js/milestones.js @@ -1,4 +1,8 @@ (function() { + var _inited = false; + document.addEventListener('tabChanged', function(e) { + if (e.detail.tab !== 'wellvisit' || _inited) return; + _inited = true; var ageSelect = document.getElementById('ms-age-group'); var checklist = document.getElementById('milestone-checklist'); var actionsBar = document.getElementById('milestone-actions'); @@ -181,4 +185,5 @@ }); console.log('✅ Milestones module loaded'); + }); })(); diff --git a/public/js/nextcloud.js b/public/js/nextcloud.js index 6f86be9..0bdd089 100644 --- a/public/js/nextcloud.js +++ b/public/js/nextcloud.js @@ -1,4 +1,8 @@ (function() { + var _inited = false; + document.addEventListener('tabChanged', function(e) { + if (e.detail.tab !== 'settings' || _inited) return; + _inited = true; function loadNextcloudStatus() { fetch('/api/auth/me', { headers: getAuthHeaders() }) .then(function(r) { return r.json(); }) @@ -51,4 +55,5 @@ }); console.log('✅ Nextcloud module loaded'); + }); })(); diff --git a/public/js/shadess.js b/public/js/shadess.js index 0b4a47b..61205c1 100644 --- a/public/js/shadess.js +++ b/public/js/shadess.js @@ -988,7 +988,10 @@ } // ── Init on DOM ready ──────────────────────────────────────────────────── - document.addEventListener('DOMContentLoaded', function() { + var _inited = false; + document.addEventListener('tabChanged', function(e) { + if (e.detail.tab !== 'wellvisit' || _inited) return; + _inited = true; initShadess(); initShadessRecording(); initWvRecording(); diff --git a/public/js/sickVisit.js b/public/js/sickVisit.js index a046f82..6142728 100644 --- a/public/js/sickVisit.js +++ b/public/js/sickVisit.js @@ -411,7 +411,10 @@ } // ── Init ────────────────────────────────────────────────────────────────── - document.addEventListener('DOMContentLoaded', function() { + var _inited = false; + document.addEventListener('tabChanged', function(e) { + if (e.detail.tab !== 'sickvisit' || _inited) return; + _inited = true; initRecording(); populateAddDropdowns(); renderRosPe(); diff --git a/public/js/soap.js b/public/js/soap.js index bdd3b4b..61c6f7a 100644 --- a/public/js/soap.js +++ b/public/js/soap.js @@ -1,4 +1,8 @@ (function() { + var _inited = false; + document.addEventListener('tabChanged', function(e) { + if (e.detail.tab !== 'soap' || _inited) return; + _inited = true; var recordBtn = document.getElementById('soap-record-btn'); var indicator = document.getElementById('soap-recording-indicator'); var timerEl = document.getElementById('soap-timer'); @@ -96,4 +100,5 @@ document.getElementById('soap-shorten-btn').addEventListener('click', function() { shortenDocument('soap-text'); }); console.log('✅ SOAP module loaded'); + }); })(); diff --git a/public/js/voiceDictation.js b/public/js/voiceDictation.js index 124ae05..9c96633 100644 --- a/public/js/voiceDictation.js +++ b/public/js/voiceDictation.js @@ -1,4 +1,8 @@ (function() { + var _inited = false; + document.addEventListener('tabChanged', function(e) { + if (e.detail.tab !== 'dictation' || _inited) return; + _inited = true; var recordBtn = document.getElementById('dict-record-btn'); var pauseBtn = document.getElementById('dict-pause-btn'); var indicator = document.getElementById('dict-recording-indicator'); @@ -162,4 +166,5 @@ } console.log('✅ Dictation module loaded'); + }); })(); diff --git a/public/js/wellVisit.js b/public/js/wellVisit.js index ac76eab..3157321 100644 --- a/public/js/wellVisit.js +++ b/public/js/wellVisit.js @@ -650,7 +650,10 @@ } // ─── Wire up ─────────────────────────────────────────────────────────────── - document.addEventListener('DOMContentLoaded', function () { + var _inited = false; + document.addEventListener('tabChanged', function(e) { + if (e.detail.tab !== 'wellvisit' || _inited) return; + _inited = true; init(); });