The story so far
You have a BS template with some JS to load a navbar, and footer. You know how to make input fields, and buttons. You know how to tie JS code to events. You know how to validate. You know how to use variables to coordinate what happens across events.
Wow! You know a lot of stuff!
Time for a new app. This one is simple. We'll expand it in the next example.
A bit o' tech
We're going to use localStorage. It lets you store data on a user's computer, that a browser can access. For example:
localStorage.setItem("bestAnimal", "dog");
Later, you can get the value with:
bestAnimal = localStorage.getItem("bestAnimal");
You can also remove an item:
localStorage.removeItem("bestAnimal");
bestAnimal
is a key that identifies the data. Like a primary key in a database table. localStorage
keys are strings.
Each browser has its own localStorage
. So data you store in Firefox won't be available to Chrome. Data you store in Firefox on one device, like your laptop, won't be available in Firefox on another device, like your phone, or a friend's laptop. They'll have their own storage.
Browsers give each site its own localStorage
. So wickerhope.com
and shygerms.net
have different localStorage
in every browser. However, every page on wickerhope.com
, like wickerhope.com/day/tuesday.html
, and wickerhope.com/extend/explore/evaluate/emit.html
, share the same localStorage
. So if the first page puts something in localStorage
, the other one will be able to access that data, and vice versa.
Remember how we use variables to coordinate different code fragments? localStorage
extends that across pages, and time.
On to the new app.
Requirements
Goals
Let's make an app for a piggy bank. You add pennies to it, and it tells you how much money the pig has.
The total is persistent. So, if you close your browser, do other things, then open your browser up, the total will still be there. It will be there next week. Until you empty the pig.
Screen
There's just one screen. Here's a mock up:
Not much to it. The current total, and two buttons.
Events
- Add button: Add a penny to the total.
- Reset button: Set the total to zero.
Yes, good point.
- App start: show current total.
Pseudocode
There are three events that need code. Let's rough them out.
Event: on page ready
Read total from localStorage
Show the total
So we'll need a variable for the total. Every code fragment will use the variable.
Event: Add penny button clicked
Add 0.01 to total
Store new total in localStorage
Show the total
Event: Empty the pig
Set total to 0
Store new total in localStorage
Show the total
Onward!
HTML
Here's what it will look like:
Here's the HTML:
The place for output has an id of amount
.
<p>Amount: $<span id="amount"></span></p>
Each button has an onclick
call.
The shared variable
Let's set up the template, and add the key variable: the total. We'll call it pigFortune
, because that's a little funny. OK, only a tiny bit.
I've called the app PiggyBank
. Could be BaconBank
, Hogworth
, something else. As long as we're consistent, it doesn't matter.
The key variable is on line 5:
var pigFortune = 0;
All of the code inside…
(function($) {
...
}(jQuery));
… will have access to the variable.
Loading the total
When the app loads, it will grab the current value from localStorage
. Here's code:
$(document).ready(function () {
//Template stuff
...
//Load initial savings.
//pigFortune has already been initialized to zero.
if ( localStorage.getItem("pigFortune") ) {
pigFortune = parseFloat(localStorage.getItem("pigFortune"));
}
//Show current pigFortune.
$("#amount").html(pigFortune);
});
Check out the first part:
if ( localStorage.getItem("pigFortune") ) {
pigFortune = parseFloat(localStorage.getItem("pigFortune"));
}
This line…
if ( localStorage.getItem("pigFortune") ) {
… checks whether there is a value for the key pigFortune
in localStorage
. If there is, that value will be put into the variable pigFortune
:
pigFortune = parseFloat(localStorage.getItem("pigFortune"));
A problem with localStorage
is that it will only store strings, that is, text data. That's why parseFloat()
is there. It converts data from a string to a number.
There are two similar functions: parseFloat
, and parseInt
. The difference is whether the number can have a decimal part. In JS, a float is a number that can have a decimal part, like 3.22. or 133.34. Floats are called singles in some languages.
parseInt
always returns an integer, that is, a whole number. It strips off the decimal part, if there is one. So parseInt("3.77")
returns 3.
Back to:
if ( localStorage.getItem("pigFortune") ) {
pigFortune = parseFloat(localStorage.getItem("pigFortune"));
}
If there is nothing with the key pigFortune
in localStorage
, pigFortune
will be left at its current value. What is it? Remember this:
pigFortune
was initialized to zero already.
There's one more line in the page ready code:
This code…
$("#amount").html(pigFortune);
… says to "Find something on the page with an id of amount
, and set its HTML to the value of pigFortune
."
OK, so we've finished the code for the page load event.
Adding a penny
We saw the HTML for the button:
Here's the code for PiggyBank.addPenny()
:
/**
* Record new savings.
*/
PiggyBank.addPenny = function() {
pigFortune += 0.01;
localStorage.setItem("pigFortune", pigFortune.toString());
$("#amount").html(pigFortune);
};
It start with a comment, explaining what the function does.
The first executable line is:
pigFortune += 0.01;
+=
is a shortcut for "add to." So…
pigFortune += 0.01;
… is the same as…
pigFortune = pigFortune + 0.01;
Think of +=
as "increase by," if you like.
The next line…
localStorage.setItem("pigFortune", pigFortune.toString());
… records the new value of pigFortune
in localStorage
, under the key pigFortune
.
Remember that localStorage
can only store strings. pigFortune.toString()
does the conversion.
One line left:
As we've seen, that changes the HTML of the element with the id
of amount
.
Taking it all
Here's the screen again.
What about the Take it all button?
/**
* Take all the pig's money.
*/
PiggyBank.takeFortune = function() {
pigFortune = 0;
localStorage.removeItem("pigFortune");
$("#amount").html(pigFortune);
};
It starts with a comment, telling what the function does.
The code sets pigFortune
to zero. Remember, that variable is how all of the code in the this app coordinates its work. If the "Add a penny" code runs next, it will be working with the new value of pigFortune
, that is, zero.
This…
localStorage.removeItem("pigFortune");
… erases the item with the key pigFortune
from localStorage
. It doesn't set the item to zero. It removes the item completely.
Finally…
$("#amount").html(pigFortune);
… shows the new value of pigFortune
.
Dev tools
Dev tools can show localStorage
. Handy for debugging. Here's Chrome's tools:
Exercise
Link the image to https://en.wikipedia.org/wiki/Freddo. The image comes from there.
To position the image, try the Bootstrap classes float-left
, and pr-5
.
Clicking the buttons adds one to the Freddo count, subtracts one, or sets it to zero.
Note: number of Freddos cannot go below zero.
Make sure the number of Freddos is persistent. When the user reloads the page, or reboots the computer, it will show the last value for the Freddo count.
Submit the URL of your solution.
(If you were logged in as a student, you could submit an exercise solution, and get some feedback.)
CoolThing
Code that jumps back to the previous page, after a random delay.
Summary
localStorage
let you persist data.- Each
localStorage
item has key. The key is a string. localStorage
only stores strings. If you want to store a number, you need to convert the data with.toString()
. To get the number back, grab the string form fromlocalStorage
, and useparseFloat
, orparseInt
.