← All subjects
NewFree preview available
Coding · Any age, any level

Build Real Projects: From Calculators to Algorithms

Learn by building eleven real projects, from a tip calculator and a web page to an expense tracker, a data explorer, a maze solver and a Sudoku solver. Every project has a guided build, then an open project or an exam that is marked only when you submit.

★ New0 reviews0 learners
Created by GradesPal
Modules
4
Lessons
11
Study time
14h 0m

What you’ll learn

Plan a program by writing down its state and the rule for every event
Build calculators, forms and web pages that handle real input
Keep data in arrays of objects, draw the page from it, and save it in the browser
Search, sort and page data correctly, and write reusable data functions
Solve shortest-path problems with breadth-first search
Solve puzzles with recursion and backtracking
Work under exam conditions and design your own projects from a blank page

Workshop content

4 modules · 11 lessons · 14h 0m total

Level 1 · Beginner2 lessons
Project: a tip calculator50 min · Preview

Project: a tip calculator

Projects19 min readBuild it live: Code Studio

In this lesson

  1. What you will build
  2. How to work: build in small steps
  3. Step 1: the form
  4. Step 2: places for the answers
  5. Step 3: make it look good
  6. Step 4: work out the tip

Practise this in the Code Studio

open the guided build, then build your own calculator. You type real code in your browser, see the result at once, and the tasks tick themselves when your code is right. Nothing to install.

Your first project is small enough to finish in one sitting and real enough to use at a restaurant tonight. You enter the bill, choose a tip and the number of people, and the page works out the tip, the total and what each person pays.

It uses the three languages together: HTML for the form, CSS to make it look good, and JavaScript to do the thinking. If you have worked through the HTML, CSS and JavaScript courses, you already know every piece. This lesson shows you how to put them together.

What you will build

  • A form with a bill, a tip drop-down and a number of people.
  • A Calculate button that shows the tip, the total and each person's share.
  • Friendly messages when the input does not make sense, instead of broken answers.

How to work: build in small steps

Beginners often try to write everything at once and then cannot find what broke. Professionals do the opposite: build one small thing, check that it works, then add the next. The Code Studio follows that rhythm: each step is a task that ticks when it works.

1The form

Every input gets an id, so JavaScript can find it, and every input gets a <label>, so people (and screen readers) know what it is for. Clicking a label also puts the cursor in its box.

index.htmlHTML
<label for="bill">Bill (R)</label>
<input id="bill" type="number" min="0" step="0.01" placeholder="250">

<label for="tip">Tip</label>
<select id="tip">
  <option value="10">10%</option>
  <option value="15" selected>15%</option>
  <option value="20">20%</option>
</select>

type="number" gives phones a number keypad. step="0.01" allows cents. The value of each option is the number your code will use; the text between the tags is what people read.

2Places for the answers

Plan where every answer will appear before you write any JavaScript. An empty element with an id is a place waiting for text.

HTML
<p id="error" role="alert"></p>

<dl id="result" hidden>
  <dt>Tip</dt><dd id="tipAmount"></dd>
  <dt>Total</dt><dd id="total"></dd>
  <dt>Each person pays</dt><dd id="each"></dd>
</dl>

A <dl> is a description list: terms (dt) and their descriptions (dd). The hidden attribute keeps the results out of sight until there is something to show.

3Make it look good

A calculator that looks cared for feels trustworthy. A card (a white box on a soft background) is the simplest good-looking layout there is.

style.cssCSS
body {
  background: #f3f6f9;
  font-family: Verdana, sans-serif;
  padding: 24px;
}

.app {
  background: #fff;
  border-radius: 14px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08);
  margin: 0 auto;
  max-width: 420px;
  padding: 24px;
}

input, select {
  box-sizing: border-box;
  width: 100%;
}

margin: 0 auto centres a box that has a width. max-width lets it shrink on a phone. box-sizing: border-box makes width: 100% include the padding, so the boxes do not poke out of the card.

4Work out the tip

Now the JavaScript. Find the elements once at the top, then listen for the button.

script.jsJavaScript
const bill = document.querySelector("#bill");
const tip = document.querySelector("#tip");
const people = document.querySelector("#people");

