A Simple JavaScript Weight Converter With Storage Part 1

My weighing scales - the ones I use to weigh my hefty frame - tell me my weight in kilograms. I prefer to see my weight as stones and pounds, so each week, I DuckDuckGo a search, find a calculator site, visit it, deal with their massive page loads, and eventually get the conversion done. That is pretty slow and even if I bookmarked the page, I would still have to deal with all the ads etc.

No, I’d rather I had my own one, but even better, it could remember what my weight was the last time I used it. What would be my incredibly demanding requirements, though?

It would need:

  • To allow me type in my weight in kilograms
  • To convert that value into stones and pounds, displaying the result, and
  • Be able to store the conversion so that I can compare it next time.

For this project, we will mainly use:

  • Vanilla JS
  • INPUT
  • BUTTON
  • JS Callbacks
  • localStorage
  • Mini.css

Let’s begin with the mark-up.

HTML Page

By the end of today’s tutorial, the page will eventually look like this:

I know - it’s stunning, but put that aside, we’ve work to do.

Begin by creating a new HTML file and call it weight.html. Now add in the basic HTML for a page:

1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Kilos to Stones and Pounds</title>
</head>

<body>
</body>
</html>

I’ve given it a nice title, as you can see, but what about the main input and output elements? Inside the body tag, add this section of code in; we’ll explain it straight afterwards.

1
2
3
4
5
6
7
8
9
10
<h1>Convert Kilos to Stones and Pounds</h1>
<label for="kilos">Kilos</label>
<input id="kilos" type="number" value="90" step="0.1" min="30" max="120">
<button id="convert">Convert to Stones and Pounds</button>
<div name="results">
<p>
Stones: <output id="stones" for="kilos"></output>
Pounds: <output id="pounds" for="kilos"></output>
</p>
</div>

We’ve given it a suitable H1 tag: Convert Kilos to Stones and Pounds.

Next comes the input field. For this, we have used a LABEL and said that it is “for” the INPUT field which is below it. That’s a type of “number” which means we will get some nice arrow up/arrow down buttons, and can also use the arrow keys. I’ve pre-seeded it with a value of 90 (don’t ask if that is my weight - that’s not important!), specified a minimum of 30 and a maximum of 120. Why did I pick those values? I’m not sure, but for me, I can safely say it’s the lower and upper bounds of where I want to ever be. Lastly, I have told the browser that I’d like to allow the arrow functionality to increase or decrease in steps of 0.1, which is 100g - that should be OK.

After that comes our BUTTON with an ID of convert which is the thing we will press when we want the conversion to happen.

Lastly, wrapped in a DIV are where the results will ultimately be placed. I used an OUTPUT tag here, which, to be honest, I hadn’t seen before, but it’s perfect for this because it refers to the result of something. A nice touch is that you can specify what elements contributed to this result, which here, is where I use for="kilos" - the INPUT element. Both output tags have an ID names stones and pounds - we’ll need those soon enough.

Take a look at what the HTML looks like so far - visually, it’s pretty close, but of course, clicking d’at button doesn’t do anything. Let’s handle that now once we’ve got the maths out of the way.

A Tiny Bit of Maths

Here’s a good point to explain what you need to do when converting between kilos and, stones and pounds.

Firstly, to translate between the values, we need to first convert the kilos to pounds. How do we do that?

I know that there are about 2.2 pounds in every kilo, so if we multiply the two together, that will tell us how many pounds we have for a given number of kilos.

Once we have that, we can work out how many stones a person is by dividing that total number of pounds by 14, because there are 14 pounds in a stone.

Let’s look at an example.

If I were 10 kilos, that would be 10 * 2.2 pounds, which gives us 22 pounds. Leaving aside how dangerously ill I would be, we can use some back-of-an-envelope maths to know that that would be 1 stone (22 - 14 = 1 stone) and some left over. That remaining portion would be 8 pounds, a little over half a stone.

