Skip to content

Commit dc57460

Browse files
committed
'Calorie Counter' **feat: step_89 add an event listener to the 'calorieCounter' element test 1
1 parent 04c015d commit dc57460

File tree

8 files changed

+606
-4
lines changed

8 files changed

+606
-4
lines changed

README.md

Lines changed: 4 additions & 2 deletions
Large diffs are not rendered by default.

images/previews/preview_step89.png

69.2 KB
Loading

steps/README.md

Lines changed: 4 additions & 2 deletions
Large diffs are not rendered by default.

steps/__89__step__/README.md

Lines changed: 346 additions & 0 deletions
Large diffs are not rendered by default.

steps/__89__step__/index.html

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<link rel="stylesheet" href="styles.css" />
7+
<title>Calorie Counter</title>
8+
</head>
9+
<body>
10+
<main>
11+
<h1>Calorie Counter</h1>
12+
<div class="container">
13+
<form id="calorie-counter">
14+
<label for="budget">Budget</label>
15+
<input
16+
type="number"
17+
min="0"
18+
id="budget"
19+
placeholder="Daily calorie budget"
20+
required
21+
/>
22+
<fieldset id="breakfast">
23+
<legend>Breakfast</legend>
24+
<div class="input-container"></div>
25+
</fieldset>
26+
<fieldset id="lunch">
27+
<legend>Lunch</legend>
28+
<div class="input-container"></div>
29+
</fieldset>
30+
<fieldset id="dinner">
31+
<legend>Dinner</legend>
32+
<div class="input-container"></div>
33+
</fieldset>
34+
<fieldset id="snacks">
35+
<legend>Snacks</legend>
36+
<div class="input-container"></div>
37+
</fieldset>
38+
<fieldset id="exercise">
39+
<legend>Exercise</legend>
40+
<div class="input-container"></div>
41+
</fieldset>
42+
<div class="controls">
43+
<span>
44+
<label for="entry-dropdown">Add food or exercise:</label>
45+
<select id="entry-dropdown" name="options">
46+
<option value="breakfast" selected>Breakfast</option>
47+
<option value="lunch">Lunch</option>
48+
<option value="dinner">Dinner</option>
49+
<option value="snacks">Snacks</option>
50+
<option value="exercise">Exercise</option>
51+
</select>
52+
<button type="button" id="add-entry">Add Entry</button>
53+
</span>
54+
</div>
55+
<div>
56+
<button type="submit">Calculate Remaining Calories</button>
57+
<button type="button" id="clear">Clear</button>
58+
</div>
59+
</form>
60+
<div id="output" class="output hide"></div>
61+
</div>
62+
</main>
63+
<script src="./script.js"></script>
64+
</body>
65+
</html>

