{"id":513,"date":"2025-09-09T16:25:32","date_gmt":"2025-09-09T16:25:32","guid":{"rendered":"https:\/\/tomchan.hk\/?page_id=513"},"modified":"2025-09-09T16:48:10","modified_gmt":"2025-09-09T16:48:10","slug":"gir-calculator","status":"publish","type":"page","link":"https:\/\/tomchan.hk\/?page_id=513","title":{"rendered":"GIR calculator"},"content":{"rendered":"\n<div id=\"gir-tfi-app\" style=\"max-width:980px;margin:1.5rem auto;font-family:system-ui,Segoe UI,Roboto,Helvetica,Arial,sans-serif;\">\n  <style>\n#gir-tfi-app .row {\n  display: grid;\n  grid-template-columns: 1.1fr .9fr .9fr .9fr .9fr .9fr 56px;\n  gap: .5rem;\n  align-items: end;\n\n  \/* --- new border styles --- *\/\n  border: 1px solid #d1d5db;\n  border-radius: 12px;\n  padding: .75rem;\n  background: #fff;\n}\n#gir-tfi-app #addRow,\n#gir-tfi-app #resetAll {\n  color: #000 !important;\n}\n    #gir-tfi-app .card{background:#fff;border:1px solid #e5e7eb;border-radius:14px;box-shadow:0 2px 8px rgba(0,0,0,.04)}\n    #gir-tfi-app .row{display:grid;grid-template-columns:1.1fr .9fr .9fr .9fr .9fr .9fr 56px;gap:.5rem;align-items:end}\n    #gir-tfi-app label{font-size:.8rem;color:#374151;margin-bottom:.25rem;display:block}\n    #gir-tfi-app input, #gir-tfi-app select{width:100%;padding:.6rem .7rem;border:1px solid #d1d5db;border-radius:10px;font-size:.95rem}\n    #gir-tfi-app .btn{display:inline-flex;align-items:center;gap:.5rem;border:1px solid #d1d5db;border-radius:12px;padding:.55rem .8rem;background:#fff;cursor:pointer}\n    #gir-tfi-app .btn.primary{background:#111827;color:#fff;border-color:#111827}\n    #gir-tfi-app .btn.danger{color:#b91c1c;border-color:#fecaca;background:#fff5f5}\n    #gir-tfi-app .stack{display:flex;gap:.75rem;flex-wrap:wrap}\n    #gir-tfi-app .muted{color:#6b7280;font-size:.9rem}\n    #gir-tfi-app .out{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:1rem}\n    #gir-tfi-app .kpi{padding:1rem;border:1px dashed #d1d5db;border-radius:12px;background:#fafafa}\n    #gir-tfi-app .kpi h3{margin:.2rem 0 .4rem 0;font-size:1.05rem}\n    #gir-tfi-app .kpi .val{font-size:1.4rem;font-weight:700}\n    @media (max-width:980px){#gir-tfi-app .row{grid-template-columns:1fr 1fr}}\n\n    \/* --- remove number input spinners --- *\/\n    #gir-tfi-app input[type=number]::-webkit-inner-spin-button, \n    #gir-tfi-app input[type=number]::-webkit-outer-spin-button {\n      -webkit-appearance: none;\n      margin: 0;\n    }\n    #gir-tfi-app input[type=number] {\n      -moz-appearance: textfield;\n    }\n  <\/style>\n  <div class=\"card\" style=\"padding:1rem 1rem 0\">\n    <div class=\"stack\" style=\"justify-content:space-between;align-items:center;margin:.25rem 0 1rem\">\n      <div>\n        <h2 style=\"margin:.2rem 0\">GIR, TFI &#038; Calories Calculator (IVF + Milk)<\/h2>\n      <\/div>\n      <div class=\"stack\">\n      <h4 style=\"margin:.2rem 0\">Weight (kg)<\/h4>\n        <input id=\"wt\" type=\"number\" min=\"0\" step=\"0.001\" placeholder=\"e.g. 2.8\" style=\"max-width:120px\">\n      <\/div>\n    <\/div>\n\n    <div id=\"rows\" class=\"stack\" style=\"flex-direction:column;gap:.9rem;margin-bottom:1rem\"><\/div>\n\n    <div class=\"stack\" style=\"justify-content:space-between;padding:0 0 1rem 0\">\n      <button id=\"addRow\" class=\"btn\">\u2795 Add row<\/button>\n      <button id=\"resetAll\" class=\"btn\">\u21ba Reset<\/button>\n    <\/div>\n  <\/div>\n\n  <div class=\"card\" style=\"padding:1rem;margin-top:1rem\">\n    <div class=\"out\">\n      <div class=\"kpi\">\n        <h3>TFI<\/h3>\n        <div class=\"val\"><span id=\"totMlKgDay\">\u2014<\/span><\/div>\n        <div class=\"muted\"><span id=\"totMlDay\">0<\/span> mL\/day<\/div>\n      <\/div>\n      <div class=\"kpi\">\n        <h3>GIR<\/h3>\n        <div class=\"val\"><span id=\"girOverall\">\u2014<\/span><\/div>\n        <div class=\"muted\">mg\/kg\/min<\/div>\n      <\/div>\n      <div class=\"kpi\">\n        <h3>Calories<\/h3>\n        <div class=\"val\"><span id=\"kcalKgDay\">\u2014<\/span><\/div>\n        <div class=\"muted\"><span id=\"kcalDay\">0<\/span> kcal\/day<\/div>\n      <\/div>\n    <\/div>\n  <\/div>\n\n  <details style=\"max-width:980px;margin:1rem auto\">\n    <summary class=\"muted\">Notes &#038; formulas<\/summary>\n    <div class=\"muted\" style=\"line-height:1.45;margin-top:.6rem\">\n      <ul>\n        <li><b>Default sugar (editable):<\/b> D10 = 10 g\/100 mL, D12.5 = 12.5 g\/100 mL, D20 = 20 g\/100 mL, Term\/\u201cnormal\u201d formula = 7.1 g\/100 mL, Preterm formula = 8.5 g\/100 mL.<\/li>\n        <li><b>Default energy (editable):<\/b> IV dextrose kcal\/100 mL is auto-calculated as (g\/100 mL \u00d7 3.4); Normal formula = 67 kcal\/100 mL (~20 kcal\/oz), Preterm formula = 80 kcal\/100 mL (~24 kcal\/oz).<\/li>\n        <li><b>Intermittent milk<\/b>: average mL\/hr = (mL per feed) \u00f7 (hours between feeds). Daily volume = mL\/hr \u00d7 24.<\/li>\n        <li><b>Total glucose (mg\/hr)<\/b> = \u03a3[ avg mL\/hr \u00d7 (g\/100 mL \u00d7 10) ].<\/li>\n        <li><b>Overall GIR (mg\/kg\/min)<\/b> = \u03a3[ mg\/hr ] \u00f7 (wt kg \u00d7 60).<\/li>\n        <li><b>Total energy<\/b> = \u03a3[ avg mL\/hr \u00d7 (kcal\/100 mL \u00f7 100) \u00d7 24 ], then kcal\/kg\/day = total \u00f7 wt.<\/li>\n      <\/ul>\n    <\/div>\n  <\/details>\n<\/div>\n\n<script>\n(function(){\n  const presets = {\n    \"D10 (IV dextrose)\": { glu:10, kcal:null },      \/\/ kcal computed from glu \u00d7 3.4\n    \"D12.5 (IV dextrose)\": { glu:12.5, kcal:null },\n    \"D20 (IV dextrose)\": { glu:20, kcal:null },\n    \"Normal formula\": { glu:7.1, kcal:67 },          \/\/ ~20 kcal\/oz\n    \"Preterm formula\": { glu:8.5, kcal:80 },         \/\/ ~24 kcal\/oz\n    \"Custom\": { glu:\"\", kcal:\"\" }\n  };\n\n  const modes = [\n    { val:\"continuous\", label:\"Continuous (mL\/hr)\" },\n    { val:\"q2\", label:\"q2h (mL\/feed)\" },\n    { val:\"q3\", label:\"q3h (mL\/feed)\" },\n    { val:\"q4\", label:\"q4h (mL\/feed)\" },\n  ];\n\n  const rowsEl = document.getElementById('rows');\n  const addBtn = document.getElementById('addRow');\n  const resetBtn = document.getElementById('resetAll');\n  const wtEl = document.getElementById('wt');\n\n  const outMlDay = document.getElementById('totMlDay');\n  const outMlKgDay = document.getElementById('totMlKgDay');\n  const outGIR = document.getElementById('girOverall');\n  const outKcalDay = document.getElementById('kcalDay');\n  const outKcalKgDay = document.getElementById('kcalKgDay');\n\n  function makeRow(){\n    const row = document.createElement('div');\n    row.className = 'row';\n    row.innerHTML = `\n      <div>\n        <label>Type<\/label>\n        <select class=\"type\">\n          ${Object.keys(presets).map(k=>`<option value=\"${k}\">${k}<\/option>`).join('')}\n        <\/select>\n      <\/div>\n      <div>\n        <label>Glucose (g\/100 mL)<\/label>\n        <input class=\"glu\" type=\"number\" min=\"0\" step=\"0.1\" placeholder=\"e.g. 10\">\n      <\/div>\n      <div>\n        <label>Energy (kcal\/100 mL)<\/label>\n        <input class=\"kcal\" type=\"number\" min=\"0\" step=\"0.1\" placeholder=\"auto for IV dextrose\">\n      <\/div>\n      <div>\n        <label>Mode<\/label>\n        <select class=\"mode\">\n          ${modes.map(m=>`<option value=\"${m.val}\">${m.label}<\/option>`).join('')}\n        <\/select>\n      <\/div>\n      <div>\n        <label class=\"amt-label\">Amount (mL\/hr)<\/label>\n        <input class=\"amt\" type=\"number\" min=\"0\" step=\"0.1\" placeholder=\"e.g. 6\">\n      <\/div>\n      <div>\n        <label>Avg flow (mL\/hr)<\/label>\n        <input class=\"avg\" type=\"number\" step=\"0.01\" disabled>\n      <\/div>\n      <div>\n        <button class=\"btn danger del\" title=\"Remove\">\u2716<\/button>\n      <\/div>\n    `;\n\n    const typeSel = row.querySelector('.type');\n    const gluIn = row.querySelector('.glu');\n    const kcalIn = row.querySelector('.kcal');\n    const modeSel = row.querySelector('.mode');\n    const amtLabel = row.querySelector('.amt-label');\n    const amtIn = row.querySelector('.amt');\n    const avgIn = row.querySelector('.avg');\n    const delBtn = row.querySelector('.del');\n\n    function setPreset(){\n      const key = typeSel.value;\n      const preset = presets[key];\n\n      \/\/ Glucose preset\n      if (preset.glu === \"\") { gluIn.value = \"\"; gluIn.placeholder = \"enter g\/100 mL\"; }\n      else { gluIn.value = preset.glu; }\n\n      \/\/ Energy preset\n      if (key.includes(\"IV dextrose\")){\n        \/\/ auto from glucose \u00d7 3.4 kcal\/g (parenteral dextrose)\n        const g = parseFloat(gluIn.value || 0);\n        kcalIn.value = g ? (g * 3.4).toFixed(1) : \"\";\n        kcalIn.placeholder = \"auto from glucose \u00d7 3.4\";\n      } else if (preset.kcal === \"\") {\n        kcalIn.value = \"\";\n        kcalIn.placeholder = \"enter kcal\/100 mL\";\n      } else {\n        kcalIn.value = preset.kcal;\n      }\n\n      recalc();\n    }\n\n    function applyModeUI(){\n      const m = modeSel.value;\n      if (m === 'continuous'){\n        amtLabel.textContent = \"Amount (mL\/hr)\";\n        amtIn.placeholder = \"e.g. 6\";\n      } else {\n        amtLabel.textContent = \"Amount (mL\/feed)\";\n        amtIn.placeholder = \"e.g. 18\";\n      }\n      recalc();\n    }\n\n    function avgMlHr(){\n      const m = modeSel.value;\n      const amt = parseFloat(amtIn.value||0);\n      if (!amt || amt<0) return 0;\n      if (m === 'continuous') return amt;\n      if (m === 'q2') return amt\/2;\n      if (m === 'q3') return amt\/3;\n      if (m === 'q4') return amt\/4;\n      return 0;\n    }\n\n    function recalc(){\n      \/\/ keep IV dextrose kcal synced to glucose edits\n      const key = typeSel.value;\n      if (key.includes(\"IV dextrose\")){\n        const g = parseFloat(gluIn.value || 0);\n        kcalIn.value = g ? (g * 3.4).toFixed(1) : \"\";\n      }\n\n      const avg = avgMlHr();\n      avgIn.value = avg ? avg.toFixed(2) : \"\";\n      computeTotals();\n    }\n\n    typeSel.addEventListener('change', setPreset);\n    modeSel.addEventListener('change', applyModeUI);\n    [gluIn, kcalIn, amtIn].forEach(el=>el.addEventListener('input', recalc));\n    delBtn.addEventListener('click', ()=>{ row.remove(); computeTotals(); });\n\n    \/\/ initialize\n    setPreset();\n    applyModeUI();\n    return row;\n  }\n\n  function computeTotals(){\n    const wt = parseFloat(wtEl.value);\n    let totalMlHr = 0;\n    let totalMgHr = 0;      \/\/ glucose mg per hour\n    let totalKcalDay = 0;   \/\/ kcal\/day\n\n    rowsEl.querySelectorAll('.row').forEach(row=>{\n      const glu = parseFloat(row.querySelector('.glu').value || 0);   \/\/ g\/100 mL\n      const kcal100 = parseFloat(row.querySelector('.kcal').value || 0); \/\/ kcal\/100 mL\n      const avg = parseFloat(row.querySelector('.avg').value || 0);   \/\/ mL\/hr\n\n      const mgPerMl = glu * 10; \/\/ mg\/mL\n      const mgHr = avg * mgPerMl;\n      totalMgHr += mgHr;\n\n      const kcalPerMl = kcal100 \/ 100;\n      const kcalDay = avg * kcalPerMl * 24;\n      totalKcalDay += kcalDay;\n\n      totalMlHr += avg;\n    });\n\n    const mlDay = totalMlHr * 24;\n    outMlDay.textContent = (mlDay).toFixed(1);\n\n    if (wt && wt>0){\n      const mlKgDay = mlDay \/ wt;\n      outMlKgDay.textContent = mlKgDay.toFixed(1) + \" mL\/kg\/day\";\n      const gir = totalMgHr \/ (wt * 60); \/\/ mg\/kg\/min\n      outGIR.textContent = isFinite(gir) ? gir.toFixed(2) : \"\u2014\";\n      const kcalKgDay = totalKcalDay \/ wt;\n      outKcalKgDay.textContent = isFinite(kcalKgDay) ? kcalKgDay.toFixed(1) + \" kcal\/kg\/day\" : \"\u2014\";\n    } else {\n      outMlKgDay.textContent = \"Enter weight\";\n      outGIR.textContent = \"Enter weight\";\n      outKcalKgDay.textContent = \"Enter weight\";\n    }\n\n    outKcalDay.textContent = totalKcalDay.toFixed(0);\n  }\n\n  addBtn.addEventListener('click', ()=>{\n    rowsEl.appendChild(makeRow());\n    computeTotals();\n  });\n  resetBtn.addEventListener('click', ()=>{\n    rowsEl.innerHTML = \"\";\n    wtEl.value = \"\";\n    addDefaultRows();\n    computeTotals();\n  });\n  wtEl.addEventListener('input', computeTotals);\n\n  function addDefaultRows(){\n    \/\/ one IV and one milk row to start\n    const r1 = makeRow();\n    r1.querySelector('.type').value = \"D10 (IV dextrose)\";\n    r1.querySelector('.glu').value = presets[\"D10 (IV dextrose)\"].glu;\n    rowsEl.appendChild(r1);\n\n    const r2 = makeRow();\n    r2.querySelector('.type').value = \"Normal formula\";\n    r2.querySelector('.glu').value = presets[\"Normal formula\"].glu;\n    r2.querySelector('.kcal').value = presets[\"Normal formula\"].kcal;\n    r2.querySelector('.mode').value = \"q3\";\n    r2.querySelector('.amt-label').textContent = \"Amount (mL\/feed)\";\n    rowsEl.appendChild(r2);\n  }\n\n  addDefaultRows();\n  computeTotals();\n})();\n<\/script>\n\n","protected":false},"excerpt":{"rendered":"<p>GIR, TFI &#038; Calories Calculator (IVF + Milk) Weight (kg) \u2795 Add row \u21ba Reset TFI \u2014 0 mL\/day GIR \u2014 mg\/kg\/min Calories \u2014 0 kcal\/day Notes &#038; formulas Default sugar (editable): D10 = 10 g\/100 mL, D12.5 = 12.5 g\/100 mL, D20 = 20 g\/100 mL, Term\/\u201cnormal\u201d formula = 7.1 g\/100 mL, Preterm formula&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"page-full.php","meta":{"footnotes":""},"tags":[],"class_list":["post-513","page","type-page","status-publish","article"],"_links":{"self":[{"href":"https:\/\/tomchan.hk\/index.php?rest_route=\/wp\/v2\/pages\/513","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tomchan.hk\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/tomchan.hk\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/tomchan.hk\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/tomchan.hk\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=513"}],"version-history":[{"count":10,"href":"https:\/\/tomchan.hk\/index.php?rest_route=\/wp\/v2\/pages\/513\/revisions"}],"predecessor-version":[{"id":525,"href":"https:\/\/tomchan.hk\/index.php?rest_route=\/wp\/v2\/pages\/513\/revisions\/525"}],"wp:attachment":[{"href":"https:\/\/tomchan.hk\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=513"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tomchan.hk\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=513"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}