CSE 154

Lecture 15: RegEx, Cookies, Storage

Today's Agenda

Reminders/Admin

RegEx

Cookies

LocalStorage

Reminders/Admin

CP3 due tomorrow night (or can be turned in late)

Quiz 3 coming Wendesday this week (covers async/await through today's topics)

A guide on how to install and run Node, the tool we use to write our own APIs and backends, is on the Resources page on the site.

Try to have Node ready by Wednesday's lecture

HTML5 Input Validation

We've already seen some ways to use HTML5 tags to require certain types of input by adding attributes to your <input> tags to help with validation

<input type="number">

HTML

We can limit the up and down arrows with min (and max if we choose)

<input type="number" min=0>

HTML

To insist that there is a value in the input field we can add required

<input type="number" required>

HTML

To prevent a user from being able to type in erroneous values, we can add a regular expression to the pattern attribute

<input type="number" pattern="\d+">

HTML

wpl.html Form (with Validation Attributes)

<form id="input-form">
  <div>
    <label for="name-input">Name: </label>
    <input id="name-input" name="student-name" type="text" pattern="[A-Z][a-z]+" required/>
  </div>
  <div>
    <label for="email-input">E-mail (@uw.edu): </label>
    <input id="email-input" name="email" type="email" required/>
  </div>
  <div>
    <label for="sid-input">Student Number: </label>
    <input id="sid-input" name="sid" type="number" min=1000000 max=1999999 />
  </div>
  <div id="minute-options">
    <label>2-Minute Question <input type="radio" name="minutes" value=2 /></label>
    <label>10-Minute Question <input type="radio" name="minutes" value=10 /></label>
  </div>
  <textarea name="question" minlength=20 rows=5 placeholder="Enter your question..."></textarea>
  <button id="submit-btn" type="submit">Enter Queue!</button>
</form>

HTML

Client Validation with JS

/**
 * Just before send form data to the WPL web service.
 */
function checkInputs() {
  let email = qs("input[name='email']").value;
  let question = qs("textarea").value;
  if (!email.includes("uw.edu")) {
    handleError("Please provide a UW email");
  } else if (!question.includes(" ")) // not a real question...
    // Build the 5 parameters for our POST request
    handleError("Please provide a descriptive question");
  } else {
    // could add other checks before this
    submitWPLForm();
  }
}

wpl.js

While this is a bit more work, we don't always need to send all form elements in an API request, and it also gives us more control over validation checks in JS (for properties you can't check with HTML5 attributes) before the fetch.

Limitations of HTML5 Attributes

There are some limitations of input validation given what we've learned so far.

  • How do you test for integers vs. real numbers vs. strings?
  • How do you test for a valid UW email?
  • How do you test that a person's name has a middle initial?
  • (How do you test whether a given string matches a particular complex format?)

Regular Expressions!

/^[a-zA-Z_\-]+@(([a-zA-Z_\-])+\.)+[a-zA-Z]{2,4}$/

Regular expression ("regex"): a description of a pattern of text

  • Can test whether a string matches the expression's pattern
  • Can use a regex to search/replace characters in a string

Regular expressions are extremely power but tough to read (the above regular expression matches email addresses)

Regular expressions occur in many places:

  • Java: Scanner, String's split method (CSE 143 random grammar generator)
  • Supported by HTML5, JS, Java, Python, PHP, and other languages
  • Many text editors (TextPad, Sublime, Vim, etc.) allow regexes in search/replace
  • The site Rubular is useful for testing a regex

Basic Regular Expressions

/abc/

In JS, regexes are strings that begin and end with /

The simplest regexes simply match a particular substring

The above regular expression matches any string containing "abc"

  • Match: "abc", "abcdef", "defabc", ".=.abc.=.", ...
  • Don't Match: "fedcba", "ab c", "PHP", ...

Useful Regex Quick Reference

regex quick reference

Wildcards: .

A . matches any character except a \n line break

  • /.ow.l./ matches "Mowgli", "Powell", etc.

A trailing i at the end of a regex (after the closing /) signifies a case-insensitive match

  • /cal/i matches "Pascal", "California", "GCal", etc.

Quantifiers: *, +, ?, {}

* means 0 or more occurrences

  • /abc*/ matches "ab", "abc", "abcc", "abccc", ...
  • /a(bc)*/ matches "a", "abc", "abcbc", "abcbcbc", ...
  • /a.*a/ matches "aa", "aba", "a8qa", "a!?xyz__9a", ...

+ means 1 or more occurrences

  • /Hi!+ there/ matches "Hi! there", "Hi!!! there!", ...
  • /a(bc)+/ matches "abc", "abcbc", "abcbcbc", ...

? means 0 or 1 occurrences

  • /a(bc)?/ matches only "a" or "abc"

