A new dog

The story so far

An add page

We have two pages in the dog pack app:

  • Initialize the record set
  • Show the record set

Here's the page that shows the pack:

The pack

Let's add a third page to:

  • Add a new dog to the pack.

The page will have a form, using the same types of fields you've seen before:

Dog form

Let's see how it works.

The Add button

Here's the HTML for the add button:

<button onclick="DogPack.add()"
    type="button" class="btn btn-primary"
    title="Add new dog">Add</button>

Clicking the button will run the function DogPack.add().

Here's pseudocode for what will happen:

Validate the form's data
Make a new dog record
Add the dog record to the DB
Jump to the pack list page

Let's start with the first step, validating the data.

The form has three fields:

  • Name
  • Description
  • Weight

Name

Here's the HTML for the name field:

<div class="form-group">
    <label for="dogName">Name</label>
    <input type="text" class="form-control" id="dogName"
          aria-describedby="dogNameHelp" placeholder="Enter a name">
    <small id="dogNameHelp" class="form-text text-muted">E.g., Astro.</small>
</div>

Here's some JS code that will get the user's input for name, and validate it.

  1. var newDogName = $("#dogName").val().trim();
  2. if ( newDogName == "" ) {
  3.     alert("Sorry, you didn't give a dog name.");
  4.     return;
  5. }
Line 1 says, "Find an HTML element with an id of dogName, get its value, and then remove spaces (and other whitespace characters) from the beginning and the end. Put that in the variable newDogName."

Line 2 checks the variable newDogName. If it's an empty string, show an error, and exit the function.

Now to validate description.

Description

Here's the form field's HTML:

<div class="form-group">
    <label for="dogDescription">Description</label>
    <input type="text" class="form-control" id="dogDescription"
          aria-describedby="dogDescriptionHelp"
          placeholder="Enter a short description">
    <small id="dogDescriptionHelp" class="form-text text-muted">
        E.g., Rurhro, Relroy.</small>
</div>

Here's the validation JS:

  1. var newDogDescription = $("#dogDescription").val().trim();
  2. if ( newDogDescription == "" ) {
  3.     alert("Sorry, you didn't give a description.");
  4.     return;
  5. }
It's the same as before. Line 1 says, "Hey, browser! Find an element with an id of dogDescription, get its value, and trim it. Put the result in newDogDescription."

Line 2 tests to see if newDogDescription is an empty string. If so, show an error message, and exit the function.

Now we've validated two of the three fields:

  • Name VALIDATED
  • Description VALIDATED
  • Weight

Weight

Here's the HTML:

<div class="form-group">
    <label for="dogWeight">Weight (kg)</label>
    <input type="number" min="1" class="form-control" id="dogWeight"
          aria-describedby="dogNameHelp" placeholder="Enter a weight">
    <small id="dogWeightHelp" class="form-text text-muted">E.g., 13.</small>
</div>

This is almost the same as the other fields, except that the input field will only accept a number that is at least 1.

Well, kinda. If the user types anything at all in the field, the browser will make sure that it is a number that is at least 1. However, the user can leave the field empty. Type nothing in it. The browser is OK with that.

But we aren't. We want the user to type a weight. Here is the JS.

  1. var newDogWeight = $("#dogWeight").val();
  2. if ( newDogWeight == "" ) {
  3.     alert("Sorry, you didn't give a weight.");
  4.     return;
  5. }
Almost the same as the others, except for line 1. trim() is missing, because the browser won't let users type spaces anyway. We could put trim() in, but it would not do any good.

OK, all three fields are validated.

Here the pseudocode again:

Validate the form's data  DONE
Make a new dog record  NEXT
Add the dog record to the DB
Jump to the pack list page

Make a new dog record

Here's a dog record from the DB initialization page:

{
    id: 11,
    name: "Bufford",
    description: "She can sniff it out.",
    weight: 26
}

OK, on our add form, the user typed the dog's name, description, and weight. We put it in variables during validation:

var newDogName =
    $("#dogName").val().trim();
...
var newDogDescription =
    $("#dogDescription").val().trim();
...
var newDogWeight =
    $("#dogWeight").val();

We can make a new dog record, like this:

var newDog = {
    id: WHAT GOES HERE?,
    name: newDogName,
    description: newDogDescription,
    weight: newDogWeight
};

Except, we need an id for the dog. It has to be unique. How to get that number?

Here's how: find the highest id so far, and add one to it.

