Spaces:
Running
Running
Download index.html from bilanz/quickcheck: direct link, hf CLI and curl.
- Browser
- Download file 18.8 kB
-
https://huggingface.co/spaces/bilanz/quickcheck/resolve/main/index.html
- Command line
-
hf download hf://spaces/bilanz/quickcheck/index.html
-
curl -L -o index.html https://huggingface.co/spaces/bilanz/quickcheck/resolve/main/index.html
18.8 kB
| <html lang="de"> | |
| <head> | |
| <meta charset="utf-8"> | |
| <meta name="viewport" content="width=device-width,initial-scale=1"> | |
| <meta name="description" content="Bilanz QuickCheck: Bilanzkennzahlen lokal im Browser berechnen und Geschäftsjahre vergleichen."> | |
| <title>Bilanz QuickCheck</title> | |
| <style> | |
| :root{ | |
| --bg:#071522; | |
| --panel:#0d2233; | |
| --panel2:#102a3e; | |
| --line:#24465f; | |
| --text:#edf7fb; | |
| --muted:#9eb7c5; | |
| --cyan:#26d0ce; | |
| --blue:#3e8cff; | |
| --green:#55d98b; | |
| --warn:#ffd166; | |
| --danger:#ff7b7b; | |
| --white:#fff; | |
| --shadow:0 18px 60px rgba(0,0,0,.28); | |
| } | |
| *{box-sizing:border-box} | |
| html{scroll-behavior:smooth} | |
| body{ | |
| margin:0; | |
| font-family:Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; | |
| background: | |
| radial-gradient(circle at 10% 0%, rgba(38,208,206,.14), transparent 28rem), | |
| radial-gradient(circle at 90% 15%, rgba(62,140,255,.13), transparent 28rem), | |
| var(--bg); | |
| color:var(--text); | |
| line-height:1.5; | |
| } | |
| a{color:var(--cyan)} | |
| .wrap{max-width:1180px;margin:auto;padding:26px 20px 60px} | |
| .hero{ | |
| border:1px solid var(--line); | |
| background:linear-gradient(135deg,rgba(16,42,62,.95),rgba(7,21,34,.96)); | |
| border-radius:26px; | |
| padding:30px; | |
| box-shadow:var(--shadow); | |
| margin-bottom:20px; | |
| } | |
| .badge{ | |
| display:inline-flex;gap:8px;align-items:center; | |
| padding:7px 11px;border-radius:999px; | |
| background:rgba(38,208,206,.1); | |
| border:1px solid rgba(38,208,206,.28); | |
| color:#b9ffff;font-size:13px;font-weight:700; | |
| } | |
| h1{font-size:clamp(32px,5vw,58px);line-height:1.02;margin:16px 0 10px;letter-spacing:-.04em} | |
| .hero p{max-width:780px;color:var(--muted);font-size:17px;margin:0} | |
| .hero-actions{display:flex;flex-wrap:wrap;gap:10px;margin-top:22px} | |
| button{ | |
| border:0;border-radius:12px;padding:11px 15px; | |
| font-weight:800;cursor:pointer;font-size:14px; | |
| transition:.15s transform,.15s opacity,.15s background; | |
| } | |
| button:hover{transform:translateY(-1px)} | |
| .primary{background:linear-gradient(135deg,var(--cyan),var(--blue));color:#04111c} | |
| .secondary{background:#17354a;color:var(--text);border:1px solid var(--line)} | |
| .ghost{background:transparent;color:var(--muted);border:1px solid var(--line)} | |
| .grid{display:grid;grid-template-columns:1fr 1fr;gap:18px} | |
| .panel{ | |
| border:1px solid var(--line); | |
| background:rgba(13,34,51,.94); | |
| border-radius:20px; | |
| padding:20px; | |
| box-shadow:0 12px 38px rgba(0,0,0,.15); | |
| } | |
| .panel h2{margin:0 0 5px;font-size:20px} | |
| .sub{color:var(--muted);font-size:13px;margin-bottom:16px} | |
| .year-label{ | |
| display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:14px | |
| } | |
| .year-input{ | |
| width:90px;border-radius:10px;border:1px solid var(--line); | |
| background:#081a28;color:var(--text);padding:8px 10px;font-weight:800 | |
| } | |
| .section-title{ | |
| margin:18px 0 9px; | |
| font-size:12px;letter-spacing:.12em;text-transform:uppercase;color:#7fe5e3;font-weight:900 | |
| } | |
| .field-grid{display:grid;grid-template-columns:1fr 160px;gap:8px 12px;align-items:center} | |
| label{font-size:14px;color:#d8e7ee} | |
| input[type="number"]{ | |
| width:100%;padding:10px 12px;border-radius:10px; | |
| border:1px solid var(--line);background:#081a28;color:var(--text); | |
| outline:none;font-size:15px;text-align:right; | |
| } | |
| input[type="number"]:focus{border-color:var(--cyan);box-shadow:0 0 0 3px rgba(38,208,206,.08)} | |
| .summary-row{ | |
| margin-top:15px;padding-top:13px;border-top:1px solid var(--line); | |
| display:grid;grid-template-columns:1fr 1fr;gap:10px | |
| } | |
| .sum-box{background:#081a28;border:1px solid var(--line);padding:12px;border-radius:12px} | |
| .sum-box small{display:block;color:var(--muted)} | |
| .sum-box strong{font-size:18px} | |
| .balance-message{ | |
| margin-top:10px;padding:10px 12px;border-radius:11px; | |
| font-size:13px;border:1px solid var(--line);background:#081a28;color:var(--muted) | |
| } | |
| .results{margin-top:18px} | |
| .results-head{display:flex;align-items:end;justify-content:space-between;gap:12px;margin-bottom:12px} | |
| .results-head h2{margin:0;font-size:26px} | |
| .results-head p{margin:0;color:var(--muted);font-size:13px} | |
| .metrics{display:grid;grid-template-columns:repeat(3,1fr);gap:12px} | |
| .metric{ | |
| background:linear-gradient(180deg,#102a3e,#0a1d2c); | |
| border:1px solid var(--line);border-radius:16px;padding:15px;min-height:128px | |
| } | |
| .metric-name{font-size:13px;color:var(--muted);font-weight:700} | |
| .metric-value{font-size:28px;font-weight:900;margin:5px 0 2px;letter-spacing:-.03em} | |
| .metric-delta{font-size:12px;font-weight:800;min-height:18px} | |
| .metric-info{font-size:12px;color:#89a6b6;margin-top:7px} | |
| .up{color:var(--green)} .down{color:var(--danger)} .flat{color:var(--muted)} | |
| .visuals{display:grid;grid-template-columns:1fr 1fr;gap:18px;margin-top:18px} | |
| .stack{display:flex;width:100%;height:28px;border-radius:999px;overflow:hidden;background:#081a28;border:1px solid var(--line);margin:10px 0 12px} | |
| .seg{height:100%;min-width:0;transition:width .35s ease} | |
| .legend{display:flex;flex-wrap:wrap;gap:10px 14px;font-size:12px;color:var(--muted)} | |
| .dot{width:9px;height:9px;border-radius:50%;display:inline-block;margin-right:5px} | |
| .s1{background:#26d0ce}.s2{background:#3e8cff}.s3{background:#8f7cff}.s4{background:#55d98b}.s5{background:#ffd166} | |
| .explainer{margin-top:18px} | |
| details{border-top:1px solid var(--line);padding:12px 0} | |
| details:first-of-type{border-top:0} | |
| summary{cursor:pointer;font-weight:800} | |
| details p{color:var(--muted);font-size:13px;margin:8px 0 0} | |
| .notice{ | |
| margin-top:18px;border:1px solid rgba(255,209,102,.28); | |
| background:rgba(255,209,102,.06);border-radius:16px;padding:16px;color:#dbe6ea;font-size:13px | |
| } | |
| .privacy{ | |
| display:flex;gap:10px;align-items:flex-start; | |
| margin-top:18px;border:1px solid rgba(85,217,139,.25); | |
| background:rgba(85,217,139,.07);padding:14px 16px;border-radius:16px | |
| } | |
| .privacy strong{color:#b9ffd2} | |
| footer{margin-top:24px;color:#6f8c9d;font-size:12px;text-align:center} | |
| .hidden{display:none} | |
| @media (max-width:880px){ | |
| .grid,.visuals{grid-template-columns:1fr} | |
| .metrics{grid-template-columns:repeat(2,1fr)} | |
| } | |
| @media (max-width:560px){ | |
| .wrap{padding:14px 12px 40px} | |
| .hero,.panel{padding:17px;border-radius:16px} | |
| .field-grid{grid-template-columns:1fr 135px} | |
| .metrics{grid-template-columns:1fr} | |
| .summary-row{grid-template-columns:1fr} | |
| } | |
| @media print{ | |
| body{background:white;color:#111} | |
| .wrap{max-width:none;padding:0} | |
| .hero-actions,.input-area,.privacy,footer{display:none} | |
| .hero,.panel,.metric{box-shadow:none;background:white;color:#111;border-color:#ccc} | |
| .hero p,.sub,.metric-name,.metric-info,.results-head p,.legend,.notice,details p{color:#444} | |
| .results{margin-top:0} | |
| .metrics{grid-template-columns:repeat(3,1fr)} | |
| .visuals{grid-template-columns:1fr 1fr} | |
| .badge{color:#111;background:#eee;border-color:#ccc} | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="wrap"> | |
| <section class="hero"> | |
| <span class="badge">📊 Bilanz · Local-first Financial Tool</span> | |
| <h1>Bilanz QuickCheck</h1> | |
| <p>Zentrale Bilanzkennzahlen berechnen, zwei Geschäftsjahre vergleichen und die Finanzstruktur übersichtlich darstellen – direkt im Browser.</p> | |
| <div class="hero-actions"> | |
| <button class="primary" onclick="loadDemo()">Beispieldaten laden</button> | |
| <button class="secondary" onclick="window.print()">Bericht drucken / PDF</button> | |
| <button class="ghost" onclick="resetAll()">Zurücksetzen</button> | |
| </div> | |
| <div class="privacy"> | |
| <div>🔒</div> | |
| <div><strong>Private by design:</strong> Alle Werte werden ausschließlich in deinem Browser verarbeitet. Dieser Static Space überträgt oder speichert keine eingegebenen Finanzdaten.</div> | |
| </div> | |
| </section> | |
| <div class="grid input-area"> | |
| <section class="panel"> | |
| <div class="year-label"> | |
| <div> | |
| <h2>Aktuelles Jahr</h2> | |
| <div class="sub">Pflichtangaben für die Kennzahlen</div> | |
| </div> | |
| <input class="year-input" id="year0" type="number" value="2025" min="1900" max="2200" aria-label="Aktuelles Geschäftsjahr"> | |
| </div> | |
| <div id="fields0"></div> | |
| <div id="summary0"></div> | |
| </section> | |
| <section class="panel"> | |
| <div class="year-label"> | |
| <div> | |
| <h2>Vorjahr <span style="color:var(--muted);font-weight:500">(optional)</span></h2> | |
| <div class="sub">Für Veränderungsanalyse</div> | |
| </div> | |
| <input class="year-input" id="year1" type="number" value="2024" min="1900" max="2200" aria-label="Vorjahr"> | |
| </div> | |
| <div id="fields1"></div> | |
| <div id="summary1"></div> | |
| </section> | |
| </div> | |
| <section class="panel results"> | |
| <div class="results-head"> | |
| <div> | |
| <h2>Kennzahlen</h2> | |
| <p>Rechnerische Orientierung – keine fachliche Unternehmensbewertung.</p> | |
| </div> | |
| </div> | |
| <div class="metrics" id="metrics"></div> | |
| </section> | |
| <div class="visuals"> | |
| <section class="panel"> | |
| <h2>Vermögensstruktur</h2> | |
| <div class="sub">Zusammensetzung der Aktivseite im aktuellen Jahr</div> | |
| <div class="stack" id="assetsStack"></div> | |
| <div class="legend" id="assetsLegend"></div> | |
| </section> | |
| <section class="panel"> | |
| <h2>Finanzierungsstruktur</h2> | |
| <div class="sub">Zusammensetzung der Passivseite im aktuellen Jahr</div> | |
| <div class="stack" id="liabStack"></div> | |
| <div class="legend" id="liabLegend"></div> | |
| </section> | |
| </div> | |
| <section class="panel explainer"> | |
| <h2>Kennzahlen verstehen</h2> | |
| <div class="sub">Formeln und neutrale Einordnung</div> | |
| <details open> | |
| <summary>Eigenkapitalquote</summary> | |
| <p>Eigenkapital ÷ Bilanzsumme × 100. Sie beschreibt den Anteil des Vermögens, der rechnerisch durch Eigenkapital finanziert ist. Branchen und Geschäftsmodelle unterscheiden sich stark.</p> | |
| </details> | |
| <details> | |
| <summary>Verschuldungsgrad</summary> | |
| <p>Fremdkapital ÷ Eigenkapital × 100. Die Kennzahl stellt Fremd- und Eigenfinanzierung gegenüber. Bei sehr geringem oder negativem Eigenkapital verliert die Kennzahl an Aussagekraft.</p> | |
| </details> | |
| <details> | |
| <summary>Working Capital</summary> | |
| <p>Umlaufvermögen minus kurzfristige Verbindlichkeiten. Es zeigt den rechnerischen Überschuss beziehungsweise Fehlbetrag kurzfristig gebundener Vermögenswerte gegenüber kurzfristigen Verpflichtungen.</p> | |
| </details> | |
| <details> | |
| <summary>Liquidität 1., 2. und 3. Grades</summary> | |
| <p>Vergleichen liquide Mittel, liquide Mittel plus Forderungen beziehungsweise das gesamte Umlaufvermögen mit kurzfristigen Verbindlichkeiten. Die Aussage hängt unter anderem von Zahlungszielen, Forderungsqualität und Vorratsstruktur ab.</p> | |
| </details> | |
| <details> | |
| <summary>Anlagendeckung I und II</summary> | |
| <p>Vergleichen Anlagevermögen mit langfristig verfügbarem Kapital. Anlagendeckung I verwendet Eigenkapital, Anlagendeckung II zusätzlich langfristige Verbindlichkeiten.</p> | |
| </details> | |
| </section> | |
| <div class="notice"> | |
| <strong>Wichtiger Hinweis:</strong> Bilanz QuickCheck ist ein technisches Analyse- und Lernwerkzeug. Es ersetzt keine Steuerberatung, Rechtsberatung, Wirtschaftsprüfung, Kreditentscheidung oder Unternehmensbewertung. Kennzahlen sind ohne Branchen-, Zeitreihen- und Unternehmenskontext nicht abschließend interpretierbar. | |
| </div> | |
| <footer>Bilanz · Independent Hugging Face Community Project</footer> | |
| </div> | |
| <script> | |
| const fieldDefs = [ | |
| {group:"Aktiva", key:"fixed", label:"Anlagevermögen"}, | |
| {group:"Aktiva", key:"inventory", label:"Vorräte"}, | |
| {group:"Aktiva", key:"receivables", label:"Forderungen"}, | |
| {group:"Aktiva", key:"cash", label:"Liquide Mittel"}, | |
| {group:"Aktiva", key:"otherCurrent", label:"Sonstiges Umlaufvermögen"}, | |
| {group:"Passiva", key:"equity", label:"Eigenkapital"}, | |
| {group:"Passiva", key:"longDebt", label:"Langfristige Verbindlichkeiten"}, | |
| {group:"Passiva", key:"shortDebt", label:"Kurzfristige Verbindlichkeiten"}, | |
| {group:"Passiva", key:"provisions", label:"Rückstellungen"}, | |
| {group:"Passiva", key:"otherLiab", label:"Sonstige Passiva"} | |
| ]; | |
| function euro(n){ | |
| if(!Number.isFinite(n)) return "–"; | |
| return new Intl.NumberFormat("de-DE",{style:"currency",currency:"EUR",maximumFractionDigits:0}).format(n); | |
| } | |
| function pct(n){ | |
| if(!Number.isFinite(n)) return "–"; | |
| return new Intl.NumberFormat("de-DE",{maximumFractionDigits:1,minimumFractionDigits:1}).format(n)+" %"; | |
| } | |
| function num(id){ | |
| const v=parseFloat(document.getElementById(id)?.value); | |
| return Number.isFinite(v)?v:0; | |
| } | |
| function safeDiv(a,b){ return b!==0 ? a/b : NaN; } | |
| function renderFields(yearIndex){ | |
| let html="", lastGroup=""; | |
| for(const f of fieldDefs){ | |
| if(f.group!==lastGroup){ | |
| html+=`<div class="section-title">${f.group}</div><div class="field-grid">`; | |
| lastGroup=f.group; | |
| } | |
| html+=`<label for="${f.key}${yearIndex}">${f.label}</label> | |
| <input id="${f.key}${yearIndex}" data-y="${yearIndex}" type="number" min="0" step="1000" placeholder="0" inputmode="decimal">`; | |
| const next=fieldDefs[fieldDefs.indexOf(f)+1]; | |
| if(!next || next.group!==f.group) html+="</div>"; | |
| } | |
| document.getElementById("fields"+yearIndex).innerHTML=html; | |
| } | |
| function getYear(i){ | |
| const x={}; | |
| fieldDefs.forEach(f=>x[f.key]=num(f.key+i)); | |
| x.current=x.inventory+x.receivables+x.cash+x.otherCurrent; | |
| x.assets=x.fixed+x.current; | |
| x.debt=x.longDebt+x.shortDebt+x.provisions+x.otherLiab; | |
| x.liabilities=x.equity+x.debt; | |
| x.diff=x.assets-x.liabilities; | |
| return x; | |
| } | |
| function metricsFor(x){ | |
| return { | |
| equityRatio: safeDiv(x.equity,x.assets)*100, | |
| debtRatio: safeDiv(x.debt,x.liabilities)*100, | |
| debtEquity: safeDiv(x.debt,x.equity)*100, | |
| workingCapital: x.current-x.shortDebt, | |
| cashRatio: safeDiv(x.cash,x.shortDebt)*100, | |
| quickRatio: safeDiv(x.cash+x.receivables,x.shortDebt)*100, | |
| currentRatio: safeDiv(x.current,x.shortDebt)*100, | |
| cover1: safeDiv(x.equity,x.fixed)*100, | |
| cover2: safeDiv(x.equity+x.longDebt,x.fixed)*100, | |
| fixedIntensity: safeDiv(x.fixed,x.assets)*100, | |
| cashShare: safeDiv(x.cash,x.assets)*100 | |
| }; | |
| } | |
| const metricDefs = [ | |
| ["equityRatio","Eigenkapitalquote","pct","Eigenkapital ÷ Bilanzsumme"], | |
| ["debtRatio","Fremdkapitalquote","pct","Fremdkapital ÷ Passivsumme"], | |
| ["debtEquity","Verschuldungsgrad","pct","Fremdkapital ÷ Eigenkapital"], | |
| ["workingCapital","Working Capital","eur","Umlaufvermögen − kurzfr. Verbindlichkeiten"], | |
| ["cashRatio","Liquidität 1. Grades","pct","Liquide Mittel ÷ kurzfr. Verbindlichkeiten"], | |
| ["quickRatio","Liquidität 2. Grades","pct","Liquide Mittel + Forderungen ÷ kurzfr. Verbindlichkeiten"], | |
| ["currentRatio","Liquidität 3. Grades","pct","Umlaufvermögen ÷ kurzfr. Verbindlichkeiten"], | |
| ["cover1","Anlagendeckung I","pct","Eigenkapital ÷ Anlagevermögen"], | |
| ["cover2","Anlagendeckung II","pct","EK + langfristige Verbindlichkeiten ÷ Anlagevermögen"], | |
| ["fixedIntensity","Anlagenintensität","pct","Anlagevermögen ÷ Bilanzsumme"], | |
| ["cashShare","Anteil liquide Mittel","pct","Liquide Mittel ÷ Bilanzsumme"] | |
| ]; | |
| function hasPrior(){ | |
| return fieldDefs.some(f=>num(f.key+"1")!==0); | |
| } | |
| function renderSummary(i,x){ | |
| const tolerance=Math.max(x.assets,x.liabilities,1)*0.001; | |
| const balanced=Math.abs(x.diff)<=tolerance; | |
| document.getElementById("summary"+i).innerHTML=` | |
| <div class="summary-row"> | |
| <div class="sum-box"><small>Summe Aktiva</small><strong>${euro(x.assets)}</strong></div> | |
| <div class="sum-box"><small>Summe Passiva</small><strong>${euro(x.liabilities)}</strong></div> | |
| </div> | |
| <div class="balance-message" style="border-color:${balanced?'rgba(85,217,139,.28)':'rgba(255,123,123,.35)'}"> | |
| ${balanced?'✓ Aktiv- und Passivsumme stimmen rechnerisch überein.':'⚠ Bilanzdifferenz: '+euro(x.diff)+'. Eingaben prüfen.'} | |
| </div>`; | |
| } | |
| function deltaText(a,b,type){ | |
| if(!Number.isFinite(a)||!Number.isFinite(b)) return ["","flat"]; | |
| const d=a-b; | |
| const threshold=type==="eur" ? 0.5 : 0.05; | |
| if(Math.abs(d)<threshold) return ["Keine Veränderung","flat"]; | |
| const value=type==="eur"?euro(Math.abs(d)):pct(Math.abs(d)); | |
| return [(d>0?"▲ ":"▼ ")+value+" ggü. Vorjahr",d>0?"up":"down"]; | |
| } | |
| function renderMetrics(m0,m1){ | |
| const prior=hasPrior(); | |
| document.getElementById("metrics").innerHTML=metricDefs.map(([k,name,type,info])=>{ | |
| const val=type==="eur"?euro(m0[k]):pct(m0[k]); | |
| let d=["","flat"]; | |
| if(prior) d=deltaText(m0[k],m1[k],type); | |
| return `<div class="metric"> | |
| <div class="metric-name">${name}</div> | |
| <div class="metric-value">${val}</div> | |
| <div class="metric-delta ${d[1]}">${d[0]}</div> | |
| <div class="metric-info">${info}</div> | |
| </div>`; | |
| }).join(""); | |
| } | |
| function stack(el, legendEl, items){ | |
| const total=items.reduce((s,x)=>s+x.value,0); | |
| document.getElementById(el).innerHTML=items.map((x,i)=>{ | |
| const w=total?Math.max(0,x.value/total*100):0; | |
| return `<div class="seg s${i+1}" style="width:${w}%" title="${x.name}: ${pct(w)}"></div>`; | |
| }).join(""); | |
| document.getElementById(legendEl).innerHTML=items.map((x,i)=>{ | |
| const w=total?x.value/total*100:0; | |
| return `<span><i class="dot s${i+1}"></i>${x.name} ${pct(w)}</span>`; | |
| }).join(""); | |
| } | |
| function update(){ | |
| const y0=getYear(0), y1=getYear(1); | |
| renderSummary(0,y0); renderSummary(1,y1); | |
| renderMetrics(metricsFor(y0),metricsFor(y1)); | |
| stack("assetsStack","assetsLegend",[ | |
| {name:"Anlagevermögen",value:y0.fixed}, | |
| {name:"Vorräte",value:y0.inventory}, | |
| {name:"Forderungen",value:y0.receivables}, | |
| {name:"Liquide Mittel",value:y0.cash}, | |
| {name:"Sonst. UV",value:y0.otherCurrent} | |
| ]); | |
| stack("liabStack","liabLegend",[ | |
| {name:"Eigenkapital",value:y0.equity}, | |
| {name:"Langfr. Verb.",value:y0.longDebt}, | |
| {name:"Kurzfr. Verb.",value:y0.shortDebt}, | |
| {name:"Rückstellungen",value:y0.provisions}, | |
| {name:"Sonst. Passiva",value:y0.otherLiab} | |
| ]); | |
| } | |
| function setVals(i, vals){ | |
| for(const [k,v] of Object.entries(vals)){ | |
| const e=document.getElementById(k+i); | |
| if(e) e.value=v; | |
| } | |
| } | |
| function loadDemo(){ | |
| setVals(0,{ | |
| fixed:4800000,inventory:950000,receivables:1750000,cash:1200000,otherCurrent:300000, | |
| equity:3600000,longDebt:2450000,shortDebt:1950000,provisions:700000,otherLiab:300000 | |
| }); | |
| setVals(1,{ | |
| fixed:4550000,inventory:900000,receivables:1600000,cash:950000,otherCurrent:250000, | |
| equity:3250000,longDebt:2400000,shortDebt:1850000,provisions:550000,otherLiab:200000 | |
| }); | |
| document.getElementById("year0").value=2025; | |
| document.getElementById("year1").value=2024; | |
| update(); | |
| } | |
| function resetAll(){ | |
| fieldDefs.forEach(f=>{document.getElementById(f.key+"0").value="";document.getElementById(f.key+"1").value=""}); | |
| update(); | |
| } | |
| renderFields(0); | |
| renderFields(1); | |
| document.addEventListener("input",e=>{ | |
| if(e.target.matches('input[type="number"]')) update(); | |
| }); | |
| update(); | |
| </script> | |
| </body> | |
| </html> | |