{x,y} matches between x and y occurrences

  • /a{2,3}/ matches "aa" or "aaa"

Sets: []

Sets match on any single character used in that set

  • /[abc]/ matches "a", "b", or "c"
  • /[cbl]arb/ matches "carb", "barb", or "larb"

Use the ^ to match what isn't in the set

  • /[^a]/ matches anything that isn't the letter "a" (be careful with this one!)

Most special characters are treated normally inside of sets.

  • /[a.*]/ matches "a", ".", or "*"

Character ranges: [start-end]

Inside a character set, specify a range of characters with -

  • /[a-z]/ matches any lowercase letter
  • /[a-zA-Z0-9]/ matches any lowercase or uppercase letter or digit

Inside a character set, - must be escaped to be matched

  • /[+\-]?[0-9]+/ matches an optional + or -, followed by at least one digit

Practice: Write a regex for Student ID numbers that are exactly 7 digits and start with 1 (try it!)

Regular Expressions in HTML Forms

<form id="input-form">
  ... rest of form
  <input id="name-input" name="student-name" type="text" pattern="[A-Z][a-z]+ [A-Z][a-z]+"
     title="Required name* format: 'First Last'" />
  ... rest of form
</form>

HTML

Name:

HTML5 adds a new pattern attribute to input elements

When an input is in a form along with a button, clicking the button automatically verifies the input and does a POST request (can use title parameter for more useful feedback, or the JS Constraint Validation API).

* Note: Not every name follows this pattern.

Regular Expressions in JavaScript!