This will guarantee that the new dog's id is unique.

TaffyDB to the rescue!

//Find the highest id so far.
var highestId = DogPack.packDb().max("id");
//New dog's id is one more.
var newDogId = highestId + 1;

Taffy's max() function does the work for us. It checks every record, and returns the highest value of the field id.

Add one to that, and we have the new dog's id.

Here's the complete code to create a new dog record:

//Add a new record.
//Find the highest id so far.
var highestId = DogPack.packDb().max("id");
//New dog's id is one more.
var newDogId = highestId + 1;
//Create a new object.
var newDog = {
    id: newDogId,
    name: newDogName,
    description: newDogDescription,
    weight: newDogWeight
};

Add the new dog to the database

Here the pseudocode again:

Validate the form's data  DONE
Make a new dog record  DONE
Add the dog record to the DB  NEXT
Jump to the pack list page

Just one JS statement:

//Add the new item.
DogPack.packDb.insert(newDog);

That's it. The new dog is in localStorage.

Marcus
Marcus
Wait, I don't get it. That line doesn't say localStorage anywhere.
Georgina
Georgina
I know!

When the page loaded, we bound a Taffy database to localStorage. So, changes to the DB are written to storage automatically.

Right! This is from the page load event:

  1. $(document).ready(function () {
  2.     ....
  3.     //Create an empty Taffy DB.
  4.     DogPack.packDb = TAFFY();
  5.     //Link the DB to localStorage. Existing items will be loaded.
  6.     DogPack.packDb.store("dogPack");
Line 4 creates packDb in the DogPack namespace, as a Taffy database.

Line 6 binds packDb to localStorage("dogPack").

Redirect

Here the pseudocode again:

Validate the form's data  DONE
Make a new dog record  DONE
Add the dog record to the DB  DONE
Jump to the pack list page  NEXT

The last line is done like this:

//Go to list page.
window.location.href = "index.html";

Here's all of the code for the add button:

DogPack.add = function() {
    //Get input and validate.
    var newDogName = $("#dogName").val().trim();
    if ( newDogName == "" ) {
        alert("Sorry, you didn't give a dog name.");
        return;
    }
    var newDogDescription = $("#dogDescription").val().trim();
    if ( newDogDescription == "" ) {
        alert("Sorry, you didn't give a description.");
        return;
    }
    var newDogWeight = $("#dogWeight").val();
    if ( newDogWeight == "" ) {
        alert("Sorry, you didn't give a weight.");
        return;
    }
    //Data OK.
    //Add a new record.
    //Find the highest id so far.
    var highestId = DogPack.packDb().max("id");
    //New dog's id is one more.
    var newDogId = highestId + 1;
    //Create a new object.
    var newDog = {
        id: newDogId,
        name: newDogName,
        description: newDogDescription,
        weight: newDogWeight
    };
    //Add the new item.
    DogPack.packDb.insert(newDog);
    //Go to list page.
    window.location.href = "index.html";
};

The cancel button

Here's the add form again:

Dog form

The last thing is the cancel button. Here's the HTML:

<button onclick="DogPack.forghedaboudit()"
        type="button" class="btn btn-danger"
        title="Forghedaboudit">Cancel</button>

Notice the btn-danger class. That's what makes the button red.

Here's the JS:

  1. /**
  2. * Forghedaboudit.
  3. */
  4. DogPack.forghedaboudit = function(){
  5.     if ( confirm("Are you sure?") ) {
  6.         window.location.href = "index.html";
  7.     }
  8. };
The confirm() function shows:

Confirm

If the user clicks OK, confirm() returns true, otherwise it returns false.

If confirm() returns true, then:

window.location.href = "index.html";

That jumps to the dog list page, without creating a new dog.

Exercise

Exercise: Quotes
Make an app that shows quotes.

Put your name(s) in the footer.

There should be three pages. The first lists quotes, like this:

List

The add button shows the second page, with a form like this:

Add form

Both fields are required. The add button should validate, add the quote to the database, and jump to the list page.

The third page initializes the database. It should look like:

Initialize

Hint: at the time of writing, the Boostrap 4 docs for blockquote suggested this:

<footer class="blockquote-footer">

I had to use this:

<small class='blockquote-footer'>

Submit two URLs:

  • The URL of the index page.
  • The URL of the initialization page.

(If you were logged in as a student, you could submit an exercise solution, and get some feedback.)

Summary