Skip to content

Commit 9f7a17b

Browse files
Merge pull request #46 from Pawankalyan2023/main
BMI: Improve Input Validation and Error Handling
2 parents 054af55 + 12b5d21 commit 9f7a17b

3 files changed

Lines changed: 94 additions & 8 deletions

File tree

projects/bmi/index.html

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@
1111
<body>
1212
<main>
1313
<h1>BMI Calculator</h1>
14-
<form id="form"><input id="kg" type="number" step="0.1" placeholder="Weight (kg)" required> <input id="cm"
15-
type="number" step="0.1" placeholder="Height (cm)" required> <button>Calculate</button></form>
16-
<div id="out"></div>
14+
<form id="form"><input id="kg" name="kg" type="number" step="0.1" placeholder="Weight (kg)" required>
15+
<input id="cm" name="cm" type="number" step="0.1" placeholder="Height (cm)" required>
16+
<button type="submit">Calculate</button>
17+
</form>
18+
<div id="out" aria-live="polite"></div>
1719
<p class="notes">Add validation and history with localStorage.</p>
1820
</main>
1921
<script type="module" src="./main.js"></script>

projects/bmi/main.js

Lines changed: 83 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,85 @@
11
const kg = document.getElementById('kg'); const cm = document.getElementById('cm'); const out = document.getElementById('out');
2-
function bmi() {
3-
const w = parseFloat(kg.value), h = parseFloat(cm.value) / 100;
4-
if (!(w > 0 && h > 0)) { out.textContent = 'Enter valid numbers'; return; } const v = w / (h * h); let cat = v < 18.5 ? 'Underweight' : v < 25 ? 'Normal' : v < 30 ? 'Overweight' : 'Obese'; out.textContent = `BMI: ${v.toFixed(1)} (${cat})`;
2+
function validateWeight(raw) {
3+
if (!raw) return 'Please enter your weight (kg).';
4+
const v = Number(raw);
5+
if (!Number.isFinite(v)) return 'Weight must be a number (e.g., 70).';
6+
if (v <= 0) return 'Weight must be greater than 0 kg.';
7+
if (v < 20 || v > 300) return 'Please enter a realistic weight (20–300 kg).';
8+
return '';
59
}
6-
document.getElementById('form').addEventListener('submit', e => { e.preventDefault(); bmi(); });
7-
// TODOs: save history; chart; unit toggle; input validation states
10+
11+
function validateHeight(raw) {
12+
if (!raw) return 'Please enter your height (cm).';
13+
const v = Number(raw);
14+
if (!Number.isFinite(v)) return 'Height must be a number (e.g., 170).';
15+
if (v <= 0) return 'Height must be greater than 0 cm.';
16+
if (v < 50 || v > 250) return 'Please enter a realistic height (50–250 cm).';
17+
return '';
18+
}
19+
20+
function clearCustomValidity() {
21+
kg.setCustomValidity('');
22+
cm.setCustomValidity('');
23+
kg.removeAttribute('aria-invalid'); kg.style.borderColor = '';
24+
cm.removeAttribute('aria-invalid'); cm.style.borderColor = '';
25+
}
26+
27+
function markFieldInvalid(el) {
28+
if (!el) return;
29+
el.setAttribute('aria-invalid', 'true');
30+
el.style.borderColor = '#ff6b6b';
31+
}
32+
33+
function clearFieldInvalid(el) {
34+
if (!el) return;
35+
el.removeAttribute('aria-invalid');
36+
el.style.borderColor = '';
37+
}
38+
39+
form?.addEventListener('submit', e => {
40+
e.preventDefault();
41+
if (!kg || !cm || !out) return;
42+
43+
clearCustomValidity();
44+
45+
const weightRaw = (kg.value ?? '').trim();
46+
const heightRaw = (cm.value ?? '').trim();
47+
48+
const wErr = validateWeight(weightRaw);
49+
const hErr = validateHeight(heightRaw);
50+
51+
if (wErr) kg.setCustomValidity(wErr);
52+
if (hErr) cm.setCustomValidity(hErr);
53+
54+
if (wErr && hErr) {
55+
markFieldInvalid(kg);
56+
markFieldInvalid(cm);
57+
} else {
58+
if (wErr) markFieldInvalid(kg); else clearFieldInvalid(kg);
59+
if (hErr) markFieldInvalid(cm); else clearFieldInvalid(cm);
60+
}
61+
62+
if (!form.checkValidity()) {
63+
const firstInvalid = kg.validity.valid ? cm : kg;
64+
firstInvalid.reportValidity();
65+
firstInvalid.focus();
66+
out.textContent = 'You have invalid Details';
67+
return;
68+
}
69+
70+
const w = parseFloat(weightRaw);
71+
const heightCm = parseFloat(heightRaw);
72+
const h = heightCm / 100;
73+
const bmi = w / (h * h);
74+
const cat = bmi < 18.5 ? 'Underweight' : bmi < 25 ? 'Normal' : bmi < 30 ? 'Overweight' : 'Obese';
75+
out.textContent = `BMI: ${bmi.toFixed(1)} (${cat})`;
76+
clearCustomValidity();
77+
});
78+
79+
[kg, cm].forEach(el => {
80+
el?.addEventListener('input', () => {
81+
el.setCustomValidity('');
82+
clearFieldInvalid(el);
83+
});
84+
});
85+

projects/bmi/styles.css

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@ input {
2626
color: #eef1f8
2727
}
2828

29+
input[aria-invalid="true"],
30+
input.invalid {
31+
border-color: #ff6b6b;
32+
box-shadow: 0 0 0 4px rgba(255,107,107,0.06);
33+
}
34+
2935
button {
3036
background: #6ee7b7;
3137
color: #0b1020;

0 commit comments

Comments
 (0)