Regex can be a very handy tool with JS as well, from validation to fun find/replace features. There are two common ways regex can be used:

  • With the RegExp constructor (either with a literal or string, use when you don't always know what the pattern is, such as user input)
  • With a literal (when you know exactly what the regex pattern is, evaluated exactly once)
  • let pattern1 = new RegExp(/cse154/, "i");
    let pattern2 = new RegExp("cse154", "i");
    let pattern3 = /cse154/;

    JS

    Note that we don't use "/" when using strings for patterns in the second RegExp constructor. This can be useful when we want to search for a particular pattern given as text input (e.g. a word replacer tool)!

Some Regex Functions in JS

Regex Objects have a few useful functions that take strings as arguments

regex.test(string) returns a boolean if a string matches the regex

let namePattern = /[A-Z][a-z]+ [A-Z][a-z]+/;
namePattern.test("Robert H Thompson"); // false

let studentIdPattern = new RegExp("1\d{6}");
studentIdPattern.test("-123");          // false

JS

Some String Functions in JS

Some JavaScript string methods can take Regular Expressions, like match, search, and replace

string.match(regex) returns an array of information about a match, including the index of the first match

"Hello world".match(/wo.l/); // [0: "worl", index: 6, input: "Hello world"]

JS

origStr.replace(regex, replStr) returns a new string replacing a pattern match in origStr with the string replStr

let newStr = "My cats are good cats".replace(/cat/, "kitten");
// newStr === "My kittens are good cats"

JS

Question: Where might you need to be careful with a RegEx replace?

let newStr = "There is a category of cats that catch cattle".replace(/cat/, "kitten");

newStr === "There is a kittenegory of cats that catch cattle"

And what if we replaced all instances?

let newStr = "There is a category of cats that catch cattle".replace(/cat/g, "kitten");

newStr === There is a kittenegory of kittens that kittench kittentle"

Summary

Regular Expressions are a way to test or modify strings of text against a pattern.

HTTP and State

HTTP is a stateless protocol; it simply allows a browser to request a single resource from a web server.

Once the resource has been sent to the client, the server does not keep track of any information about what was sent (other than maybe in a log file of the transaction).

But then how can websites like Amazon.com, Google, etc. remember whether you're logged in and your shopping preferences?

How does a client uniquely identify itself to a server, and how does the server provide specific content to each client?

Cookies

A small (max 4kb) amount of information stored within the computer browser

Introduced in 1994 for the Netscape browser to improve shopping experience

Have many uses:

  • Authentication, remembering login information
  • User tracking
  • Maintaining user preferences, shopping carts, etc.

Demo example of language preference cookie (try changing the language and finding the google translate cookie in your Chrome Applications tab - what happens when you refresh the page?).


This site uses cookies in order to provide the best possible experience.
Do accept our terms?
Yes No

Cookies: Shared Between Client and Server

Cookies are associated with certain websites. They consist of a key and a value. They also have an expiration date, and will go away when it is reached. If an cookie does not have an expiration date, it is usually a "session cookie", cleared when the browser is closed. (the KingCounty's language cookie is a session cookie).

Cookies let us store information on a user's computer, for things like keeping them logged in even if they close the page. These are sent by the same client to the server in future requests (until they expire).

As a web developer, this is a great feature to have to improve user experience (but you should be clear about your Privacy Policy).

More Cookie Details

  • Cookies are only data, not program code.
  • Cookies can be used to track your viewing habits on a particular site.
    • Do you think this is a good thing? Or a bad thing?
  • New privacy laws in Europe (GDPR) and California (CCPA) are making website owners rethink using cookies.

A great 10-minute video here with a simple overview of how different types of cookies work

Format of Cookies

Cookies are essentially just key -> value pairs with some extra information.

  • path: which page does this apply to?
  • domain: the domain (usually the current one you're on)
  • max-age: how long (in seconds) is this cookie good for
  • expires: what's the expiration date for this cookie?
  • secure: HTTPS-only?
  • samesite: other domains are not allowed to eat this cookie.

Viewing Cookies

You can view your cookies for different sites on the Chrome Tools Application Tab

Try it out on different websites!

How cookies can be set and retrieved

Client-Side

  • JavaScript can set and retrieved using document.cookie
  • More details here

Server-Side (Node/Express, but also other server-side languages):

  • When the browser requests a page, the server may send back a cookie(s) with it to store on the client - this can be done in different server-side languages.
  • Future requests to the server will bring back the cookie until it expires.
  • If your server has previously sent any cookies to the browser, the browser will send them back on subsequent requests to remind the server who is connecting to it.

How to read and use cookies?

document.cookie

Returns a long string, looking something like:

"_ga=GA1.2.1860036673.1569205383; dwf_sg_task_completion=False; _gid=GA1.2.1782728754.1588304902; lux_uid=158861962030447448"

This string follows a pattern (RegEx, anyone?), like key=value; key2=value2

Can be tricky to parse correctly. So... there's another way.

Cookie Footnote: Cookies and Expiration time

Client-Side Browser Storage

Cookies are shared by clients and servers, and are fairly small (4kb)

There are Storage technologies built-in to the browser to store data that doesn't need to be stored on the server

What information can you think of that is useful to store only on the client?

  • Color theme preferences
  • Saved shopping cart (until an "order" button is clicked to submit a request
  • Previous searches
  • ...

Browser storage technologies

localStorage and sessionStorage can be used to store data on the browser.

localStorage is a window property that allows you to save information across browser sessions (i.e after you close the browser)

sessionStorage is a window property that allows you to save information for this session only, and will be cleared when the page is closed.

Name/value pairs (seen in cookies and Storage) are supported by most every browser

Storage

There are four useful methods for Storage

method description
setItem(keyName, keyValue) Sets the keyName location in storage to be keyValue
getItem(keyName) Retrieves the keyValue in storage associated with keyName
removeItem(keyName) Removes the keyName location in storage
clear() Removes all key/values in the storage

storage-demo.html compares the two storage technologies using the code on the following slides. Inspect the Chrome Application Tab to see the difference between different browser windows.

localStorage example

window.localStorage.setItem("color-mode", "dark");
window.localStorage.setItem("language", "en");
window.localStorage.setItem("favorite-drink", "coffee");
let colorMode = window.localStorage.getItem("color-mode");
window.localStorage.removeItem("color-mode");

JavaScript (example)

sessionStorage example

Similarly for sessionStorage...

window.sessionStorage.setItem("color-mode", "dark");
window.sessionStorage.setItem("language", "en");
window.sessionStorage.setItem("favorite-drink", "coffee");
let colorMode = window.sessionStorage.getItem("color-mode");
window.sessionStorage.removeItem("color-mode");

JavaScript (example)

Viewing Storage in the Applications Tab

Viewing local storage

Requirement: Values are Strings

But what if you want a key to hold a collection of items (e.g. a dictionary of preferences, or a current cart)?


let notes = [{ tag : "Personal", note : "Feed Orange." },
             { tag : "Personal", note : "Exercise Juice."}];
window.localStorage.setItem("notes", notes);
let data = window.localStorage.getItem("notes");
// { notes : [Object object] }

JS

Solution: Save stringified object (possibly an array) and access as parsed JSON


window.localStorage.setItem("notes", JSON.stringify(notes));
let data = JSON.parse(window.localStorage.getItem("notes"));
// { notes : [{ tag : "Personal", note : "Feed Orange." },
//            { tag : "Personal", note : "Exercise Juice." }]}

JS

Summary: Cookies vs. Browser Storage

Cookies Local Storage Session Storage
Size 4kb ~10mb ~5-10m
Expires Manually Set Never When browser is closed
Storage Location Browser and Server Browser Only Browser Only
Sent with HTTP Requests Yes No No

Note that storage limits for local/session storage depend on browser and device (Desktop vs. Mobile).

More questions from this lecture?

Especially if you're watching a recording, write your question on PollEverywhere and I'll answer them at the start of next lecture.

Either on your phone or computer, go to PollEv.com/robcse