The story so far
Persisting record sets
There's a problem with the course data app in the previous lesson. It doesn't remember anything. We created a record set when the page loads:
(function($) {
//Initialize course catalog.
var catalog = [
{
id: 42,
title: "Web apps for happy dogs",
maxEnrollment: 40,
location: "Monty Hall 301"
},
...
];
It was lost when the page ended.
We want something like this:
(function($) {
//Initialize course catalog.
var catalog = LOAD RECORD SET FROM LOCALSTORAGE
We're going to use a JS library called TaffyDB to do exactly that. The <script>
tag to load Taffy is not part of our standard template. You need to add this line:
<script src="https://cdnjs.cloudflare.com/ajax/libs/taffydb/2.7.3/taffy-min.js"></script>
Taffy does many things, but let's start with the basics:
- Putting a record set into
localStorage
- Loading a record set from
localStorage
Let's write an app that knows about a dog pack. It will start with two pages:
- A page that creates a record set, and puts it in
localStorage
- A page that loads the record set from
localStorage
, and shows it
Creating a pack
Check out the page that creates the record set. It looks like this:
Click the button, and it will create a record set, and use Taffy to put it into localStorage
.
Here's some psuedocode, for what we want to do when the button is clicked:
Create the record set in a JS array
Make a TaffyDB
Link the TaffyDB to localStorage
Make sure the TaffyDB is empty
Insert the record set into the TaffyDB
The first line, creating the record set, you've seen before.
var dogPack = [
{
id: 11,
name: "Bufford",
description: "She can sniff it out.",
weight: 26
},
...
];
We can add as many dogs as we like.
That's the first task done:
Create the record set in a JS array DONE THIS
Make a TaffyDB NOW DO THIS
Link the TaffyDB to localStorage
Make sure the TaffyDB is empty
Insert the record set into the TaffyDB
Here's how you make a TaffyDB:
//Create an empty Taffy DB.
DogPack.packDb = TAFFY();
Notice that I put packDb
into the DogPack
namespace. I could have done this:
//Create an empty Taffy DB.
var packDb = TAFFY();
Here, packDb
is just a variable.
Putting packDb
in the namespace is optional in this program, but will make some of our future work easier.
What's the next step?
Create the record set in a JS array DONE THIS
Make a TaffyDB DONE THIS
Link the TaffyDB to localStorage NOW DO THIS
Make sure the TaffyDB is empty
Insert the record set into the TaffyDB
These lines will make a TaffyDB linked to localStorage
:
//Link the DB to localStorage. Existing items will be loaded.
DogPack.packDb.store("dogPack");
The name of the store()
function is a bit misleading. It seems like it would, well, store something. But it doesn't.
What the store()
function does is bind DogPack.packDb
to the localStorage
item with the key dogPack
(remember that every item in localStorage
has a key).
This binding gives us JS magic. Any changes we make to DogPack.packDb
automatically change localStorage
. So, if we add a record to DogPack.packDb
, TaffyDB automatically changes localStorage
. If we delete a record in DogPack.packDb
, TaffyDB automatically changes localStorage
.
Back to the pseudocode:
Create the record set in a JS array DONE THIS
Make a TaffyDB DONE THIS
Link the TaffyDB to localStorage DONE THIS
Make sure the TaffyDB is empty NOW DO THIS
Insert the record set into the TaffyDB
We don't know what's in localStorage
already. Let's erase what's there, to be safe.
//Remove all items.
DogPack.packDb().remove();
Because DogPack.packDb
is bound to localStorage
, erasing everything from DogPack.packDb
also erases everything from localStorage
with the key dogPack
.
The last thing:
Create the record set in a JS array DONE THIS
Make a TaffyDB DONE THIS
Link the TaffyDB to localStorage DONE THIS
Make sure the TaffyDB is empty DONE THIS
Insert the record set into the TaffyDB NOW DO THIS
Remember that we made the record set earlier:
var dogPack = [
{
id: 11,
name: "Bufford",
description: "She can sniff it out.",
weight: 26
},
...
];
So…
//Insert new records into the DB.
DogPack.packDb.insert(dogPack);
Here's the entire code for Initialize button:
<button id="initialize" class="btn btn-primary" onclick="DogPack.initPack()">Initialize</button>
...
DogPack.initPack = function() {
//Set up initial data set.
var dogPack = [
{
id: 11,
name: "Bufford",
description: "She can sniff it out.",
weight: 26
},
...
];
//Create an empty Taffy DB.
DogPack.packDb = TAFFY();
//Link the DB to localStorage. Existing items will be loaded.
DogPack.packDb.store("dogPack");
//Remove all items.
DogPack.packDb().remove();
//Insert new records into the DB.
DogPack.packDb.insert(dogPack);
alert("Done");
};
There's an alert()
at the end, so you know something happened.
Sometimes there's () (parentheses) after DogPack.packDb, as in the remove()
call. Sometimes, there's not, as in the store()
call. Rather than trying to figure out why, just copy the code you need from this page, or one of the later ones.
Showing the record set
Try the page that shows the pack. Assuming you have initialized the record set, you'll see:
Here's the code:
<div id="packContainer" class="hide-on-load"></div>
...
$(document).ready(function () {
//Load the navbar from the library.
$("#navbar").load("library/includes/navbar.html");
//Load the footer from the library.
$("#footer").load("library/includes/footer.html");
//Create an empty Taffy DB.
DogPack.packDb = TAFFY();
//Link the DB to localStorage. Existing items will be loaded.
DogPack.packDb.store("dogPack");
//Start building the output table.
var packHtml =
"<table class='table'>" +
" <thead>" +
" <th>Name</th>" +
" <th>Description</th>" +
" <th>Weight (kg)</th>" +
" </thead>" +
" <tbody>";
//Sort by name, then generate HTML for each record.
DogPack.packDb().order("name").each(function (dog) {
var dogRow =
"<tr>" +
" <td>" + dog.name + "</td>" +
" <td>" + dog.description + "</td>" +
" <td>" + dog.weight + "</td>" +
"</tr>";
packHtml += dogRow;
});
//Finish the pack HTML.
packHtml += "</tbody></table>";
//Show it.
$("#packContainer")
.html(packHtml)
.show('slow');
});
The first line…
<div id="packContainer" class="hide-on-load"></div>
… creates a place to show the table.
These lines create a TaffyDB and bind it to localStorage
:
//Create an empty Taffy DB.
DogPack.packDb = TAFFY();
//Link the DB to localStorage. Existing items will be loaded.
DogPack.packDb.store("dogPack");
It's the same code that was on the initialization page.
Earlier, we made a for forEach()
loop to show a record set. The loop created some HTML. This is the code from before:
catalog.forEach(function(course){
var courseHtml =
"<ul>" +
" <li>Title: " + course.title + "</li>" +
" <li>Maximum enrollment: " + course.maxEnrollment + "</li>" +
" <li>Location: " + course.location + "</li>" +
"</ul>";
catalogHtml += courseHtml;
});
We're going to do the same thing, but change the loop syntax for TaffyDB. Here's how we'll show the pack:
DogPack.packDb().order("name").each(function (dog) {
var dogRow =
"<tr>" +
" <td>" + dog.name + "</td>" +
" <td>" + dog.description + "</td>" +
" <td>" + dog.weight + "</td>" +
"</tr>";
packHtml += dogRow;
});
DogPack.packDb().order("name")
says to sort the record set by the property name
. Then, for each record…, well, the same thing that forEach
does, except that forEach
is called each
.
That's it! Inject the final HTML into the output container and show it:
$("#packContainer")
.html(packHtml)
.show('slow');
Directories
This app has two pages:
- Create and save a record set
- Show a record set
The first page alters the data. The second does not.
If this were a business app, the first page would be available only to people inside the business, admins of some type. You wouldn't want customers to use the page.
The second page would be available to everyone, customers included.
- Create and save a record set ADMINS ONLY
- Show a record set PUBLIC
You'll learn how to add a login system later.
There is something you can do now, though. Usually, protected pages are kept in a different directory from public pages. Here's how the files might look:
Files we want only admins to use are in the admin
directory. This is a good habit to get into.
Exercise
It has two pages.
The first pages initializes the fish data. It looks like this:
Clicking the button initializes a TaffyDB database bound to localStorage
.
Put the page in an admin directory.
The second page lists the fish, sorted by name. For example:
You can change the fish data, if you want. Use whatever fields you like, as long as at least two fields are shown.
Upload the URL of your solution.
(If you were logged in as a student, you could submit an exercise solution, and get some feedback.)