document.querySelector("#calc").addEventListener("click", () => {
  const billAmount = Number(bill.value);
  const tipAmount = billAmount * Number(tip.value) / 100;
  document.querySelector("#tipAmount").textContent = "R " + tipAmount.toFixed(2);
});

Remember

a box's .value is always text, even in a number box. Number("200") turns it into the number 200. Without it, "200" + 30 would give "20030".

toFixed(2) rounds to two decimal places and returns text such as "30.00", which is exactly what money should look like.

5The total and each person's share

JavaScript
const total = billAmount + tipAmount;
document.querySelector("#total").textContent = "R " + total.toFixed(2);
document.querySelector("#each").textContent = "R " + (total / count).toFixed(2);

6Protect it against bad input

People will click Calculate with an empty box, or type a negative bill. Real programs expect that. Check first, then show a message and stop with return.

JavaScript
error.textContent = "";
if (!(billAmount > 0)) {
  error.textContent = "Enter the bill amount first.";
  result.hidden = true;
  return;
}

Tip

write the test as !(billAmount > 0) instead of billAmount <= 0. An empty box gives Number(""), which is 0, but some bad input gives NaN (not a number). NaN > 0 is false, so !(NaN > 0) is true: one test catches every bad case.

7Polish

Zero people would divide by zero and show Infinity. Force the count to be at least one:

JavaScript
const count = Math.max(1, Math.floor(Number(people.value)) || 1);

Read it from the inside out. Number(people.value) is the number typed. Math.floor removes any decimals. || 1 replaces 0 or NaN (both false-like) with 1. Math.max(1, …) makes sure the result is never below 1.

The finished project

index.htmlHTML
<main class="app">
  <h1>Tip calculator</h1>

  <label for="bill">Bill (R)</label>
  <input id="bill" type="number" min="0" step="0.01" placeholder="250">

  <label for="tip">Tip</label>
  <select id="tip">
    <option value="10">10%</option>
    <option value="15" selected>15%</option>
    <option value="20">20%</option>
  </select>

  <label for="people">People</label>
  <input id="people" type="number" min="1" value="1">

  <button id="calc" type="button">Calculate</button>
  <p id="error" role="alert"></p>

  <dl id="result" hidden>
    <dt>Tip</dt><dd id="tipAmount"></dd>
    <dt>Total</dt><dd id="total"></dd>
    <dt>Each person pays</dt><dd id="each"></dd>
  </dl>
</main>
style.cssCSS
body {
  background: #f3f6f9;
  color: #1a2940;
  font-family: Verdana, sans-serif;
  margin: 0;
  padding: 24px;
}

.app {
  background: #fff;
  border-radius: 14px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08);
  margin: 0 auto;
  max-width: 420px;
  padding: 24px;
}

label {
  display: block;
  font-weight: 700;
  margin: 14px 0 4px;
}

input,
select {
  border: 1px solid #c9d4df;
  border-radius: 8px;
  box-sizing: border-box;
  font: inherit;
  padding: 10px;
  width: 100%;
}

#calc {
  background: #1f74bf;
  border: 0;
  border-radius: 8px;
  color: #fff;
  cursor: pointer;
  font: inherit;
  font-weight: 700;
  margin-top: 18px;
  padding: 12px;
  width: 100%;
}

#calc:hover {
  background: #155a98;
}

#error {
  color: #c0392b;
  min-height: 1.2em;
}

dt {
  color: #5d7088;
  margin-top: 10px;
}

dd {
  font-size: 1.4rem;
  font-weight: 700;
  margin: 0;
}
script.jsJavaScript
const bill = document.querySelector("#bill");
const tip = document.querySelector("#tip");
const people = document.querySelector("#people");
const error = document.querySelector("#error");
const result = document.querySelector("#result");

function money(amount) {
  return "R " + amount.toFixed(2);
}