steps/__89__step__/script.js

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
const calorieCounter = document.getElementById('calorie-counter');
2+
const budgetNumberInput = document.getElementById('budget');
3+
const entryDropdown = document.getElementById('entry-dropdown');
4+
const addEntryButton = document.getElementById('add-entry');
5+
const clearButton = document.getElementById('clear');
6+
const output = document.getElementById('output');
7+
let isError = false;
8+
9+
function cleanInputString(str) {
10+
const regex = /[+-\s]/g;
11+
return str.replace(regex, '');
12+
}
13+
14+
function isInvalidInput(str) {
15+
const regex = /\d+e\d+/i;
16+
return str.match(regex);
17+
}
18+
19+
function addEntry() {
20+
const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
21+
const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
22+
const HTMLString = `
23+
<label for="${entryDropdown.value}-${entryNumber}-name">Entry ${entryNumber} Name</label>
24+
<input type="text" id="${entryDropdown.value}-${entryNumber}-name" placeholder="Name" />
25+
<label for="${entryDropdown.value}-${entryNumber}-calories">Entry ${entryNumber} Calories</label>
26+
<input
27+
type="number"
28+
min="0"
29+
id="${entryDropdown.value}-${entryNumber}-calories"
30+
placeholder="Calories"
31+
/>`;
32+
targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
33+
}
34+
35+
36+
function calculateCalories(e) {
37+
e.preventDefault();
38+
isError = false;
39+
40+
const breakfastNumberInputs = document.querySelectorAll("#breakfast input[type='number']");
41+
const lunchNumberInputs = document.querySelectorAll("#lunch input[type='number']");
42+
const dinnerNumberInputs = document.querySelectorAll("#dinner input[type='number']");
43+
const snacksNumberInputs = document.querySelectorAll("#snacks input[type='number']");
44+
const exerciseNumberInputs = document.querySelectorAll("#exercise input[type='number']");
45+
46+
const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
47+
const lunchCalories = getCaloriesFromInputs(lunchNumberInputs);
48+
const dinnerCalories = getCaloriesFromInputs(dinnerNumberInputs);
49+
const snacksCalories = getCaloriesFromInputs(snacksNumberInputs);
50+
const exerciseCalories = getCaloriesFromInputs(exerciseNumberInputs);
51+
const budgetCalories = getCaloriesFromInputs([budgetNumberInput]);
52+
53+
if (isError) {
54+
return;
55+
}
56+
57+
const consumedCalories = breakfastCalories + lunchCalories + dinnerCalories + snacksCalories;
58+
const remainingCalories = budgetCalories - consumedCalories + exerciseCalories;
59+
const surplusOrDeficit = remainingCalories < 0 ? 'Surplus' : 'Deficit';
60+
output.innerHTML = `
61+
<span class="${surplusOrDeficit.toLowerCase()}">${Math.abs(remainingCalories)} Calorie ${surplusOrDeficit}</span>
62+
<hr>
63+
<p>${budgetCalories} Calories Budgeted</p>
64+
<p>${consumedCalories} Calories Consumed</p>
65+
<p>${exerciseCalories} Calories Burned</p>
66+
`;
67+
output.classList.remove("hide");3
68+
}
69+
70+
function getCaloriesFromInputs(list) {
71+
let calories = 0;
72+
73+
for (const item of list) {
74+
const currVal = cleanInputString(item.value);
75+
const invalidInputMatch = isInvalidInput(currVal);
76+
77+
if (invalidInputMatch) {
78+
alert(`Invalid Input: ${invalidInputMatch[0]}`);
79+
isError = true;
80+
return null;
81+
}
82+
calories += Number(currVal);
83+
}
84+
return calories;
85+
}
86+
87+
addEntryButton.addEventListener("click", addEntry);
88+
calorieCounter.addEventListener("submit", calculateCalories);
89+

steps/__89__step__/styles.css

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
:root {
2+
--light-grey: #f5f6f7;
3+
--dark-blue: #0a0a23;
4+
--fcc-blue: #1b1b32;
5+
--light-yellow: #fecc4c;
6+
--dark-yellow: #feac32;
7+
--light-pink: #ffadad;
8+
--dark-red: #850000;
9+
--light-green: #acd157;
10+
}
11+
12+
body {
13+
font-family: "Lato", Helvetica, Arial, sans-serif;
14+
font-size: 18px;
15+
background-color: var(--fcc-blue);
16+
color: var(--light-grey);
17+
}
18+
19+
h1 {
20+
text-align: center;
21+
}
22+
23+
.container {
24+
width: 90%;
25+
max-width: 680px;
26+
}
27+
28+
h1,
29+
.container,
30+
.output {
31+
margin: 20px auto;
32+
}
33+
34+
label,
35+
legend {
36+
font-weight: bold;
37+
}
38+
39+
.input-container {
40+
display: flex;
41+
flex-direction: column;
42+
}
43+
44+
button {
45+
cursor: pointer;
46+
text-decoration: none;
47+
background-color: var(--light-yellow);
48+
border: 2px solid var(--dark-yellow);
49+
}
50+
51+
button,
52+
input,
53+
select {
54+
min-height: 24px;
55+
color: var(--dark-blue);
56+
}
57+
58+
fieldset,
59+
label,
60+
button,
61+
input,
62+
select {
63+
margin-bottom: 10px;
64+
}
65+
66+
.output {
67+
border: 2px solid var(--light-grey);
68+
padding: 10px;
69+
text-align: center;
70+
}
71+
72+
.hide {
73+
display: none;
74+
}
75+
76+
.output span {
77+
font-weight: bold;
78+
font-size: 1.2em;
79+
}
80+
81+
.surplus {
82+
color: var(--light-pink);
83+
}
84+
85+
.deficit {
86+
color: var(--light-green);
87+
}

steps/__89__step__/title.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
Step 89
2+
3+
If you click on your
4+
Calculate Remaining Calories button, you'll see that
5+
nothing happens. You still need to mount
6+
the event listener.
7+
Add an event listener to
8+
your calorieCounter element. The event type should
9+
be submit, and the callback function should
10+
be calculateCalories.
11+

0 commit comments

Comments
 (0)