We can use some mathematical functions to do the hard work for us here but let’s illustrate it with pseudo-code, first.

  • totalPounds is equal to kilos multiplied by 2.2 (approximately)
  • stones are the whole number of totalPounds divided by 14
  • pounds are the remainder of totalPounds divided by 14

Time for some JavaScript.

Adding in the Calculations

For simplicity, we’ll add in the JavaScript just under the DIV in a SCRIPT tag.

1
2
3
4
<script>
const poundsInAStone = 14;
const poundsInAKilo = 2.204623;
</script>

I’m going to start with some constants rather than plug magic numbers throughout the code. Here we have the number of pounds in a stone (14) and the more accurate number of pounds in a kilo.

Under that, add in some constants which point to elements in our DOM. I don’t want to keep looking these things up but with such a small page, it wouldn’t be a problem if we did.

1
2
3
const kiloElement = document.getElementById("kilos");
const poundElement = document.getElementById("pounds");
const stoneElement = document.getElementById("stones");

Now we need to do the calculation functions. For these, we need three: kilos to pounds, pounds to stones and pounds left over once we’ve calculated the stones. Add these in next, right underneath the other JavaScript.

1
2
3
4
5
const calculateTotalPounds = (kilos, poundsInAKilo) => kilos * poundsInAKilo;

const convertKilosToStones = (pounds, poundsInAStone) => Math.floor(pounds / poundsInAStone);

const convertKilosToPounds = (pounds, poundsInAStone) => pounds % poundsInAStone;

You can see that I pass in some of those magic numbers as constants, which we defined earlier: poundsInAKilo and poundsInAStone. It’s worth also explaining a little of how I turned the pseudo-code into actual JavaScript functions, though.

Math.floor() is a way to round a result downwards, so, for instance Math.round(14.2) would return 14. Here, in convertKilosToStones() I’m using it to divide the total number of pounds (pounds) by the number of pounds in a stone (14), but telling JavaScript to ignore the remainder, by rounding down.

convertKilosToPounds() is a little different in that we are using the modulus operator (%) to do the same kind of calculation, but instead keep the remainder. It literally means: divide A by B and return the remainder.

That handles the maths, but let’s add in some code to grab the values and check that they are valid numbers etc.

1
2
3
4
5
6
7
8
9
10
const convertKilosToStonesAndPounds = () => {
let kilosValue = parseFloat(kiloElement.value);
if (isNaN(kilosValue)) {
alert("Please enter a valid number for kilos");
return;
}
const totalPounds = calculateTotalPounds(kilosValue, poundsInAKilo);
stoneElement.innerText = convertKilosToStones(totalPounds, poundsInAStone);
poundElement.innerText = convertKilosToPounds(totalPounds, poundsInAStone).toFixed(2);
}

Line by line, we firstly convert the text value of kilos - it is text, despite flagging the type as number. The result of that is converted into a floating point value which basically means a decimal number.

Next, I check to see if that conversion returned Not a Number (NAN). If it did, we can be pretty sure there are some funky characters that are non-numeric, in there. We want to catch that and warn the user, which we do in the IF block.

If we get past that, we probably fine. The next three statements call our calculation functions, and plug the results into our OUTPUT tags that we defined right at the beginning. Note the last call to toFixed(2). That makes sure that our result is to 2 decimal places, which is easier to read. If you are unsure what I mean, it ensures that instead of seeing an answer like 1.2736328262 we instead get 1.27. Much nicer!

Almost done, let’s add in some call back functions to our button and calculate the stones and pounds immediately with our pre-seeded number 90.

1
2
document.getElementById("convert").addEventListener("click", convertKilosToStonesAndPounds);
convertKilosToStonesAndPounds();

That’s all for now. Save everything, make sure it works and check out the next installment where we add in storage plus a small amount of CSS to make it look prettier.


Hi! Did you find this useful or interesting? I have an email list coming soon, but in the meantime, if you ready anything you fancy chatting about, I would love to hear from you. You can contact me here or at stephen ‘at’ logicalmoon.com