From c0cbf1c0bd90234621e7553154cf078d4c15e482 Mon Sep 17 00:00:00 2001 From: DevSoftTech Server Date: Wed, 23 Sep 2026 08:15:09 +0530 Subject: [PATCH] Ensure strict sequential keyboard focus navigation across OPD Consult and IPD Discharge prescription controls --- app/Views/billing/ipd/discharge_create.php | 146 ++++++++++------- app/Views/billing/opd_prescription_basic.php | 160 ++++++++++++------- 2 files changed, 193 insertions(+), 113 deletions(-) diff --git a/app/Views/billing/ipd/discharge_create.php b/app/Views/billing/ipd/discharge_create.php index 4110b15..e5da3cc 100644 --- a/app/Views/billing/ipd/discharge_create.php +++ b/app/Views/billing/ipd/discharge_create.php @@ -6426,16 +6426,18 @@ $historyFields = [ highlightIdx = (highlightIdx - 1 + items.length) % items.length; updateHighlight(items, true); } else if (e.key === 'Enter' || e.key === 'Tab') { + if (e.key === 'Tab' && e.shiftKey) return; + e.preventDefault(); if (isVisible) { - if (e.key === 'Enter') e.preventDefault(); - if (highlightIdx >= 0 && items[highlightIdx]) { - dosageInput.value = items[highlightIdx].getAttribute('data-val'); + var targetIdx = highlightIdx >= 0 ? highlightIdx : 0; + if (items[targetIdx]) { + dosageInput.value = items[targetIdx].getAttribute('data-val') || items[targetIdx].innerText.trim(); } dosageDropdown.style.display = 'none'; highlightIdx = -1; - var freq = document.getElementById('discharge_dosage_freq'); - if (freq) freq.focus(); } + var freq = document.getElementById('discharge_dosage_freq'); + if (freq) freq.focus(); } else if (e.key === 'Escape') { dosageDropdown.style.display = 'none'; highlightIdx = -1; @@ -6521,10 +6523,10 @@ $historyFields = [ var html = ''; items.forEach(function(s, i) { - var bgStyle = (i === highlightIdx) ? 'background:#e2ebff;' : ''; + var bgStyle = (i === highlightIdx) ? 'background:#0d6efd;color:#ffffff;font-weight:600;' : ''; var labelHtml = '' + $('
').text(s.code).html() + ''; if (s.desc) { - labelHtml += ' (' + $('
').text(s.desc).html() + ')'; + labelHtml += ' (' + $('
').text(s.desc).html() + ')'; } html += '
' + labelHtml + '
'; }); @@ -6546,15 +6548,8 @@ $historyFields = [ }); freqInput.addEventListener('keydown', function(e) { + if (e.key === 'Tab' && e.shiftKey) return; var sugs = getSuggestions(freqInput.value); - if (!sugs.length || freqDropdown.style.display === 'none') { - if (e.key === 'Enter') { - e.preventDefault(); - var whenSelect = document.getElementById('discharge_dosage_when'); - if (whenSelect) whenSelect.focus(); - } - return; - } if (e.key === 'ArrowDown') { e.preventDefault(); @@ -6577,20 +6572,29 @@ $historyFields = [ freqInput.value = sugs[highlightIdx].code; } } else if (e.key === 'Enter' || e.key === 'Tab') { + e.preventDefault(); if (freqDropdown.style.display === 'block') { - if (e.key === 'Enter') e.preventDefault(); - if (highlightIdx >= 0 && sugs[highlightIdx]) { - freqInput.value = sugs[highlightIdx].code; + var targetIdx = highlightIdx >= 0 ? highlightIdx : 0; + if (sugs[targetIdx]) { + freqInput.value = sugs[targetIdx].code; } freqDropdown.style.display = 'none'; - var whenSelect = document.getElementById('discharge_dosage_when'); - if (whenSelect) whenSelect.focus(); + highlightIdx = -1; } + var whenSelect = document.getElementById('discharge_dosage_when'); + if (whenSelect) whenSelect.focus(); } else if (e.key === 'Escape') { freqDropdown.style.display = 'none'; } }); + $(document).on('click', '.discharge-freq-opt', function() { + freqInput.value = $(this).data('code'); + freqDropdown.style.display = 'none'; + var whenSelect = document.getElementById('discharge_dosage_when'); + if (whenSelect) whenSelect.focus(); + }); + document.addEventListener('click', function(e) { if (!freqInput.contains(e.target) && !freqDropdown.contains(e.target)) { freqDropdown.style.display = 'none'; @@ -6598,6 +6602,28 @@ $historyFields = [ }); })(); + // ─── Sequential Enter-key Navigation between Formulation, Timing & Route ─── + $('#discharge_med_type').on('keydown', function(e) { + if (e.key === 'Enter') { + e.preventDefault(); + $('#discharge_dosage').focus(); + } + }); + + $('#discharge_dosage_when').on('keydown', function(e) { + if (e.key === 'Enter') { + e.preventDefault(); + $('#discharge_dose_where').focus(); + } + }); + + $('#discharge_dose_where').on('keydown', function(e) { + if (e.key === 'Enter') { + e.preventDefault(); + $('#discharge_no_of_days').focus(); + } + }); + // ── Smart Duration Autotext for #discharge_no_of_days ───────────────────────── (function() { var daysInput = document.getElementById('discharge_no_of_days'); @@ -6739,21 +6765,18 @@ $historyFields = [ } updateHighlight(items, true); } else if (e.key === 'Enter' || e.key === 'Tab') { + if (e.key === 'Tab' && e.shiftKey) return; + e.preventDefault(); if (isVisible) { - if (e.key === 'Enter') e.preventDefault(); var targetIdx = selectedIdx >= 0 ? selectedIdx : 0; if (items[targetIdx]) { daysInput.value = items[targetIdx].getAttribute('data-val') || items[targetIdx].innerText.trim(); } daysDropdown.style.display = 'none'; selectedIdx = -1; - var remark = document.getElementById('discharge_remark'); - if (remark) remark.focus(); - } else if (e.key === 'Enter') { - e.preventDefault(); - var remark = document.getElementById('discharge_remark'); - if (remark) remark.focus(); } + var remark = document.getElementById('discharge_remark'); + if (remark) remark.focus(); } else if (e.key === 'Escape') { daysDropdown.style.display = 'none'; selectedIdx = -1; @@ -6786,16 +6809,23 @@ $historyFields = [ var medRemarkHighlightIdx = -1; - function highlightMedRemarkItem(idx) { + function highlightMedRemarkItem(idx, updateInput) { var $items = $('#discharge_remark_dd .discharge-remark-dd-item'); if (!$items.length) return; if (idx < 0) idx = 0; if (idx >= $items.length) idx = $items.length - 1; medRemarkHighlightIdx = idx; - $items.css('background', '').removeClass('active-dd-item'); + $items.css({ 'background': '', 'color': '', 'font-weight': '' }).removeClass('active-dd-item'); var $target = $items.eq(medRemarkHighlightIdx); - $target.css('background', '#e2ebff').addClass('active-dd-item'); + $target.css({ 'background': '#0d6efd', 'color': '#ffffff', 'font-weight': '600' }).addClass('active-dd-item'); + + if (updateInput) { + var val = $target.text().trim(); + if (val) { + $('#discharge_remark').val(val); + } + } var container = document.getElementById('discharge_remark_dd'); var elem = $target[0]; @@ -6832,8 +6862,8 @@ $historyFields = [ var $row = $('
') .text(s); - $row.on('mouseenter', function() { highlightMedRemarkItem(idx); }) - .on('mouseleave', function() { $(this).css('background',''); }) + $row.on('mouseenter', function() { highlightMedRemarkItem(idx, false); }) + .on('mouseleave', function() { $(this).css({ 'background': '', 'color': '', 'font-weight': '' }); }) .on('mousedown', function(e) { e.preventDefault(); }) .on('click', function() { $('#discharge_remark').val(s); @@ -6864,31 +6894,31 @@ $historyFields = [ if (!isVisible) { var sugs = getMedRemarkSuggestions(($(this).val() || '').trim()); renderMedRemarkDropdown(sugs); - highlightMedRemarkItem(0); + highlightMedRemarkItem(0, true); return; } e.preventDefault(); - var nextIdx = medRemarkHighlightIdx + 1; - if (nextIdx >= $items.length) nextIdx = 0; - highlightMedRemarkItem(nextIdx); + var nextIdx = medRemarkHighlightIdx < 0 ? 0 : (medRemarkHighlightIdx + 1) % $items.length; + highlightMedRemarkItem(nextIdx, true); } else if (e.key === 'ArrowUp') { if (!isVisible) return; e.preventDefault(); - var prevIdx = medRemarkHighlightIdx - 1; - if (prevIdx < 0) prevIdx = $items.length - 1; - highlightMedRemarkItem(prevIdx); - } else if (e.key === 'Enter') { - if (isVisible && medRemarkHighlightIdx >= 0) { - e.preventDefault(); - var $target = $items.eq(medRemarkHighlightIdx); + var prevIdx = medRemarkHighlightIdx < 0 ? ($items.length - 1) : (medRemarkHighlightIdx - 1 + $items.length) % $items.length; + highlightMedRemarkItem(prevIdx, true); + } else if (e.key === 'Enter' || e.key === 'Tab') { + if (e.key === 'Tab' && e.shiftKey) return; + e.preventDefault(); + if (isVisible) { + var targetIdx = medRemarkHighlightIdx >= 0 ? medRemarkHighlightIdx : 0; + var $target = $items.eq(targetIdx); if ($target.length) { - $target.trigger('click'); + $('#discharge_remark').val($target.text().trim()); } - } else if (!isVisible && e.key === 'Enter') { - e.preventDefault(); - var btnAdd = document.getElementById('btn_discharge_med_add'); - if (btnAdd) btnAdd.focus(); + $dd.hide().empty(); + medRemarkHighlightIdx = -1; } + var btnAdd = document.getElementById('btn_discharge_med_add'); + if (btnAdd) btnAdd.focus(); } else if (e.key === 'Escape') { $dd.hide().empty(); medRemarkHighlightIdx = -1; @@ -7119,6 +7149,7 @@ $historyFields = [ applyDischargeMedicineMatch(row); $dd.hide().empty(); dischargeMedHighlightIdx = -1; + setTimeout(function() { $('#discharge_med_type').focus(); }, 30); }); $dd.append($item); @@ -7185,17 +7216,24 @@ $historyFields = [ var prevIdx = dischargeMedHighlightIdx - 1; if (prevIdx < 0) prevIdx = $items.length - 1; highlightDischargeMedNameItem(prevIdx); - } else if (e.key === 'Enter') { - if (isVisible && dischargeMedHighlightIdx >= 0 && dischargeMedSuggestRows[dischargeMedHighlightIdx]) { + } else if (e.key === 'Enter' || e.key === 'Tab') { + if (e.key === 'Tab' && e.shiftKey) return; + if (isVisible) { e.preventDefault(); - applyDischargeMedicineMatch(dischargeMedSuggestRows[dischargeMedHighlightIdx]); + var targetIdx = dischargeMedHighlightIdx >= 0 ? dischargeMedHighlightIdx : 0; + if (dischargeMedSuggestRows[targetIdx]) { + applyDischargeMedicineMatch(dischargeMedSuggestRows[targetIdx]); + } $dd.hide().empty(); dischargeMedHighlightIdx = -1; - var nextTarget = section.querySelector('#discharge_med_type') || section.querySelector('#discharge_dosage'); - if (nextTarget) nextTarget.focus(); + setTimeout(function() { $('#discharge_med_type').focus(); }, 30); + } else if (e.key === 'Enter') { + e.preventDefault(); + setTimeout(function() { $('#discharge_med_type').focus(); }, 30); } } else if (e.key === 'Escape') { - $dd.hide(); + $dd.hide().empty(); + dischargeMedHighlightIdx = -1; } }); } diff --git a/app/Views/billing/opd_prescription_basic.php b/app/Views/billing/opd_prescription_basic.php index 7634cab..7324f32 100644 --- a/app/Views/billing/opd_prescription_basic.php +++ b/app/Views/billing/opd_prescription_basic.php @@ -6840,20 +6840,18 @@ if (prevIdx < 0) prevIdx = $items.length - 1; highlightMedDosageItem(prevIdx, true); } else if (e.key === 'Enter' || e.key === 'Tab') { + if (e.key === 'Tab' && e.shiftKey) return; + e.preventDefault(); if (isVisible) { var targetIdx = medDosageHighlightIdx >= 0 ? medDosageHighlightIdx : 0; var $target = $items.eq(targetIdx); if ($target.length) { - if (e.key === 'Enter') e.preventDefault(); $('#med_dosage').val($target.text().trim()).trigger('change'); - $dd.hide().empty(); - medDosageHighlightIdx = -1; - setTimeout(function() { $('#med_freq').focus(); }, 30); } - } else if (e.key === 'Enter') { - e.preventDefault(); - setTimeout(function() { $('#med_freq').focus(); }, 30); + $dd.hide().empty(); + medDosageHighlightIdx = -1; } + setTimeout(function() { $('#med_freq').focus(); }, 30); } else if (e.key === 'Escape') { $dd.hide().empty(); medDosageHighlightIdx = -1; @@ -6866,30 +6864,36 @@ { code: 'BD', desc: 'Twice Daily (2 doses/day)' }, { code: 'TDS', desc: 'Thrice Daily (3 doses/day)' }, { code: 'QID', desc: 'Four Times Daily (4 doses/day)' }, - { code: 'HS', desc: 'At Bedtime (Once at night)' }, - { code: 'SOS', desc: 'As Needed (Only when required)' }, + { code: 'HS', desc: 'At Bedtime / Night' }, + { code: 'SOS', desc: 'As Needed (If Required)' }, + { code: 'STAT', desc: 'Immediately (Single Dose)' }, { code: 'Q4H', desc: 'Every 4 Hours' }, { code: 'Q6H', desc: 'Every 6 Hours' }, { code: 'Q8H', desc: 'Every 8 Hours' }, - { code: 'Alternate Day', desc: 'Once every 2 days' }, - { code: 'Weekly', desc: 'Long-interval (Once a week)' }, - { code: 'Monthly', desc: 'Long-interval (Once a month)' }, - { code: 'Continuous Infusion', desc: 'IV drip maintained continuously' }, - { code: 'Stat', desc: 'Immediate single dose' } + { code: 'Q12H', desc: 'Every 12 Hours' }, + { code: 'Weekly', desc: 'Once a Week' }, + { code: 'Alt Day', desc: 'Alternate Days (Every 48 Hours)' } ]; var medFreqHighlightIdx = -1; - function highlightMedFreqItem(idx) { + function highlightMedFreqItem(idx, updateInput) { var $items = $('#med_freq_dd .med-freq-dd-item'); if (!$items.length) return; if (idx < 0) idx = 0; if (idx >= $items.length) idx = $items.length - 1; medFreqHighlightIdx = idx; - $items.css('background', '').removeClass('active-dd-item'); + $items.css({ 'background': '', 'color': '', 'font-weight': '' }).removeClass('active-dd-item'); var $target = $items.eq(medFreqHighlightIdx); - $target.css('background', '#e2ebff').addClass('active-dd-item'); + $target.css({ 'background': '#0d6efd', 'color': '#ffffff', 'font-weight': '600' }).addClass('active-dd-item'); + + if (updateInput) { + var val = $target.find('strong').text().trim() || $target.text().trim(); + if (val) { + $('#med_freq').val(val).trigger('change'); + } + } var container = document.getElementById('med_freq_dd'); var elem = $target[0]; @@ -6960,13 +6964,14 @@ } $row.html(labelHtml); - $row.on('mouseenter', function() { highlightMedFreqItem(idx); }) - .on('mouseleave', function() { $(this).css('background',''); }) + $row.on('mouseenter', function() { highlightMedFreqItem(idx, false); }) + .on('mouseleave', function() { $(this).css({ 'background': '', 'color': '', 'font-weight': '' }); }) .on('mousedown', function(e) { e.preventDefault(); }) .on('click', function() { $('#med_freq').val(code).trigger('change'); $dd.hide().empty(); medFreqHighlightIdx = -1; + setTimeout(function() { $('#med_when').focus(); }, 30); }); $dd.append($row); @@ -6990,35 +6995,59 @@ if (!isVisible) { var sugs = getMedFreqSuggestions(($(this).val() || '').trim()); renderMedFreqDropdown(sugs); - highlightMedFreqItem(0); + highlightMedFreqItem(0, true); return; } e.preventDefault(); - var nextIdx = medFreqHighlightIdx + 1; - if (nextIdx >= $items.length) nextIdx = 0; - highlightMedFreqItem(nextIdx); + var nextIdx = medFreqHighlightIdx < 0 ? 0 : (medFreqHighlightIdx + 1) % $items.length; + highlightMedFreqItem(nextIdx, true); } else if (e.key === 'ArrowUp') { if (!isVisible) return; e.preventDefault(); - var prevIdx = medFreqHighlightIdx - 1; - if (prevIdx < 0) prevIdx = $items.length - 1; - highlightMedFreqItem(prevIdx); - } else if (e.key === 'Enter') { + var prevIdx = medFreqHighlightIdx < 0 ? ($items.length - 1) : (medFreqHighlightIdx - 1 + $items.length) % $items.length; + highlightMedFreqItem(prevIdx, true); + } else if (e.key === 'Enter' || e.key === 'Tab') { + if (e.key === 'Tab' && e.shiftKey) return; + e.preventDefault(); if (isVisible) { - e.preventDefault(); var targetIdx = medFreqHighlightIdx >= 0 ? medFreqHighlightIdx : 0; var $target = $items.eq(targetIdx); if ($target.length) { - $target.trigger('click'); - setTimeout(function() { $('#med_when').focus(); }, 30); + var code = $target.find('strong').text().trim() || $target.text().trim(); + $('#med_freq').val(code).trigger('change'); } + $dd.hide().empty(); + medFreqHighlightIdx = -1; } + setTimeout(function() { $('#med_when').focus(); }, 30); } else if (e.key === 'Escape') { $dd.hide().empty(); medFreqHighlightIdx = -1; } }); + // ─── Sequential Enter-key Navigation between Formulation, Timing & Route ─── + $('#med_type').on('keydown', function(e) { + if (e.key === 'Enter') { + e.preventDefault(); + $('#med_dosage').focus(); + } + }); + + $('#med_when').on('keydown', function(e) { + if (e.key === 'Enter') { + e.preventDefault(); + $('#med_where').focus(); + } + }); + + $('#med_where').on('keydown', function(e) { + if (e.key === 'Enter') { + e.preventDefault(); + $('#med_days').focus(); + } + }); + // ─── Duration Smart Autocomplete ────────────────────────────── var _DURATION_PRESETS = [ '1 Day', '2 Days', '3 Days', '4 Days', '5 Days', '6 Days', '7 Days', @@ -7137,20 +7166,18 @@ if (prevIdx < 0) prevIdx = $items.length - 1; highlightMedDaysItem(prevIdx, true); } else if (e.key === 'Enter' || e.key === 'Tab') { + if (e.key === 'Tab' && e.shiftKey) return; + e.preventDefault(); if (isVisible) { var targetIdx = medDaysHighlightIdx >= 0 ? medDaysHighlightIdx : 0; var $target = $items.eq(targetIdx); if ($target.length) { - if (e.key === 'Enter') e.preventDefault(); $('#med_days').val($target.text().trim()).trigger('change'); - $dd.hide().empty(); - medDaysHighlightIdx = -1; - setTimeout(function() { $('#med_remark').focus(); }, 30); } - } else if (e.key === 'Enter') { - e.preventDefault(); - setTimeout(function() { $('#med_remark').focus(); }, 30); + $dd.hide().empty(); + medDaysHighlightIdx = -1; } + setTimeout(function() { $('#med_remark').focus(); }, 30); } else if (e.key === 'Escape') { $dd.hide().empty(); medDaysHighlightIdx = -1; @@ -7180,16 +7207,23 @@ ]; var medRemarkHighlightIdx = -1; - function highlightMedRemarkItem(idx) { + function highlightMedRemarkItem(idx, updateInput) { var $items = $('#med_remark_dd .med-remark-dd-item'); if (!$items.length) return; if (idx < 0) idx = 0; if (idx >= $items.length) idx = $items.length - 1; medRemarkHighlightIdx = idx; - $items.css('background', '').removeClass('active-dd-item'); + $items.css({ 'background': '', 'color': '', 'font-weight': '' }).removeClass('active-dd-item'); var $target = $items.eq(medRemarkHighlightIdx); - $target.css('background', '#e2ebff').addClass('active-dd-item'); + $target.css({ 'background': '#0d6efd', 'color': '#ffffff', 'font-weight': '600' }).addClass('active-dd-item'); + + if (updateInput) { + var val = $target.text().trim(); + if (val) { + $('#med_remark').val(val); + } + } var container = document.getElementById('med_remark_dd'); var elem = $target[0]; @@ -7228,13 +7262,14 @@ var $row = $('
') .text(s); - $row.on('mouseenter', function() { highlightMedRemarkItem(idx); }) - .on('mouseleave', function() { $(this).css('background',''); }) + $row.on('mouseenter', function() { highlightMedRemarkItem(idx, false); }) + .on('mouseleave', function() { $(this).css({ 'background': '', 'color': '', 'font-weight': '' }); }) .on('mousedown', function(e) { e.preventDefault(); }) .on('click', function() { $('#med_remark').val(s).trigger('change'); $dd.hide().empty(); medRemarkHighlightIdx = -1; + setTimeout(function() { $('#btn_add_medicine').focus(); }, 30); }); $dd.append($row); @@ -7258,28 +7293,30 @@ if (!isVisible) { var sugs = getMedRemarkSuggestions(($(this).val() || '').trim()); renderMedRemarkDropdown(sugs); - highlightMedRemarkItem(0); + highlightMedRemarkItem(0, true); return; } e.preventDefault(); - var nextIdx = medRemarkHighlightIdx + 1; - if (nextIdx >= $items.length) nextIdx = 0; - highlightMedRemarkItem(nextIdx); + var nextIdx = medRemarkHighlightIdx < 0 ? 0 : (medRemarkHighlightIdx + 1) % $items.length; + highlightMedRemarkItem(nextIdx, true); } else if (e.key === 'ArrowUp') { if (!isVisible) return; e.preventDefault(); - var prevIdx = medRemarkHighlightIdx - 1; - if (prevIdx < 0) prevIdx = $items.length - 1; - highlightMedRemarkItem(prevIdx); - } else if (e.key === 'Enter') { - if (isVisible && medRemarkHighlightIdx >= 0) { - e.preventDefault(); - var $target = $items.eq(medRemarkHighlightIdx); + var prevIdx = medRemarkHighlightIdx < 0 ? ($items.length - 1) : (medRemarkHighlightIdx - 1 + $items.length) % $items.length; + highlightMedRemarkItem(prevIdx, true); + } else if (e.key === 'Enter' || e.key === 'Tab') { + if (e.key === 'Tab' && e.shiftKey) return; + e.preventDefault(); + if (isVisible) { + var targetIdx = medRemarkHighlightIdx >= 0 ? medRemarkHighlightIdx : 0; + var $target = $items.eq(targetIdx); if ($target.length) { - $target.trigger('click'); - setTimeout(function() { $('#btn_add_medicine').focus(); }, 30); + $('#med_remark').val($target.text().trim()).trigger('change'); } + $dd.hide().empty(); + medRemarkHighlightIdx = -1; } + setTimeout(function() { $('#btn_add_medicine').focus(); }, 30); } else if (e.key === 'Escape') { $dd.hide().empty(); medRemarkHighlightIdx = -1; @@ -9799,6 +9836,7 @@ applyMedicineSelection(row); $dd.hide().empty(); medNameHighlightIdx = -1; + setTimeout(function() { $('#med_type').focus(); }, 30); }); $dd.append($item); @@ -9851,16 +9889,20 @@ var prevIdx = medNameHighlightIdx - 1; if (prevIdx < 0) prevIdx = medicineSuggestRows.length - 1; highlightMedNameItem(prevIdx); - } else if (e.key === 'Enter') { + } else if (e.key === 'Enter' || e.key === 'Tab') { + if (e.key === 'Tab' && e.shiftKey) return; if (isVisible) { e.preventDefault(); var targetIdx = medNameHighlightIdx >= 0 ? medNameHighlightIdx : 0; if (medicineSuggestRows[targetIdx]) { applyMedicineSelection(medicineSuggestRows[targetIdx]); - $dd.hide().empty(); - medNameHighlightIdx = -1; - setTimeout(function() { $('#med_freq').focus(); }, 30); } + $dd.hide().empty(); + medNameHighlightIdx = -1; + setTimeout(function() { $('#med_type').focus(); }, 30); + } else if (e.key === 'Enter') { + e.preventDefault(); + setTimeout(function() { $('#med_type').focus(); }, 30); } } else if (e.key === 'Escape') { $dd.hide().empty();