extract calculator shared modules
This commit is contained in:
parent
4a14a71151
commit
e4ea553bee
4 changed files with 77 additions and 84 deletions
|
|
@ -508,7 +508,7 @@
|
|||
<script defer src="/js/documents.js"></script>
|
||||
<script defer src="/js/calc-math.js"></script>
|
||||
<script defer src="/js/drugs-loader.js"></script>
|
||||
<script defer src="/js/calculators.js"></script>
|
||||
<script type="module" src="/js/calculators.js"></script>
|
||||
<script type="module" src="/js/bedside/index.js"></script>
|
||||
<script defer src="/js/learningHub.js"></script>
|
||||
<script defer src="/js/admin.js?v=7.1.3"></script>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,12 @@
|
|||
import { parseAgeMonths, formatParsedAge } from './calculators/age.js';
|
||||
import { initImageLightbox } from './calculators/lightbox.js';
|
||||
|
||||
// ============================================================
|
||||
// CALCULATORS.JS — Pediatric clinical calculators
|
||||
// ============================================================
|
||||
|
||||
initImageLightbox();
|
||||
|
||||
(function() {
|
||||
var _inited = false;
|
||||
document.addEventListener('tabChanged', function(e) {
|
||||
|
|
@ -10,49 +15,6 @@
|
|||
initCalculators();
|
||||
});
|
||||
|
||||
// ── Flexible age parser ─────────────────────────────────────────────
|
||||
// Accepts: "3y", "3 years", "29m", "29 months", "2y5m", "2 years 5 months",
|
||||
// "15d", "15 days", "3y 2m 10d", "36" (months), "3.5 years", etc.
|
||||
// Returns age in months (may be fractional), or null if unparseable.
|
||||
function parseAgeMonths(input) {
|
||||
if (input == null) return null;
|
||||
var s = String(input).toLowerCase().trim();
|
||||
if (!s) return null;
|
||||
// Plain number with no unit: if >= 24 assume years, else months. Matches
|
||||
// common shorthand ("36" for 3y, "6" for 6 months).
|
||||
if (/^[\d.]+$/.test(s)) {
|
||||
var n = parseFloat(s);
|
||||
if (isNaN(n)) return null;
|
||||
return n >= 24 ? n : n; // keep as months; user can add unit if they meant years
|
||||
}
|
||||
var total = 0;
|
||||
var matched = false;
|
||||
// Use (?![a-z]) instead of \b so "2y5m" terminates "y" correctly.
|
||||
// Order matters: longest-first alternations (years before yrs before y, etc.).
|
||||
var my = s.match(/([\d.]+)\s*(?:years|year|yrs|yr|y)(?![a-z])/);
|
||||
if (my) { total += parseFloat(my[1]) * 12; matched = true; }
|
||||
var mm = s.match(/([\d.]+)\s*(?:months|month|mos|mo|m)(?![a-z])/);
|
||||
if (mm) { total += parseFloat(mm[1]); matched = true; }
|
||||
var mw = s.match(/([\d.]+)\s*(?:weeks|week|wks|wk|w)(?![a-z])/);
|
||||
if (mw) { total += parseFloat(mw[1]) * 7 / 30.4375; matched = true; }
|
||||
var md = s.match(/([\d.]+)\s*(?:days|day|d)(?![a-z])/);
|
||||
if (md) { total += parseFloat(md[1]) / 30.4375; matched = true; }
|
||||
return matched ? total : null;
|
||||
}
|
||||
|
||||
function formatParsedAge(months) {
|
||||
if (months < 1) {
|
||||
var d = Math.round(months * 30.4375);
|
||||
return '= ' + d + ' day' + (d === 1 ? '' : 's') + ' (' + months.toFixed(2) + ' mo)';
|
||||
}
|
||||
if (months < 24) {
|
||||
return '= ' + (Math.round(months * 10) / 10) + ' months';
|
||||
}
|
||||
var yr = Math.floor(months / 12);
|
||||
var mo = Math.round(months - yr * 12);
|
||||
if (mo === 12) { yr += 1; mo = 0; }
|
||||
return '= ' + yr + ' yr' + (mo ? ' ' + mo + ' mo' : '') + ' (' + Math.round(months) + ' mo total)';
|
||||
}
|
||||
// Expose for debugging / other modules
|
||||
window._parseAgeMonths = parseAgeMonths;
|
||||
|
||||
|
|
@ -2899,43 +2861,3 @@
|
|||
resultDiv.innerHTML = html;
|
||||
}
|
||||
})();
|
||||
|
||||
// ============================================================
|
||||
// IMAGE LIGHTBOX — any element with data-img-src opens fullscreen
|
||||
// ============================================================
|
||||
(function() {
|
||||
document.addEventListener('click', function(e) {
|
||||
var opener = e.target.closest && e.target.closest('[data-img-src]');
|
||||
if (opener) {
|
||||
e.preventDefault();
|
||||
var lb = document.getElementById('img-lightbox');
|
||||
if (!lb) return;
|
||||
var src = opener.dataset.imgSrc;
|
||||
var title = opener.dataset.imgTitle || '';
|
||||
document.getElementById('img-lightbox-img').src = src;
|
||||
document.getElementById('img-lightbox-img').alt = title;
|
||||
document.getElementById('img-lightbox-title').textContent = title;
|
||||
document.getElementById('img-lightbox-open').href = src;
|
||||
lb.style.display = 'flex';
|
||||
return;
|
||||
}
|
||||
// Close on close button, on backdrop click (not on image), and on Escape (below)
|
||||
var closeBtn = e.target.closest && e.target.closest('#img-lightbox-close');
|
||||
var lb2 = document.getElementById('img-lightbox');
|
||||
if (!lb2 || lb2.style.display !== 'flex') return;
|
||||
if (closeBtn || e.target === lb2) {
|
||||
lb2.style.display = 'none';
|
||||
document.getElementById('img-lightbox-img').src = '';
|
||||
}
|
||||
});
|
||||
document.addEventListener('keydown', function(e) {
|
||||
if (e.key === 'Escape') {
|
||||
var lb = document.getElementById('img-lightbox');
|
||||
if (lb && lb.style.display === 'flex') {
|
||||
lb.style.display = 'none';
|
||||
document.getElementById('img-lightbox-img').src = '';
|
||||
}
|
||||
}
|
||||
});
|
||||
})();
|
||||
|
||||
|
|
|
|||
36
public/js/calculators/age.js
Normal file
36
public/js/calculators/age.js
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
export function parseAgeMonths(input) {
|
||||
if (input == null) return null;
|
||||
var s = String(input).toLowerCase().trim();
|
||||
if (!s) return null;
|
||||
// Plain number with no unit: keep as months; user can add a unit if they meant years.
|
||||
if (/^[\d.]+$/.test(s)) {
|
||||
var n = parseFloat(s);
|
||||
if (isNaN(n)) return null;
|
||||
return n;
|
||||
}
|
||||
var total = 0;
|
||||
var matched = false;
|
||||
var my = s.match(/([\d.]+)\s*(?:years|year|yrs|yr|y)(?![a-z])/);
|
||||
if (my) { total += parseFloat(my[1]) * 12; matched = true; }
|
||||
var mm = s.match(/([\d.]+)\s*(?:months|month|mos|mo|m)(?![a-z])/);
|
||||
if (mm) { total += parseFloat(mm[1]); matched = true; }
|
||||
var mw = s.match(/([\d.]+)\s*(?:weeks|week|wks|wk|w)(?![a-z])/);
|
||||
if (mw) { total += parseFloat(mw[1]) * 7 / 30.4375; matched = true; }
|
||||
var md = s.match(/([\d.]+)\s*(?:days|day|d)(?![a-z])/);
|
||||
if (md) { total += parseFloat(md[1]) / 30.4375; matched = true; }
|
||||
return matched ? total : null;
|
||||
}
|
||||
|
||||
export function formatParsedAge(months) {
|
||||
if (months < 1) {
|
||||
var d = Math.round(months * 30.4375);
|
||||
return '= ' + d + ' day' + (d === 1 ? '' : 's') + ' (' + months.toFixed(2) + ' mo)';
|
||||
}
|
||||
if (months < 24) {
|
||||
return '= ' + (Math.round(months * 10) / 10) + ' months';
|
||||
}
|
||||
var yr = Math.floor(months / 12);
|
||||
var mo = Math.round(months - yr * 12);
|
||||
if (mo === 12) { yr += 1; mo = 0; }
|
||||
return '= ' + yr + ' yr' + (mo ? ' ' + mo + ' mo' : '') + ' (' + Math.round(months) + ' mo total)';
|
||||
}
|
||||
35
public/js/calculators/lightbox.js
Normal file
35
public/js/calculators/lightbox.js
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
export function initImageLightbox() {
|
||||
document.addEventListener('click', function(e) {
|
||||
var opener = e.target.closest && e.target.closest('[data-img-src]');
|
||||
if (opener) {
|
||||
e.preventDefault();
|
||||
var lb = document.getElementById('img-lightbox');
|
||||
if (!lb) return;
|
||||
var src = opener.dataset.imgSrc;
|
||||
var title = opener.dataset.imgTitle || '';
|
||||
document.getElementById('img-lightbox-img').src = src;
|
||||
document.getElementById('img-lightbox-img').alt = title;
|
||||
document.getElementById('img-lightbox-title').textContent = title;
|
||||
document.getElementById('img-lightbox-open').href = src;
|
||||
lb.style.display = 'flex';
|
||||
return;
|
||||
}
|
||||
var closeBtn = e.target.closest && e.target.closest('#img-lightbox-close');
|
||||
var lb2 = document.getElementById('img-lightbox');
|
||||
if (!lb2 || lb2.style.display !== 'flex') return;
|
||||
if (closeBtn || e.target === lb2) {
|
||||
lb2.style.display = 'none';
|
||||
document.getElementById('img-lightbox-img').src = '';
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener('keydown', function(e) {
|
||||
if (e.key === 'Escape') {
|
||||
var lb = document.getElementById('img-lightbox');
|
||||
if (lb && lb.style.display === 'flex') {
|
||||
lb.style.display = 'none';
|
||||
document.getElementById('img-lightbox-img').src = '';
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
Loading…
Reference in a new issue