document.querySelector("#calc").addEventListener("click", () => {
  const billAmount = Number(bill.value);
  const count = Math.max(1, Math.floor(Number(people.value)) || 1);

  error.textContent = "";
  if (!(billAmount > 0)) {
    error.textContent = "Enter the bill amount first.";
    result.hidden = true;
    return;
  }

  const tipAmount = billAmount * Number(tip.value) / 100;
  const total = billAmount + tipAmount;

  document.querySelector("#tipAmount").textContent = money(tipAmount);
  document.querySelector("#total").textContent = money(total);
  document.querySelector("#each").textContent = money(total / count);
  result.hidden = false;
});

Make it yours

Once all seven tasks tick, change it until it feels like yours:

  1. Your currency and your colours. Change R to your currency and replace the blues with a palette you like.
  2. A custom tip. Add a 4th option, "Other", that shows a box for a percentage.
  3. Round up. Add a checkbox "Round each share up to the nearest rand" and use Math.ceil.
  4. Calculate as you type. Listen to the input event on the boxes as well, so there is no need for the button.

Your turn: build a calculator of your own

Marked like an exam

this project shows no hints and no answers while you work, and nothing ticks until you submit. Then you get your mark, the feedback and the model answers, and you can try again.

Open the second exercise. There are no steps this time, only a list of what your calculator must do. You choose what it calculates.

Pick one:

  • A BMI calculator (weight ÷ height²).
  • A unit converter (kilometres to miles, °C to °F).
  • A discount calculator (price and percentage off).
  • An age in days calculator.
  • A grade average calculator.
  • Anything you wish existed.

It must have labelled inputs, react to the button, give different answers for different inputs, survive empty boxes, use a function of your own and look good. When the tasks tick, press Download page to keep a copy.

Check yourself

Why do we write Number(bill.value)?

The value of an input is always text. Number() converts the text to a number so we can do arithmetic. Without it, + would join pieces of text together.

What does toFixed(2) return, and why is it useful for money?

It rounds a number to two decimal places and returns it as text, for example "15.00". Money is shown in cents, and 15 or 14.9985 would look wrong.

Why does the code use return after showing an error message?

return ends the function. Without it the code would carry on and show a wrong answer under the error message.

Why give every input an id and a label?

The id lets JavaScript find the element, and the for attribute of the label connects the text to it. People can click the label to focus the box, and screen readers read the label aloud.

Build the tip calculator → Your turn: your own calculator →

Project: a one-page website55 min
Level 2 · Intermediate3 lessons
Project: a working calculator60 min
Project: a sign-up form that checks itself60 min
Project: a number guessing game60 min
Level 3 · Advanced3 lessons
Project: a memory card game75 min
Project: an expense tracker that remembers90 min
Project: a quiz app driven by data90 min
Level 4 · Expert: algorithms3 lessons
Project: a data explorer (search, sort, pages)90 min
Project: a maze solver (breadth-first search)105 min
Project: a Sudoku solver (backtracking)105 min

Requirements

  • Basic HTML, CSS and JavaScript: the GradesPal HTML, CSS and JavaScript courses cover everything you need
  • Any device with a web browser: a computer is best
  • No age or grade requirement: open to everyone

Frequently asked questions

Do I need to install anything?

No. You write and run all the code in the GradesPal Code Studio, in your browser. You can download each finished page as a file to keep.

What should I know before I start?

The basics of HTML, CSS and JavaScript: elements, simple styling, variables, if statements, functions and click events. If you have done the GradesPal HTML, CSS and JavaScript courses, you are ready.

Is the Expert level really advanced?

Yes. It covers the problems taught in first-year computer science: searching and sorting data, shortest paths with breadth-first search, and recursion and backtracking. You build each one into a working app, then write the functions yourself in an exam.

How are the projects marked?

The guided builds tick each step as soon as your code works, and you can ask for a hint or the answer. The open projects and the exams are different: no hints, no answers and nothing ticks until you submit. Then you get your mark, the feedback and the model answers. You can try again as often as you like, and your best mark is kept.

Can I buy only one level?

Yes. The course has three levels: Beginner, Intermediate and Advanced. You can buy the whole course or one level at a time.

Who is this course for?

Anyone. It suits school learners, university students and adults changing careers or learning for fun. There is no grade or age requirement.

No reviews yet