All CS 110 Reading

This page contains all the at-home reading material for CS 110, not including the textbooks and such. Feel free to search this if you're looking for something and can't find it.

HTML

HTML, CSS and JavaScript

In this course, you will learn three languages, which play different roles in the implementation of a web page:

  • HTML (HyperText Markup Language). This language specifies the structure and content of a web page. You can think of it as the flesh and bones of a site.
  • CSS (Cascading Style Sheets). This language specifies the appearance, presentation or style of a web page. You can think of it as the clothes, though sometimes the metaphor of skin is used.
  • JavaScript. This language specifies the behavior of a web page. If the page is dynamic or interactive, it's JavaScript that supplies the magic.

We will begin with HTML.

HTML Elements and Tags

An HTML document is composed out of elements that begin and end with tags. For example, the H2 tag was used to create the header element you see above:

<h2> HTML Elements and Tags </h2>
start tag contents end tag

Here's an example of a simple page; it's an excerpt of the CS fun example that we saw in class on the first day.

<!doctype html>
<!-- created by Ellen -->
<html>

    <!-- A simple web page illustrating some basic HTML tags -->

    <head>
        <title>Fun CS events</title>
    </head>

    <body>
        <h1>Join us for some fun CS department events!</h1>
        <ul>
            <li>Spring Cirque du CS 
            <li>Holiday cookie party
            <li>Faculty-student frisbee game
        </ul>

        <h2>Spring Cirque du CS</h2>
        <p>A celebration of student accomplishments in Computer Science! 
           <strong>Demonstrate your CS110 project!</strong>
        </p>
        <p>
            <img src="cirque1.jpg" alt="circus treats" height="200">
        </p>
  
        <h2>Outdoor Fun</h2>

        <p>All levels of skill and experience are welcome!</p>
        <blockquote>
              <p>The faculty have always beaten us in the past, but never again! We have 
              some Wellesley Whiptails <br> on our team and we've been practicing hard, 
              so we're gonna kick the faculty's butt this year! <br>
              <em>-- anonymous CS student</em>
              </p>
         </blockquote>
    </body>
</html>

The following are some HTML tags that you can see above. If you forget what a tag does or are looking for a new tag, you can look up tags in an HTML Reference. (Note that we will not be learning all the tags in that reference; we'll learn a useful subset.) Some of the tags we've seen are:

  • Structural tags like
    • <html>
    • <head>
    • <title>
    • <body>
  • Header tags are <h1><h6>
  • Text tags like
    • <p>
    • <br>
    • <strong>
    • <em>
    • <code>
    • <q>
  • List tags:
    • <ul>
    • <ol>
    • <li>

There are several other tags that you have seen, but still need to learn more about.

  • The all-important anchor (hyperlink) tag: <a>
  • The image tag: <img>
  • Odd tags like <link> and <meta>

We'll learn more about these in this reading.

Most elements have an end tag that matches the start tag. In a few special cases, particularly </p> and </li>, the end tag is optional and may be omitted because the browser can determine it from context.

Some elements (such as <br>, <hr>, and <img>) consist only of a start tag and do not have corresponding end tags or contents. These are called empty elements.

Tags serve as instructions telling the browser how to display the contents of elements. The browser is an interpreter for HTML code; it reads the HTML code and renders its elements based on rules for each kind of tag.

Nesting

Multiple tags can be nested: one fits inside the other like measuring cups or Russian dolls. If we have two tags, fred and barney, they can be nested like this:

<fred>
   Region A
      <barney>
         Region B
      </barney>
   Region C
</fred>

The fred tag applies to all three regions, Region A, Region B and Region C, while barney applies only to Region B that it surrounds. The Region A and Region C only have the fred tag apply to them.

When nesting two tags, the inner tag must be closed before the outer tag is closed. Your browser may not enforce this; it may be forgiving of errors, but you can't be sure that every browser will be so forgiving, so always follow this syntactic rule.

Tag Syntax

We learned that tags always begin with a left angle bracket < and close with a right angle bracket >. (Remember that the browser doesn't care whether the tag's name is upper or lower case.) You can provide additional information within the tag to further specify what it does, using attributes.

Structural Tags

Web pages have a required structure, and so there are required structural tags to mark the different parts. Each page has a HEAD and a BODY, enclosed by tags with those names. These two parts are contained within an HTML element. The HEAD contains information about the page, such as its TITLE, so the HEAD requires the <title> element. We'll learn more of these structural tags later.

Header Tags

Headers are just what you think they are: they're just like headings for chapters, sections, subsections and so forth in books, papers and other documents that you're used to. H1 is for things like chapters, H2 for sections, H3 fo subsections, and so forth.

Text Tags

Text tags are used for textual elements, such as creating paragraphs using the <P> tag, or emphasizing some text using the <EM> tag, and so forth.

List Tags

If we want to create a bullet list, we can use the <UL> tag, which stands for unordered list. This tag is just a container: it encloses a set of list items, each created by the <LI> tag. Thus, the following creates a list:

  <ul>
    <li>apples
    <li>bananas
    <li>coconuts
  </ul>

If you want the list items to be numbered automatically, you want an ordered list, which you can get with the <OL> tag.

A good example of the use of attributes is seen with the anchor tag, <a>. To use it as a hyperlink, you have to specify where the link takes us. For example, to have a link that says Google and takes us to www.google.com, we say:

<a href="http://www.google.com">Google</a>

The href part is the attribute. For this tag, since the attribute is almost always required, we can almost think of it as an a href tag, but that way of thinking will confuse us later, so it's best to think of it as two separate ideas. Later, we'll see other attributes for the <a> tag.

Exercise 1

(Note: we will intersperse exercises like this in the reading. They are solely for your benefit. They are typically short and may help with understanding the concepts and techniques. They are not graded. We highly recommend that you make time for them.)

To start this exercise, click on this link to JSFiddle. JSFiddle is an extremely popular sandbox that allows you to play with HTML, CSS and JS right in your browser, without having to launch an editor (such as TextWrangler), save files to your server, or any other such infrastructure. We'll use it a lot in this course.

Copy/paste the following code into the HTML box of the JSFiddle. Then click the "Run" menu item to see the result.

  <p>This is the text on my little page.</p>

  <p>This is some additional, very boring, text on my page.</p>

Then add an h1 header and an h2 header to the page.

Now put in a link to your favorite website. Here are some of ours. (To see the URL where they go hover over a link and look at the left-bottom bar of your browser.)

The title tag

The contents of the title tag doesn't appear on the body of the web page (though it often appears at the top of the window in the title bar). It is, however, very important for two reasons:

  • It tells search engines what stuff is on the page.
  • It appears in menus when someone bookmarks a page or looks in their history.

For both those reasons, a page title like about us or contact is often not helpful. It's a good idea to put something more descriptive in the title, such as About CS 110 or CS 110 staff contact information.

Once, it was very popular on the web to have links like this:

  • Click here for apple pie recipes
  • Click here for peach pie recipes
  • Click here for prune pie recipes

It seemed so clever and intuitive, making the clickable text be the word "here." There are two big problems with this, though:

  • Accessibility: Screen-reading software for the blind often will read the text of the links on a page so that the user can easily navigate to other pages. Links like those above read as "here," "here," "here" — useless.
  • Indexing: Search engines pay special attention to the click text on a page, since those are often an important clue about the content of the destination page. The links above don't show what the important words are.

So what do you do instead? Just wrap the link tags around important words:

Accessibility is very important in CS 110, so keep that in mind.

In the head element of each CS110 lecture page, you'll see some HTML that looks something like:

   <link href="http://cs.wellesley.edu/~cs110/cs110-main-style.css" rel="stylesheet" type="text/css">

Like the anchor tag, the <link> tag also has an href attribute, and it also links one web page with another. However, it has a different purpose. Instead of producing a clickable link, the <link> tag tells the browser that there is some additional information about this page located in a different file. The href attribute of the <link> tag tells the browser where to find the other file. The href attribute contains a URL, which we'll learn about later.

The <link> tag contains other attributes depending on the purpose of the connection. In our case, it contains:

  • a rel attribute that says what the RELationship the other file has to this one. We use it to specify a style sheet, which says how tags should be formatted.
  • a type attribute that says what kind of stuff the other file contains. In our case, we say that the file contains text/css.
In HTML5, the attribute type is not required anymore. The reason is that CSS is declared the default style for HTML5. However, you might see type in our older examples and in many pages on the Web. It is not an error to use it, but it's not required anymore.

The <link> tag can be used for a variety of purposes, but most current browsers only use it for style sheets.

At this point, the <link> tag is still a mystery. We've told you what it's for, and something about its syntax, but not what goes in the other file. We'll learn more about the <link> tag, style sheets and CSS in later lectures.

Exercise 2

Modify the JSFiddle from the previous exercise by adding the following link element near the top. (You'll get a minor complaint from JSFiddle, but you can ignore it.)

<link href="https://cs.wellesley.edu/~cs110/cs110-main-style.css" rel="stylesheet">

How does this affect the appearance of the document?

In the modified document, how can you change the appearance of an unvisited hyperlink from blue text to text that is large and green? (Hint: use a header tag.)

Tag and Attribute Syntax

We can now generalize start tag syntax to include any number of attributes, as follows:

<tag attr1 = "value1" attr2 = "value2" ... attrN = "valueN"> 
   contents
</tag>

Browsers differ on how nit-picky they are about attributes. Many will let you get away with omitting the quotation marks when the value is a single solid word (no spaces in the value). Others will complain if you have line-breaks in your attributes. In general, it's best to comply with the strictest syntax rules, so that your site will work on the most browsers.

Note that some versions of HTML, namely XHTML, require attributes to be in quotation marks. We're using HTML5, which is much more liberal, and will let you omit quotation marks unless the value contains a space, a line break, grave accent (`), equals sign (=), less than sign (<), greater than sign (>), quote (") or apostrophe ('). In short, if there's anything confusing in the value, use quotation marks.

Using Images

One thing that we all want to do with our web pages is add pictures. Because the picture file is a separate file, we have to link to it, just like the href attribute of the anchor (<a>) tag.

Once you have an image file, say small_weasel.jpg you can use it on your web page like this:

<img src = "small_weasel.jpg" alt = "a small weasel">

with the following result:

a small weasel

Of course, this only works if the server can find the image file. The src attribute must be the URL of the image file. It can be an absolute URL or a relative URL. What did we use here?

When the browser asks for this page, the server sends it back and it also finds and sends back any image files that the page references. If the server doesn't find the file (or the file is corrupted in some way), the browser will show this:

a small weasel

Depending on your browser, you may see a broken-image icon above, the alt text, or possibly nothing at all.

Exercise 3

Modify the JSfiddle to display an image of the weasel. (Of course, you could replace this image by any other image you'd like!) Note that in this case, you must use an absolute URL for the IMG, namely:

http://cs.wellesley.edu/~cs110/reading/small_weasel.jpg

Add a title attribute with value "small weasel image" to the image. What does this do?

The ALT Attribute

You noticed that we added an ALT attribute to the IMG tag that is a small piece of text that can be used in place of the image in certain circumstances. The ALT attribute is an important part of the HTML standard. Perhaps its most important use supports accessibility. Unfortunately, not everyone has good enough vision to see the images that we use in our websites, but that doesn't mean they can't and don't use the Web. Instead, they (typically) have software that reads a web page to them, including links. When the software gets to an IMG tag, it reads the ALT text. If there is no ALT text, it may read the SRC attribute, hoping there's a hint there, but all too often the SRC attribute is something like "../images/DCN87372.jpg" and the visually impaired web user is left to guess.

Therefore, you should always include a brief, useful value for the ALT attribute. If your page is an image gallery, then your ALT text could be a description of the image. However, describing the image is not, in general, the idea. For example, if the image is a link whose target is made clear by the image, then the ALT text should say something like, "Link to ..." so the user will know what to do with it. The sole exception is for images that are just used for formatting, such as blank pictures that fill areas or colorful bullets for bullet lists. In those cases, in fact, it's better to include an ALT attribute that is empty, so that the user doesn't have to listen to the SRC attribute being read. In both cases, the text should be useful for someone who wants to use your site but isn't sighted. It helps to turn off images and view your site to check.

Furthermore, you should avoid having critical information on your website conveyed only in images. There may be times when it is unavoidable, but to the extent that it is possible, we want our websites to be easily usable by all people, including the blind and visually impaired.

Accessibility is important in modern society. We build ramps as well as stairs, we put cutouts in curbs, and we allocate parking spaces for the handicapped. Indeed, most federal and state government websites are legally required to be accessible, and ALT attributes are just one part of that.

In this class, we expect you to always use the ALT attribute. If you find an image or an example where we've forgotten to use one, please bring it to our attention.

For more information, you can read the following

Resizing and Aspect Ratio

If you want to display a bunch of pictures, the web page appears neater if the pictures align well. You can align them vertically if they all have the same width, or horizontally if they all have the same height. For example, the following three pictures are all 150 pixels high.

a molehill the Eiffel Tower the Matterhorn

Regardless of the actual dimensions of an image, the browser will squeeze it into a set size if requested. You can do this with two new attributes, namely HEIGHT and WIDTH:

<img src="..." alt="..."  height="height-goes-here"   width="width-goes-here">

Replace the "height-goes-here" and "width-goes-here" with integers specified in pixels, which we'll discuss later. If both width and height are specified, both will be obeyed, but you have to be careful with that. Suppose the original image is 160x240: taller than it is wide. Technically, the ratio of the width to the height is called the aspect ratio. The Eiffel Tower picture has an aspect ratio of 160:240 or 2:3. If you set the height and width so that they don't have the same aspect ratio, the picture will look distorted. Here is the Eiffel Tower with the wrong aspect ratio:

<img src="eiffel-tower.jpeg" alt="the Eiffel Tower" width="300" height="150">

the Eiffel Tower

If you use either the HEIGHT or the WIDTH attributes, but not both, the browser will usually calculate the other attribute so that the aspect ratio is preserved. Thus, the picture will have either the width or height you want, but will not be distorted. That's how we did that row of pictures above.

Exercise 4

Modify the JSfiddle to display an image of the Eiffel tower next to the weasel so that both images have the same height. You'll have to use an absolute URL for both images:

http://cs.wellesley.edu/~cs110/reading/small_weasel.jpg
http://cs.wellesley.edu/~cs110/reading/HTML-files/eiffel-tower.jpeg

Comments

From the very first computer program, programmers have needed to leave notes in the code to help themselves and others understand what's going on or what the code's purpose is. These notes are called comments. Comments are a part of the program text (they're not written separately, because then, well, they'd get separated), but they are ignored by the computer. Comments aren't about what someone can discover by reading the code, but should cover the background context of the code, or its goal.

Because it's important to get in the habit of putting comments in your HTML code, we will require comments in this course. At this point, you won't have a lot to say, and that's fine. You will start by labeling each file with its name, your name, the date, and any sources you consulted (such as the source code of other web pages). Think of this as signing your work. Later, when you're designing a website with many coordinated pages, you can use comments on a page to talk about how it fits into the overall plan.

HTML Comment Syntax

The HTML comment syntax is a little odd-looking. Here's an example:

<!-- I can say anything I want in a comment.  -->

The syntax starts with a left angle bracket < then an exclamation point and two hyphens, then the comment (anything you want) and ends with two hyphens and a right angle bracket >.

Beauty in Websites

Ah, but you object that your web page looks ugly without centering, font changes, colors, and so forth. That may be; we're not going to try to contradict your aesthetic sense. However, for the first week of this course, we don't want to confuse anyone by introducing style sheets right away. So, we ask you to be patient. We will get to style sheets very soon.

In the meantime, consider the fact that many visitors to your site might not gain any advantage from style sheets anyway, because they are visually impaired, or because they are using an old or alternative browser that doesn't honor style sheets. For such users, the most important thing is the content and having that content well-structured and clearly conveyed. So, until we get to style sheets, consider that you are designing your website with accessibility in mind.

Bugs and Debugging

An HTML document may contain many different kinds of errors that prevent it from rendering as you expect. Errors in code are known as bugs, and the process of finding and correcting such errors is called debugging.

Here are some common types of HTML bugs:

  • a tag name is misspelled/wrong, such as <tilte> or <break>.
  • a start tag is used in place of an end tag:

    <em>important<em>

  • a tag is malformed:

    <em important</em>

  • an element has an end tag that doesn't match the start tag:

    <h1>CS110 HTML Coding</h2>

  • tags aren't nested properly (really just a special case of the previous bug):

    <h1><em>CS110 HTML Coding</h1><em>

  • attribute names are misspelled/wrong:

    <img source="logo.jpg" hieght=100>

  • quote marks aren't properly matched:

    <img src="logo.jpg height=100>

Exercise 5

Copy the following buggy HTML code into a JSfiddle and debug the code until it looks like you think it's intended to look.

<h1>A Buggy HTML File</h1>

<p> This HTML file contains several <em>bugs</em> (i.e., errors).
<br>
Can you <em>debug</em> them (i.e., find and fix them)?

<p>Here's an unordered list with three items: 

<ul>

    <li>A <strong>strong</strong> item.</li>

    <li>An ordered sublist with two items: 

        <ol> 

          <p> A CAPITALIZED item 

          <li> An <a href="http://www.wellesley.edu">
                  <em>italic link</a></em>
   
    <li> A final <code>item<code>, using code font.

</ul>

<p>Here's <a href="http://cs.wellesley.edu another link</a>

Validation of HTML Code

How can you be sure you've followed every nit-picky rule that the HTML standards committee devised? (The standards committee is the World Wide Web Consortium or W3C.) Even if you have memorized all the rules, checking a page would be tedious and error-prone – perfect for a computer! Fortunately, the W3C created an HTML validator. You can validate by supplying a URL, by uploading a file, or even copy/pasting in some HTML. Visit that page and try validating your little.html file, debugged buggy.html file, or even the file for this lecture. An HTML validator is an excellent tool to help you debug your HTML code.

Validation also helps with accessibility. One important aspect of accessibility is having the proper HTML syntax for each page in your site. Visitors with accessibility needs will use the alternative browsers and screen readers, and that software will be aided by syntactically correct HTML. Read the following for a longer discussion of why to validate your HTML pages.

Throughout the semester, if you need to validate a web page, you can find the HTML validator and others in the validators section of the CS110 documentation page.

If you haven't already, try validating little.html. You'll see that it doesn't validate. The reasons are slightly technical, so bear with us, but you'll see how to make your own documents valid.

Document Type

There are several different, incompatible HTML versions, and so a document that is valid HTML 3.2 is invalid HTMl 4.01 and vice versa. Neither would be valid XHTML 1.0. So, the validator needs to know what version of HTML you're using. More importantly, the browser or screen reader or other software needs to know what syntax to expect. Therefore, the first thing any web page needs to do is announce the syntax it's using. This is done with a special DOCTYPE (for document type) tag.

In this course, we're using HTML5. (Your book describes HTML 4.01 (and also XHTML), but HTML 4.01 is essentially a subset of HTML5, so nothing they tell you will be incorrect.) Fortunately, the doctype for HTML5 is very simple and easy, certainly compared to HTML 4.01. It looks like this:

      <!doctype html>
    

We urge you just to copy/paste that tag to your own pages and don't worry about it further.

Note: because HTML5 is still pretty new, the validator at W3C will give you a warning that the result is "experimental."

Charset

A browser needs to know what characters (letters, numbers, and punctuation) are in the HTML file. Are they western European characters, or Russian, Greek, Sanskrit, Korean, Japanese, Chinese, or !Kung or something else? This information is called the character set or charset for short. For our purposes, we can use something called UTF-8.

To do so, we put a <meta> tag in the <head> of our document. It looks like this:

 <meta charset="utf-8">

Again, we urge you just to copy/paste that code and don't worry about it.

Icon Declaring Validation

Once you get your page to validate, you can put some HTML code on your page to give it a seal of approval, declaring that it is valid (and what standard it meets). You will see in lab examples of this strategy.

The very cool thing about this icon is that it is clickable, and clicking it will cause the validator to process your page again. Thus, you can modify your page, upload the changes, and click the icon to re-validate it, making validation very easy. In fact, we suggest that you put the icon on your page before it's valid, and use it during your debugging process.

The snippet of code is just the following, so go ahead and copy/paste it into your pages. The code doesn't use anything we don't know, so read it!

<p>
  <a href="http://validator.w3.org/check?uri=referer">
     <img 
       src="http://cs.wellesley.edu/~cs110/Icons/valid-html5v2.png"
       alt="Valid HTML 5"
       title="Valid HTML 5"  
       height="31" width="88">
  </a> 
</p>

An HTML Template

The preceding requirements result in a kind of boilerplate that you'll need for all your web pages. Feel free to copy/paste the following to begin all your HTML pages, or to use this template.html

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <link rel="stylesheet" href="style.css">
    <meta name=author content="Your name here">
    <title>title here</title>
</head>
<body>

<p>
  <a href="http://validator.w3.org/check?uri=referer">
     <img 
       src="http://cs.wellesley.edu/~cs110/Icons/valid-html5v2.png"
       alt="Valid HTML 5"
       title="Valid HTML 5"  
       height="31" width="88">
  </a> 
</p>
</body>
</html>

DIV and CSS

This section introduces the DIV tag. The DIV tag is a generic container tag, which doesn't make a lot of sense yet, but will in the next few readings. To motivate the DIV tag, we'll talk a little about CSS, but not in a complete or definitive way, so bear with us on that. We'll get to CSS very soon.

CSS (Cascading Style Sheets) is the style language for web pages. Here is one way (not even the best way) to put a green box around a paragraph:

  <p style="border: 3px solid green">Success makes so many people hate you... &mdash;
  Marilyn Monroe</p>

Here it is in action:

Success makes so many people hate you... — Marilyn Monroe

So far, so good. If we wanted to put a box around two paragraphs, we would need an element that contains both those paragraphs. It turns out that HTML paragraphs can't contain other HTML paragraphs, which makes sense because normal everyday paragraphs don't contain other paragraphs.

None of the other HTML elements really work either, so to handle this situation, the World Wide Web HTML standards committee created the <DIV> tag, standing for a division of your document. A DIV can contain anything (paragraphs, lists, headers, and even other DIVs). Consequently, DIV is very useful and is used a lot. A more real-world example is a putting a set of links into a DIV and positioning that to be a navigation area, or putting a set of paragraphs in a DIV to create a set of posts. We will use it a lot in CS 110, though we will also use some newer tags that are intended to reduce the over-use of DIV.

The need for meaningful tags

As we've said, HTML was designed to structure the content of a web page. That explains the existence of tags like <p>, <h1>, <ol>, etc. However, when web developers started creating pages with a lot of content, it became clear that to make better use of the available screen space, a way to organize the page content in bigger chunks was needed. Then, CSS could be used to arrange their position on the page. Therefore, the tag <div> was born (short for division), which is currently the most used (and overused) tag in every webpage. While this seemed to have solved the page layout problem, HTML code became difficult to understand, other computer programs (e.g. search engines) couldn't make sense of all divs in a page, if they wanted to use the organization of the page for inferring the meaning of the content.

HTML5 introduced a series of new tags that have meaningful names and can be used universally to express what the content is about, beyond the existing simple tags. Additionally, to make the pages more alive with different kinds of content, several new tags that allow content to be embedded in a page were also added. In the following, we will give a short summary of some of these tags. Try to make use of them in your pages. They will make your code better and more readable to the programs of the future.

Semantic Tags

Here is a list of new HTML5 tags that are known as semantic tags, because their names have specific meaning. Click on the info icon () for more information about each one.

Tag Name Short Description More Info
<header> Specifies a header for a document or section.
<footer> Specifies a footer for a document or section.
<section> Defines sections in a document (e.g. chapters).
<nav> Defines a set of navigation links.
<aside> Defines content which is relevant but not central (e.g. callouts, sidebars).
<article> Defines independent, self-contained content (e.g., blog post, news story).
<abbr> Indicates an abbreviation or acronym.

<abbr title="United Nations">UN</abbr>

See an example in action in the paragraph below for the word W3C.

Which Tag to Use?

Given all the tags listed above, along with DIV, you might feel bewildered as to which one to use. Here is a helpful HTML5 sectioning flowchart from html5doctor.com. Click on the image to see a larger version:

HTML5 Sectioning Flowchart

Click on the image to see a larger version

Browser Support

Changing the web language standards goes through a lengthy process spearheaded by the W3C consortium. The vendors of the browsers need often many years to implement all the changes. Therefore, not all new HTML5 are currently supported by all browsers. The info link in the table gives information about which browsers currently support the tag.

Media Tags

HTML5 also introduces more meaningful tags to support embedding media resources directly in the page, allowing for a more rich experience in the browser. Below we show four such tags in action.

Tag Name Short Description More Info
<figure>
<figcaption>
Specifies self-contained content (e.g. illustrations, diagrams, photos). It uses <figcaption> to specify individual or group captions.
<video> Specifies video, such as a movie clip or other video streams.
Three supported formats for the moment are MP4, WebM, Ogg.
<audio> Specifies sound, such as music or other audio streams.

The <figure> and <figcaption> tags

The tags in action:

Chihiro from the movie Spirited Away. Image Source.

Here is how to use these two tags

  <figure> 
    <img src="images/imageName.png" alt="image description" >
    <figcaption>A caption for the image</figcaption>
  </figure>
          

For more examples and explanation for this pair of tags read this article by the HTML5Doctor website.

The <video> tag

Here is an example of embedding video directly on your page:

  <video controls
            src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"
            width="300"
            id="bunny_video"
  >
          

The attributes controls and autoplay are called boolean attributes. A tag either has them or doesn't have them. Here, we've omitted autoplay, so that the page won't make noise when you load it.

The <audio> tag

Here is an example of embedding audio directly on your page:

    <audio controls>
      <source src="http://www.jingle.org/britsungmont.mp3" type="audio/mpeg">
      Your browser does not support the audio element.
    </audio>
  

Live Testing

Often you want simply to try out new elements or their combination, without having to write a complete HTML document. We have already seen how the documentation for the HTML tags by the W3Schools website provides an editing space where to experiment with tags. However, there are many more tools on the web that allow you to do the same, for all three languages at once: HTML, CSS, and Javascript.

One tool that we will be using during lecture time for experimentation is jsfiddle. Here is a screenshot from trying out the <video> tag directly in its workspace.

a screenshot for jsfiddle
A screenshot from jsfiddle use

Solutions to Exercises

URLs

Absolute URLs

URLs are used to specify the locations of resources in files on any computer in the world, so they can be a little complex. Taking as an example the URL of the page you are reading:

http:// cs.wellesley.edu/ ~cs110/lectures/L02/ URLs.html
protocol server.domain path filename

let's break it down in its components:

  • http:// This is the protocol, which is almost always HTTP, the HyperText Transfer Protocol. You'll also occasionally see FTP, the File Transfer Protocol; HTTPS, the secure version of HTTP; and others.
  • cs.wellesley.edu/  This is the server: a machine connected to the internet that hands out files to anyone who asks. cs is the name of the machine; wellesley.edu is the domain. The name of the server combined with the domain must be unique in the world. In fact, the domain must be unique in the world, and the server name must be unique within the domain.
  • ~cs110/lectures/L02/  This is the path: a sequence of directories (AKA folders), separated by slashes, that indicates where on the server the file is located. In this path, there's a tilde (~), which means to start at the public_html directory under the home directory of the cs110 account. We'll always be using that kind of URL in this class, so keep this special rule in mind.
  • URLs.html  This is the file that is being requested.

Because URLs can specify files on many different kinds of computers, you should stick to a lowest common denominator when naming your directories and files, to avoid confusing machines and browsers. The lowest common denominator means:

  • use letters and digits, but no special characters like /, *, #, &, and so forth
  • no spaces (this is the most common error for Mac and PC users). For example, if you want to have a web page named cats and dogs.html you're much safer with cats-and-dogs.html or cats_and_dogs.html

Furthermore, be careful with upper and lower case. To your eyes, cats.html and Cats.html may seem like the same filename, but to a computer, they're as different as cats.html and dogs.html. The same rule is true of directory names: they are case-sensitive. Many people like to stick to all lower-case, just so they don't have to remember. .

Exercise 1

Use a file transfer program (such as Fetch or WinSCP) to create a path of directories in your CS account, and then create a simple web page that just says “hello world” and put it in the bottommost directory. Construct the URL to the page and then try to view the page with your browser.

Certain parts of the end of an absolute URL can be omitted. For example, the filename can be omitted and (usually) defaults to a file named index.html in the specified directory (for an example, see our course homepage). Similarly, the path can be omitted, in which case the page is in the top directory of the web server. However, the protocol and server must be specified. You can't omit those. If a URL has a protocol, it's an absolute URL, otherwise it'll be treated as a relative URL.

Tree Structured Directories

As you know, most operating systems (including Mac, Windows, Unix, iOS, Android, etc.), organize the contents of a computer's hard drive into folders, also called directories. Folders and files form a tree structure, because of the ability of directories to contain other directories.

Here's an example:

For a website about Joss Whedon, we might have a folder about his Buffy the Vampire Slayer TV show, another about the TV show Angel, and a document about his comics. These might all be in a top-level folder called Joss. (The top-level folder is also called the root folder.) The folders about the TV shows might each have a sub-folder called cast. And so on.

While it's easy to conceptualize a tree of folders and files, also called a directory tree, there are many different ways to draw it. Here are several ways of depicting the Joss directory tree described above that you will see in this course:

Joss directory tree drawn by hand
A hand drawing for the Joss Whedon's website.
Joss directory tree on a Mac
The folder structure as displayed in Mac by Finder.
Joss directory tree on Windows
The folder structure as displayed in Windows by Windows Explorer.

For example, we can see that buffy.html and willow.html are both files in the same directory, the one called cast, which is, in turn, one of three things in the directory called Buffy, which is in the directory called Joss. Joss contains two directories (Buffy and Angel) and a file called comics.html and so on. Take a minute to be sure you understand the relationships among the directories and files. Notice that there are two files named angel.html; this is okay, because they are in different directories.

Relative URLs

We can use these relationships to form a shorthand way of specifying a URL. This is called a relative URL, because we specify the location of a file relative to a known file. Here are the basic rules:

  • Relative URLs are only for files on the same server. Therefore, we can leave off the protocol and server name.
  • If a file is in the same directory as the HTML file containing the link, we just give its name. If we want to put a link in the file buffy.html linking it to willow.html, we can say:
    <a href="willow.html">her best friend Willow</a>
  • If a file is in a sibling subdirectory, we can just give the path starting from the sibling. So, if we are in the file called mythology.html and we want to give a link to the file angel.html, we can say:
    <a href="cast/angel.html">Angel, the vampire with a soul</a>
  • If the file is in a directory that contains a subdirectory that contains the HTML file with the link, we have to go up the tree. To go up, we write ../. That's dot, dot, slash. For example, if we are in the file host.html and we want to make a link to season3.html, we can say:
    <a href="../season3.html">the Host returned in season 3</a>
    That last step, with the .. is tricky: to go up, we write ..; while to go down we have to indicate which subdirectory we mean. In either case, we separate these up/down steps with a slash. Here's another example: suppose we want to put a link from buffy.html to comics.html. In this case, we can write:
    <a href="../../comics.html">another layer in the comics</a>

Exercise 2

Create some additional directories in the public_html folder of your CS account and practice with the relative URLs. Relative URLs will make your lives much easier when you produce different versions and when you deliver your website to your client. Try the equivalent of:

  • A link from plot.html to comics.html
  • A link from season3.html to plot.html
  • A link from gunn.html to willow.html

Fragments

The model above establishes a one-to-one correspondence between a URL and a file (web page) somewhere in the vast Internet. Sometimes, however, you want to address (point to) a particular location within a page. Such locations are called fragments.

While fragments can be used in many ways, one common use is to have a table of contents at the top of a page, allowing readers to skip down to the particular section they are interested in. An example of such a table of contents is at the left side of these notes.

Fragments are addressed by extending the URL by adding a # character and the id attribute of the fragment (the HTML element that refers to the fragment). Thus, we have:

http:// cs.wellesley.edu/ ~cs110/lectures/L03-html/ URLs.html# relative
protocol server.domain path filename fragment id

One key step is marking the destination of the URL, by naming the fragment, just as we name a file or folder. This is done with the id attribute, which can be applied to every HTML tag. We typically add it to the header tag (such as h2) of the section we want to skip to. For example:

<h2 id="relative">Relative URLs</h2>

Given the code above, we can then point to that section from any web page anywhere, using an absolute URL, like the one in the table above. We can also use fragments with relative URLs. For example, to point to that section from another file in the same directory, we can just give the filename and the fragment name: URLs.html#relative. In fact, if we want to point to it from within the same file, we can omit the filename and the relative URL becomes just #relative. You can see examples of that kind of URL in the table of contents on the sidebar.

Web Navigation

Let's look now at some of the standard navigational structures of web pages. As the name suggests, a site's navigational structure describes the paths of navigation through the site. When thinking about these structures, keep in mind that while some sites consist of only a single page, most "real" websites consist of many pages. In most websites with more than just a few pages, you will see a combination of several of these structures.

Linear and Circular

linear and circular navigation

  • Follows pre-defined path
  • Links to NEXT and PREV
  • Examples: Slide Show, Tour or Presentation

Hub and Spoke

hub and spoke navigation

  • Central navigation hub with many links
  • Other pages only have one "back" link, hence no navigation overhead
  • Example: CS110 syllabus page links to each lecture page

Clique

clique navigation

  • Every page connects to every other page
  • No special "navigation" page
  • Quickest to get around in, but every page must have all N links on it
  • Adequate for small sites but unwieldy for larger sites
  • Example: the top level of the CS110 site

Rooted Tree

tree navigation

  • The structure is "self-similar". It has a root web page that has subtrees as its branches. Each subtree is a root with subtrees.
  • Very modular, conceptually clear
  • Separate subareas aren't connected
  • Works well for big sites
  • Examples: Yahoo!, NY Times

Network or Graph

network navigation, left halfnetwork navigation, right
half

  • Interconnections on a somewhat ad hoc basis
  • A page might be connected to a number of other pages (based on logical content of pages on site)
  • Can be too random; hard for visitors to understand
  • Almost necessary for a large site
  • Examples: Wellesley College Website

Project Considerations

Your project should consist of 8-10 pages. You should make sure to discuss with your partner how your web pages are linked to make navigation easy and logical for visitors. In the project design phase you are required to describe the interconnection of all the pages on your site and provide a brief discussion about the site's navigation structure using the terminology learned today.

CSS Introduction

When HTML was first introduced, there were a number of tags whose purpose was just for formatting: for example, tags that center or switch to an italic font. With HTML version 4.0, such tags were made obsolete (though most browsers still support them), in favor of a formatting technique called Cascading Style Sheets.

Customizing Your Tags

When a browser is displaying a page, there is a step of reading a tag, such as <em> or <h1> and then determining what the results are to look like. (This is sometimes called rendering a page.) Each browser has a default way of rendering a tag. For example, most browsers will render the <em> tag by switching to an italic version of the current font. Most browsers will render an <h1> tag by switching to a very large version of the current font. There are several important points to make about this:

  • Different browsers don't necessarily render a tag the same way. For example, you might find that <blockquote> in Safari indents by a different amount than Internet Explorer does.
  • Some control is transferred to the user. A user can decide, via their browser preferences, what font families and font sizes they want to use, or what colors their links should be. This is a good thing.
  • As the author of a web page, you can customize the rendering or style of tags in your pages. For example, if you want the <em> tag to look red, you can do that. The style of tags is determined by something called CSS, for Cascading Style Sheets.

CSS Style Sheets

You can specify the style of a tag using a style sheet. These style sheets can be put in (at least) three different places:

  1. Inline Styles. These are specified in the tag itself.
  2. Document-Level (Internal) Style Sheets. These are specified in the <head> of a document, using the special tag <style>.
  3. External Style Sheets. These are specified in a separate CSS file that is connected to the HTML file by the <link> tag. We discussed this link in the HTML lecture.

Suppose that we always want <em> to be red. (Be aware of accessibility.)

  1. Inline Style. You use the style attribute of the tag to set the color property to have the value red and the background-color property to have the value white. (You should be reminded of the attribute/value idea in tags, but the syntax is different. With CSS, property/value pairs are separated by semi-colons, and the property ends with a colon.) Note that you should always pick both colors, in case the user's browser has specified a background color that matches your foreground color. Here's the example:
    this is an <em style="color: red; background-color: white">important</em> word
    
    which results in:

    this is an important word

  2. Document-Level (Internal) Style Sheets. You use the <style> tag in the <head> of your document to specify the style for the <em> tag once and for all:
    <style>
       em { 
          color: red; 
          background-color: white;
       }
    </style>
    

    In your document (that is, in the tags enclosed by <body>), you just use the <em> tag normally, and it will be rendered as red.

  3. External Style Sheets. These look just like document-level style sheets, except that you don't put the definition(s) inside a <style> tag. Instead, you reference the file using the <link> tag in the <head>, the same place you would use the <style> tag. Suppose we create a file called my-style.css that contains the following:
    em { 
       color: red; 
       background: white;
    }

    and we reference it in the <head> like this:

    <link rel="stylesheet" href="my-style.css">
    
    

    As with document-level style sheets, we can just use the <em> tag normally from then on.

Syntax of a CSS Rule

The Head First HTML and CSS book has a good graphic for explaining the syntax of a CSS rule:

explanation of a CSS rule
Explaining the syntax rule. Appears in pg. 259 of your book.

There are several facets to the syntax of a CSS rule:

  • The style properties (such as color) are followed by a colon, then at least one space, then the value of the property (such as red). If you want to specify more than one property/value pair, separate them with semi-colons. If there's only one property/value pair, the semi-colon is optional. (Many people put it in just in case they add another property/value pair later.) The order of the style properties does not matter.
  • For an in-line style, simply state the style properties as the value of the style attribute in the HTML tag. Remember to enclose the style properties within quotation marks.
  • For either a document-level style sheet or an external style sheet, the name of the element (such as p or em) that you are modifying goes first, then an opening brace, then the style properties, then a closing brace. In a CSS rule, the element to which we apply the style is known as the selector. All tags can be selectors. However, we will see more ways to define selectors in the forthcoming material. Spaces and line breaks are ignored, so feel free to format this in a visually pleasing way. As always, clear and consistent indentation is very helpful for any reader of your styles.
  • Document-level style sheets require the enclosing <style> tag, while external style sheets always omit the <style> tag.
  • External style sheets and document-level style sheets use the same syntax for specifying the tags, properties and values, but the external style sheet omits the beginning and ending <style> tags. You'll have nothing in angle brackets in an external CSS file.
  • CSS is a different language from HTML and therefore has a different comment syntax in both an internal and external style sheet. For CSS, the comment characters are /* to begin and */ to end. Thus, for an external style sheet, you might have:
    /* Written by the CS110 Faculty
       Specifies a CSS Rule for the element <em> 
    */
          
    em {
       color: magenta; 
       background-color: white;
    } 

Some CSS Properties

Now that you know how to write style sheets, let us see some properties that you can use in these styles. One can style an element over many aspects:

  • color of the text
  • background of element (color, image, origin, position, etc.),
  • the border that surrounds the element (its color, size, style, etc.),
  • the box that surrounds the element (margin, padding, size, etc.)
  • the text inside the element (alignment, spacing, direction, etc.)
  • the font for the text of the element (font family, style, weight, etc.)
and other aspects that sometime are specific to certain elements such as tables, lists, user interface elements, etc. We suggest that you refer to the CSS Reference website for a listing and examples of all CSS properties.

Examples

In the following, we give several examples of properties that are very useful for styling elements. For pedagogical purposes, we're not providing the code as text that can be easily copied and pasted somewhere else. We believe that by typing the instructions on your own, you will learn the names and values of properties, as well as potential errors that occur when one types. We strongly suggest that you use jsfiddle to try out all these examples. Before entering the code, read our questions and try to predict the answer without running the code. Then check if you were right. To use jsfiddle, enter the HTML code in the HTML box, the CSS code in the CSS box, and then click the button Run. There is no need to write a whole HTML file, only the snippets shown in the examples. Also, to see the effect of styling, the text in HTML elements doesn't have to be meaningful as in our examples.

Example 1

example for color and opacity
Using color and opacity.

Questions for Example 1

In the rendered result, is the background color blue? Why not? What about the color of the text nested in <em>? Why it is not white like the rest? What does this tell about the order in which rules are applied?


Example 2

example for text and list properties
Styling for text and lists.

Questions for Example 2

Try first to predict how this code will be rendered. What is the effect of each rule on every element? How will the <em> nested in <li> look like? Then, enter this code in jsfiddle to see whether you were right in your predictions.


Example 3

example for background and border
Styling for background, border, and text.

The URL for the background image was generated with the Google URL shortener service.

Questions for Example 3

What do you see when this code is rendered? What happens when you comment out the rule for <header>? Can you add styling for the border-bottom property? What happens when you replace border-top- with border- (keeping the rest unchanged)? What happens when you change the value for text-align from center to right? Finally, add this style border: 3px solid red; to <header> and see what happens. This is an example of combining values for several properties in one style.

Cascading

CSS has cascading in the title because there's a strict hierarchy that determines which specification applies if the style of a particular tag is set in more than one place. Suppose you specified the <em> tag as (1) green in an external style sheet, (2) blue in a document-level style sheet and (3) red in an inline style. Which wins?

The simple answer is that the closest specification wins. This makes sense, because you can use the more local specifications to override the more distant, global specifications. So, inline style attributes beat document-level sheets, and document-level sheets beat external style sheets.

Furthermore, properties from enclosing elements can be inherited by the elements inside them. Notice how, in one of the examples, the <em> element inside the <li> element inherits its properties.

The process of resolving all the conflicting CSS rules is called the cascade. In practice, the rules are pretty intuitive: the rule that is closer and more specific wins.

Which Style Sheet to Use?

One of the most common rules of thumb for creating clear and beautiful documents is consistency. For example, section headers should always be the same size, weight and font.

You can best achieve consistency by specifying the style far enough from the text so that the style is specified in just one place. If you have a single web page that you would like to be consistent, you should use a document-level style sheet. If you have several web pages (a web site) that you want to be consistent, you should definitely use an external style sheet. Even if your website is only a single web page but you think you might someday have a second web page using the same style, you should use an external style sheet. In short, always use an external style sheet.

Imagine that you are creating a website for a client. For that website, you should define an external style sheet. Then, if you or your client decides that <h1> should be centered, <h2> should be bold and blue, <h3> should be underlined and non-bold, and <em> should be pink, you can do that in one place. If you later change your mind and decide that <em> should be purple, you make one change in one file and all of your website is consistently and instantly changed. If you had used the local style technique, you would have to edit every page of your site, searching for and modifying each occurrence. This is tedious and error prone.

We recommmend that you use external style-sheets as often as possible. Document-level style sheets can be used occasionally, but you should avoid as much as possible inline styling.

Caches

One of the great advantages of external style sheets is also, for a web developer, a slight bother. To understand that, you have to understand caches.

The word “cache” (pronounced “cash”) is an ordinary, but uncommon, English word (more of an SAT word for most people). However, it's used all the time by computer scientists because caches are used all the time by computers, in all kinds of ways, because caching is a general technique for speeding things up.

In particular, your web browser will cache (keep a copy of) an external style sheet in a folder on your local machine (that folder is called, of course, the cache). If the web browser needs that style file again, say on another page of your site that uses the same external style file, the browser doesn't have to re-download the file; it just grabs a copy from the cache. This makes the web browser faster.

So, why is the browser cache a problem for a web designer? Because if you make a change to the external style sheet, the web browser may continue to use the old cached copy, instead of getting the new improved copy from the server. This means that when you view your page, you won't see your changes — very frustrating.

The solution is to tell the web browser to ignore the cache when you re-load the page. In most web browsers, this is done by holding down the shift key when you click on the reload icon.

So, just remember:

When in doubt, use shift+reload

The Bigger Picture

The idea of CSS illustrates an important concept in the field of computer science, namely abstraction. Abstraction is the idea of saying what you want done without saying how to do it. By leaving out the details about how to do something, you allow for some flexibility, so that you can revise your method of doing the task without messing up anything that depends on that task being done. Here, we said <em> without saying what that meant, putting elsewhere the specification of how to emphasize.

Footnote: Colors and Accessibility

Since <em> stands for emphasis, what could be better emphasis than putting something in red? Unfortunately, using color to convey meaning is, in fact, a terrible idea, because some people are color-blind or even completely blind. We'll talk more about the issue of accessibility as the need arises throughout this course. You should always think about accessibility when you are designing a web page, because you want your page to be readable by anyone, not only by people with the same physical abilities, browser software, computer display, and network bandwidth that you have. Some websites are legally required to be accessible. However, for the purposes of this lecture's examples, let's suppose that using red is a sensible thing to do.

Fonts

Reading: We strongly suggest you read chapter 8 of Head First HTML and CSS with these notes.

Traditional Fonts

One of the most important aspect of a page that can be controlled with CSS is the font. A font is a collection of pictures of letters. A letter is some kind of Platonic ideal, like perfect circles or archetypal chairs. It's also a unit of information. Any particular letter is drawn by some person. Some are simple block letters, others are works of art (like medieval illuminated manuscripts). A font is a collection of these pictures, one for each character in the character set.

Fonts are studied in the field of typography, and their study is outside the scope of this course. If you are interested in their history and technique you should take the ART 222: Introductory Print Methods course offered by the Book Arts program.

For many years, fonts in web pages were restricted by the fonts that came already pre-installed in a computer. This didn't allow for a lot of variety in styling. This changed with CSS3 and the introduction of web fonts, which don't need to be installed in one's computer. Furthermore, with the use of the Google Fonts API it is very easy to incorporate such fonts in a website, as we will demonstrate in these notes.

Read the suggested chapter 8 in Head First HTML and CSS for a more detailed account on styling fonts. In the following, we give a very concise summary.

Font Properties

There are systematic ways in which fonts can be characterized:

  • Font-families: serif, sans-serif, monospace, etc. Serifs are the little marks at the end of the strokes of a letter. Along the baseline, they are horizontal, and can help guide your eye along the line. Some fonts have them, some don't. ("sans" is French for "without.") Times is a serif font; Arial is sans-serif.
  • Font names: Verdana, Arial and Geneva are all sans-serif fonts, yet they look different: they are different fonts. Each font is the creative product of some artist or foundry.
  • Style: some fonts are upright or normal, others are slanted with a little extra curliness that we call italic. Some font artists define several styles for their font families.
  • Size: fonts might be 10 point, 12 point, or many other font sizes. (A point is 1/72nd of an inch.) Some fonts simply scale the "design size," so, for example, 12 point is simply 20 percent larger than 10 point. Other fonts modify the scaling for artistic beauty. You can also use seven abstract "absolute" sizes (they specify elements of a table of font sizes kept by the browser) named:
    • xx-small
    • x-small
    • small
    • medium
    • large
    • x-large
    • xx-large

    You can also use abstract relative sizes named larger and smaller, that are relative to the surrounding font.

  • Weight: The designer may produce variant fonts with thicker or thinner lines. Fonts with thicker lines are often called bold.

Examples

In the following we show two examples of using different font families for the elements <p> and <em>. Notice how the text changes when the second rule is added.

Example 1

code to show font styling result of applying font styling
Applying a font to the element <p>.

Example 2

code to show font styling

result of applying font styling

Adding a font for the element <em>.

Optional Reading

Beyond here is optional reading for the interested student. The material is well within your abilities, and you're encouraged to read it, but it is not required.

Web Fonts

As we mentioned, with traditional fonts that come pre-installed in our machines, we have only a limited number of choices (since the fonts need to be installed in the machine of the viewers of the page too, not only your own). However, with web fonts (supported by all modern browsers) there are new ways to deliver fonts (either by having your files as part of your website, or by linking to other web servers) so that everyone can see the pages with the font we intended.

Be aware that not all fonts on the Web are free. For some of them you need to pay. Thus, it is better to start your search with one of the services that aggregate fonts that are free for use. Such a website is Font Squirrel, from which you can download the fonts you like. Suppose after browsing the available fonts, you decided to use the handdrawn font Desyrel.

screenshot from Font Squirrel site
A screenshot from the FontSquirrel website showing the page for the Desyrel font.

Clicking on the Download TTF button, you can get the file with the font (after unzipping), desyrel.ttf. Then, you can create a subfolder fonts in the folder where your HTML and CSS files are stored and then use this font as shown below:

@font-face {
       font-family: desyrel;
       src: url("fonts-files/desyrel.ttf") format("truetype");
       font-weight: normal;
       font-style: normal;
}

p {
       font-family: desyrel, cursive;
       font-size: xx-large;
}
                

This sentence was written with the Desyrel font, downloaded from FontSquirrel.


Unfortunately, things are not so simple. Because there are so many browsers and platforms, to make sure that all of them will display the desired font, we will need to provide the font in many different formats (Chapter 8 in your book explains these formats). Thus, the rule for @font-face will look a bit more complicated. The good news is that this code and all the files can be automatically created for you by Font Squirrel, using its menu for WebFont Generator, after you upload the file desyrel.tff (or some other font). Here is how the automatically generated CSS will look like:

@font-face {
    font-family: 'desyrelregular';
    src: url('desyrel-webfont.eot');
    src: url('desyrel-webfont.eot?#iefix') format('embedded-opentype'),
         url('desyrel-webfont.woff') format('woff'),
         url('desyrel-webfont.ttf') format('truetype'),
         url('desyrel-webfont.svg#desyrelregular') format('svg');
    font-weight: normal;
    font-style: normal;
}
            

Notice that the files are referred directly, and you might need to add the relative path to the folder you'll be storing these files.

If this looks like a lot of work, there is an easier way, that doesn't involve having to keep the font files on our own server, we explain this method in the next section.

Google Fonts API

The easiest way to incorporate fancy fonts in your pages is to use the free service provided by Google Fonts API. API stands for Application Programming Interface. With this method, you only need to perform a few simple steps:

  • Find fonts that you like from the list of Google Fonts , and click the button Add to Collection.
  • On the bottom part of the browser, in the Collection tab, click on the button Use and verify your choices.
  • Copy the provided <link> code from Step 3 to your HTML file (it goes in the <head> section).
  • Add the CSS code from Step 4 to the CSS rules you want.

You're done. Google takes care of providing all needed format files, you don't have to provide such formats as part of your website.

Here is an example of the code you need to write to create the shadowed header below:

The <link> line goes into the HTML file:

  <head>
    ...
    <link href='http://fonts.googleapis.com/css?family=Wallpoet' rel='stylesheet' >
 </head>

The font-family style goes in the CSS file (inside the rule for the desired element):

  h2 {
      font-family: 'Wallpoet', cursive;
      font-size: 200%;
      color: black;
      text-shadow: 4px 4px 4px gray;
}

This header uses Wallpoet from Google Fonts

The font was created by Lars Berggren.


Putting fonts into your CSS File

The previous code works fine, but if you have a dozen pages in your site, and you want to use Wallpoet in all of them, every one of those pages would have to have the link tag in the head. That is a lot of redundancy and is contrary to our goal of stating the CSS information once in the shared external CSS file.

What we can do instead is, in the Google Fonts browser, instead of using the default link code, switch to the @import tab.

In that tab, you'll find code like this (it's the same URL as in the link):

@import url(https://fonts.googleapis.com/css?family=Wallpoet);

Copy/paste that into your shared CSS file, and you'll be able to use Wallpoet in any file that uses that CSS file.

Google Fonts can break HTML Validation

When you use several Google Fonts for a page, the URL generated by Google contains the operator | to separate the different fonts. HTML doesn't like such special characters, thus, your page will not deemed valid by the W3 validator. To fix this issue, you should replace the character | with %7C.

Choosing a method

We showed here three different ways of styling fonts and that can be confusing at first. Here are some tips for you to decide what to use:

  • If the website you are building is simple and you feel overwhelmed by the choices we provided, stay with traditional fonts.
  • If you want a more sophisticated look for your website (maybe for a book or music band), get familiar with how to use Google Fonts API.
  • If your website needs a particular kind of font that Google dosn't provide, learn how to incorporate Web Fonts by using the services provided by the FontSquirrel website. Chapter 8 of your book is required reading in this case.

Keep in mind that your choice must be informed by the needs of the website you're building. Is the font important to convey something particular about the nature of the website? If the answer is yes, then you should make all the efforts to learn the advanced techniques we described.

CSS Selectors

CSS Selectors

When we introduced CSS rules, we described the generic form of a rule as in Figure 1. At the head of the rule is the selector, followed by a series of property and values pairs enclosed in curly braces.

depiction of a css rule
Figure 1: Depiction of a CSS Rule

Today's focus is on the selector. The selector indicates which element(s) the rule will apply to. So far, we have only seen a tag as the selector, so a rule would style all paragraphs (P elements), or all EM elements, or whatever elements correspond to that tag. In this reading, we will expand the set of selectors.

CSS and ID

Back in the reading on URLs, we learned about giving an element an ID (short for identifier, like a driver's license is a kind of ID card). Because an ID is unique on a web page, it can be the target of a hyperlink. For example, the title of this section (see the H2 element just before this paragraph) has an ID of css_and_id, and so the relative URL for this section is http://css-selectors.html#css_and_id. (Try it!).

In addition, an ID can be used as the selector in a CSS rule. Thus, the following rule was used to make that H2 section header teal:

#css_and_id {
   color: teal;
}

Notice the syntax here: the ID is preceded by a # symbol (pronounced hash, or sharp sign, or pound sign, depending on your awareness of twitter, your musical training and your age).

The ID selector picks out the element with that ID, and only that element, to apply the style to. But what about the rule that sets all the H2 elements to light blue, namely this following? (Later, we'll learn about the #2EA9D3 code, but for now, trust us that it means light blue)

h2 {
   color: #2EA9D3;
}

The conflict is resolved by using the more specific rule, which is the one with the ID. You're probably not surprised at that.

CSS and Classes

One drawback of using an ID is that an ID is unique, so you can only style one element using an ID. Suppose we have various elements on our page that are important, and we want to style them differently from non-important elements. We could number them important1, important2, and so on, but that would be unbearably tedious. Instead, we want to describe a kind or category of element, which CSS calls a class of element.

An example will help. Suppose we have a grocery list. We're actually out of some critical items, so those have been given the class important:

  • milk
  • bread
  • apples
  • bananas
  • toilet paper
  • soap

Here's the source code:

<ul>
    <li class="important">milk
    <li class="important">bread
    <li>apples
    <li>bananas
    <li class="important">toilet paper
    <li>soap
</ul>

You can see that class works just like ID, in that you specify it as the value of an HTML attribute. Note that, just like ID, you as the author of the web page get to decide what the ID or class is. If you want to label them critical, or crit or whatever, that's your choice.

Now let's turn to the CSS side of things. The important items in the list above got styled using bold red using a CSS rule like this:

.important {
   color: red;
   font-weight: bold;
}

First, note the syntax of the selector. The name of the class is preceded by a dot or a period (a full stop if you're British). Otherwise, it works just like an ID: all the elements with that class get that style rule applied.

ID, Class, Abstraction and Modularity

In this discussion of ID and class, we can see the concepts of abstraction and modularity that we will return to many times in this course. First of all, the ID and class allows us to separate the structure and semantics of the page (which belong to HTML) from the presentation or style of the page (which belong to CSS). Separating different aspects is part of modularity. The name that we choose for the ID or class provides the semantic label, and the CSS rule then applies some style to those labelled element(s).

A related aspect of this modularity is how to choose the names. Suppose that instead of choosing important as the class name, we had chosen bold_red. It's about the same amount of typing, and it's much clearer as to what the class name does, right? However, trouble arises when we change the site. Suppose have a big website, with hundreds of pages and thousands of elements labeled important. Cleverly, you have one external CSS file that every page uses, so the CSS rule is just in one place, like this:

.boldred {
   color: red;
   font-weight: bold;
}

One day, the boss comes in and says I'm tired of the bold red; it's too scary. Change them all to medium maroon. You change the rule as follows:

.boldred {
   color: maroon;
   font-weight: medium;
}
and you're done in five minutes, with all the hundreds of pages instantly getting the new rule. The boss thinks you're a wizard. This shows the power of modularity — in this case, specifying something in one place instead of copy/pasting.

However, you now have a website where class="boldred" changes the contents to medium maroon. At best, that's confusing and misleading.

The better approach is to name things by what they mean rather than by what they do. That's the power of abstraction. It's not always possible to come up with a good name, but it's worth trying to. You can read more about good class names.

ID versus Class

Students often wonder about what the difference is between a class and an id, and when to use each one. The key is uniqueness: an id must be unique, while a class describes a kind/type/category of element.

For example, there might be many occurrences of these classes of elements:

  • an external link,
  • a figure caption,
  • a logo graphic

On the other hand, there is probably only one of the following elements per page, so these might have an id.

  • copyright statement
  • login/logout box
  • help button

With ID and class as tools, we can create as many hooks for styling as we want. In principle, every single element could have its own ID, and we could give it a custom style. However, that would be tedious and confusing. There's a better way, which we turn to now.

Descendant Selectors

A descendant selector creates a style rule where the elements are chosen based on where they are in the hierarchy of the page. Remember that an HTML document can be modeled as a tree. At the root is the <html> element, with all other elements as descendants, grouped in different families. Chrome's Inspect Element gives a very good depiction of the tree corresponding to the document.

Let's start with a motivating example. By default, hyperlinks are blue and underlined. That might be what you want for most of your page, but in the nav bar you want them to be, say, green and not underlined. Here's one way:

<nav>
  <ul>
    <li><a class="navlink" href="home.html">Home</a>
    <li><a class="navlink" href="about.html">About Us</a>
    <li><a class="navlink" href="contact.html">Contact Info</a>
  </ul>
</nav>

You can combine that with the following CSS rule:

.navlink {
    text-decoration: none;
    color: green;
    background-color: gray;
}

That's not too bad, but supposing that you also want to adjust other elements inside the NAV (say removing the bullets from the UL), you'd have to add more IDs and classes. You can see that this is tedious and annoying. You really want to say stuff inside the NAV is styled differently. For that, we can use descendant selectors, meaning that all descendants of an element are selected. (The UL is a child of the NAV, the LI elements are grandchildren, and the A elements are great-grandchildren.) Here's an example:

nav ul {
    list-style-type: none;
}

nav a {
    text-decoration: none;
    color: green;
    background-color: gray;
}

With a descendant selector, you give two selectors. The first is the ancestor and the second is the descendant. If you have A B, it means all elements that match B that are also descendants of elements that match A. (This can be generalized to three or more selectors, but that's uncommon.)

In the example above, we used two tags as the selectors, NAV UL and NAV A, but the selectors don't have to be tags. Either selector could be any one of the three basic selectors we know: (1) tags, (2) ID, and (3) class. For example:

#banner H1 {
    font-size: xx-large;  /* banner header is huge */
}

#copyright em {
   font-style: normal;  /* italic looks weird in tiny font */                
}
                
.appendix h2 {
   color: blue; /* make headers in appendices look different */
}

.appendix .important {
   color: black;  /* since it's in an appendix, don't use red */             
}

In practice, you wouldn't use an ID as the second selector, since an ID is already unique and doesn't gain any specificity by adding an ancestor.

To use descendant selectors effectively, it's important to keep the tree in your mind. Here is a graphic of a tree from an example you've seen before:

depiction of the DOM tree
Figure 2: Depiction of a Tree

Since the ancestry of an element is important with descendant selectors, debugging can require being able to easily see the ancestry of a particular element. Figure 3 shows the path of elements in which our a element is nested, as displayed by Chrome's Inspect Element window. This is an absolute path, starting from the root, html. When we specify the selector, we can use only parts of such a path, such as nav ul li a, or simply nav a.

depiction of the DOM tree to show nesting elements
Figure 3: Nested elements path as depicted in Inspect Element window.

Pseudo-selectors

There is one more kind of selector that will be important in this class, namely pseudo-selectors. We will look at how to format hyperlinks. As you know, hyperlinks are blue by default, but only when they haven't been visited. Once you've visited them, they turn purple (by default). You can control the style of both kind of link using CSS. You can also control what they look like when you hover over them, and in the moment of clicking on them. There are names for these four states:

  • a:link is an unvisited link
  • a:visited is, unsurprisingly, a visited link
  • a:hover is when the mouse is over the link
  • a:active is the moment when the link is clicked

Here's an example of some CSS to style all four states:

#hyperlink-example a:link {
    color: orange;
}                
                
#hyperlink-example a:visited {
    color: red;
}                
                
#hyperlink-example a:hover {
    border: 1px solid blue;
    font-size: 2em;                
}
                
#hyperlink-example a:active {
    border: 2px solid red;
    font-size: 2em;                
    font-weight: bold;                
}

Here's the example in action:

Note that there are ordering constraints among these pseudo-selector rules; we recommend specifying them in the order used above. You don't have to specify all of them (:active, for example, is pretty rare, and with touch screen devices, :hover is useless).

You can learn more and play with the specifications using this page: W3 Schools CSS Links.

Note that if you don't care about the state of the link, you can specify the appearance just using the A tag:

#hyperlink-stateless a {
    color: green;
}                

Here's the stateless example in action:

Selector Summary

Let's summarize the kinds of selectors that we've learned:

  • tag , e.g., p, em, li, etc. Such a selector will apply to all elements of this kind in the document.
  • .classname, e.g., .important. Such a selector will apply to all elements that share the attribute class=classname.
  • tag.classname, e.g, h2.important. Such a selector will apply to the indicated elements with the attribute class=classname. We didn't learn this explicitly, but it's a straightforward variation on the classname idea.
  • #idName, e.g., #main, etc. Such a selector applies to the single element that has the attribute id=idName.
  • selector descendant-selector, e.g. nav a. This applies to all descendants of the selected kind that have the selected ancestor.
  • a:link, a:visited, a:hover and a:active. These pseudo-selectors allow you to style hyperlinks based on their state.

To better understand the different kinds of CSS selectors, refer to the code examples in W3Schools CSS Selectors' page.

More Selectors (OPTIONAL)

There are many more esoteric selectors, and you're welcome to learn them. The following material is optional, and you can stop here. Read on if you're curious.

Grouping Selectors

If you have a rule that you want to apply to several things, rather than copy/paste the rule (copy/paste is always bad for modularity), you can share the rule. Suppose you have three elements on the page with IDs of harry, ron, and hermione. If they all have different colors, but the same font, you could do:

#harry { color: red; }
#ron { color: green; }                
#hermione { color: blue; }                

#harry, #ron, #hermione {
   font-family: impact;
}

You can see that there's just one rule to specify the font family for all three. All you have to do is list all the selectors, separated by commas. The selectors can be tags, classes, ids, even descendant selectors, in any order.

More Pseudo-Selectors

Pseudo-selectors come in two flavors: pseudo-classes and pseudo-elements.

  • A pseudo-class differentiates among an element’s different states or types. Examples of using states of an element are: information about link states: :hover, :visited, :active, about form inputs states: :checked, :disabled. Examples of using the type of an element are structural pseudo-classes such as :first-child [see example], :nth-child(odd) [see example], :nth-of-type(n) [see example]. Finally, in CSS3, there is a new pseudo-class known as :not, which negates a rule for the selected element (that is, the rule will apply to all other elements that are not selected). See example.
  • A pseudo-element provides access to an element’s subpart, which includes those pseudo-elements that select portions of text nodes, for instance, :first-line [see example] or :first-letter [see example].

In CSS3, to differentitate between pseudo-classes and pseudo-elements, the syntax to refer to them has changed. An element is referred with a double colon. You will see both examples on the Web, because they are still supported by browsers. Two new pseudo-elements that are also interesting are ::before and ::after which can be used to add content before or after an element. These are used when one wants to add icons in front or after certain elements, see example.

Chrome Inspector

Why Are We Choosing Chrome?

The default browser we will use in this course is Google Chrome. This means that all your assignments should first work well on Chrome and only if you desire, you can make changes to make things look the same on the other browsers. For your project, once you have everything working on Chrome, you might consider adjusting the CSS rules to fix problems on the other browsers such as Firefox, Safari and Internet Explorer.

The reason for choosing Chrome is that it runs on both MacIntosh and Windows computers, so it is neutral between those two operating systems. Furthermore, it is the most popular browser on the web, according to W3School's browser use statistics. Statistics from the Wikipedia article are a bit different from those of W3Schools, but both agree on the dominance of Chrome.

Developer Tools

All browsers have tools to help developers understand how their HTML, CSS, and Javascript code is being interpreted by the browser. In these notes you will become familiar with Chrome's developer tools, most importantly the Inspect Element window. In the future, we will also talk about how to use the Console to debug Javascript applications.

You can access the Elements window in several ways; choose one that you are comfortable with:

  • Using the mouse (or trackpad): right-click and choose Inspect Element on the drop-down menu.
  • Using the menu: View | Developer | Developer Tools
  • Using the keyboard:
    • Mac: Cmd + Opt + I
    • Windows: Ctrl + Shift + I

    Note that that's the letter I, as in Inspector.

A new window will open at the bottom of your current web page. This window is usually docked in this position, but you can use the docking icon dock icon to dock/undock it from the main window. Figure 1 shows the complete screenshot of a web page and the developer tools at the bottom.

screenshot of chrome inspect element
Figure 1: Screenshot of a page and the Inspect Element window.

The Elements window and the Web page

The first thing to notice in the Elements window is that it is divided in two panes. On the left side we see a tree representation of the nested structure of the HTML document (similar to that of folders and files in programs such as Finder (Mac) or Windows Explorer). On the right side there is a series of tabs, opened on Styles, showing what styles are applied to the selected element and how the browser has calculated the box that contains the element.

By selecting an element in the tree representation and hovering the mouse over it, one can see how the corresponding area in the Web page is highlighted in blue, also showing a little yellow box with the width x height dimensions of the element's content box. In Figure 1, we notice in the upper part that the whole document is highlighted, because we have selected the <html> element (in the Elements window).

Spend a few minutes navigating the document tree and highlighting different tags, to see the corresponding box on the Web page.

Your Exploration Task

The Chrome Inspector is a very useful tool, but it takes a little practice to be comfortable with it. Please spend a few minutes on the following exploration, because it'll help get you started using it. We'll do more practice in class and in lab.

  1. Vist the HTML file wellesley-no-css.html.
  2. Open the Inspect Element window and start exploring the document tree. Notice how elements are nested in each other, e.g., <ul> is nested in <nav>, <li>'s are nested in <ul>, <a> is nested in <li>, etc.
  3. Click on one of the elements, for example the <a> tag for Hillary Clinton and then inspect what you see in the Styles pane. Because you haven't specified your own style for the page, the listed styles are the ones provided by the browser (the user agent). Figure 2 shows the default style for <a>. For the moment, don't worry about the complicated name of the selector (a:-webkit-any-link), simply think that it is the style for a. Also, notice how below the rule for a, the rules inherited from its ancestors: li and ul are shown.
screenshot default styles for selector a
Figure 2: Default styles provided by the browser for a.

You might be confused by styles such as color: -webkit-link, because the value is not a kind of color. The reason for this is that the browser keeps a table where every value such as -webkit-link is mapped to a real value. You can see the results of this mapping in the Computed tab, as shown in Figure 3.

screenshot computed styles for selector a
Figure 3: Computed styles for the selector a.

Notice how the color property has a real value now. Don't worry if you don't understand the rgb(85,26,139) value; it's a way to represent colors using numbers, which we will discuss a bit later in the course).

Things to try on your own

For the wellesley-no-css.html document (without CSS styling), explore the default styles for each element and look at what properties and values these styles have.

Here are some questions to ask yourself and figure out during the exploration:

  • Which elements have the property display and what kind of values does this property take?
  • What can you say about the elements that don't have a display property? (For such cases, look at the "Computed" tab as well.
  • Select the element h1 in the document tree, then hover with the mouse over the colored box (it has the words: margin, border, padding). What do you see in the web page as you perform this hovering? Repeat the same for the element ul.
  • Do you understand what the numbers in the box mean?
  • Resize your browser page, then click on the button reload browser button reload. Which numbers in the box changed?
  • Can you figure out the relation between the unit em and px, both used in the styles? Refer to the "Computed" tab for some help.
  • Select the element nav and then the element footer. What can you say about the selector or the rule?

Now that you have explored the default styles provided by the browser, you can explore what happens when you add a stylesheet. You can try wellesley-w-css.html

In a new browser window open this second HTML file and open "Inspect Element". Try to compare how the "Styles" pane looks for elements you have styled. For an example, see in Figure 4 the before-and-after comparison for the h1 element.

screenshot of defaults styles for h1 screenshot of user-defined styles for h1
Figure 4: Default styling for h1 (left) and user-defined styles (right).

More Questions

To answer the following questions, you might need to compare several elements from the unstyled and styled document.

  1. Has the box size for h1 changed? Explain how this is possible.
  2. Can you come up with the formula that calculates the entire box size that each element occupies in the page?
  3. Which are all the different ways that you can influence this box size through the stylesheet?

Box Model

Page layout involves placing page elements (such as text and graphics) where you choose on a page. In the past, page layout was done with special HTML tags, including tables. The modern approach is to separate the page layout from the page contents by using CSS. This has the advantage that you can have different layouts for different media (screens, printouts, cellphones) as well as keeping the HTML clean and uncluttered for those users who don't use the CSS, such as a blind person who uses screen reading software.

Boxes

To understand page layout, you first have to understand that, to a web browser, a web page is a series of boxes. The boxes have a width and height, and they get assembled (laid out) on the page, much the way Ben Franklin might have laid out the text and pictures in his newpaper.

Boxes come in two kinds: blocks and inline.

A block is something big like a paragraph or a <div>. Blocks are preceded and followed by line breaks, so Ben Franklin or the layout engine stacks them vertically on the page. (Normally, a block doesn't have anything to the left or right, though we will see some exceptions later.)

An inline element (box) is something like a word, where Ben Franklin or the layout engine fills up a line with as many as it can, then goes on to the next line, and so forth. You may be surprised to learn that <img> elements are inline, so that a line is filled with as many images as will fit before starting the next line. (That's why centering an image is tricky; we'll look at that a bit later.)

DIV and SPAN

The <div> element is the generic block element. A DIV can contain any other element, including other DIVs. You can nest DIVs as deep as you want. It has no semantics, but we can style it by using CSS (often adding an ID or a class to the element, to distinguish it from other DIVs). Because DIV is a generic container, we will often use it to structure our pages. It will feature in many of the examples below.

The <span> element is the generic inline element. As with DIV, span has no semantics, but we can style it using CSS, and, of course, we can add ID and class if we want.

A span can contain other inline elements, including other spans, but no inline element can contain a block element. That means you can put EM inside a P, but not vice versa. The browser may let you get away with it, but the validator won't.

Margins, Borders and Padding

The contents of a box can optionally be surrounded by a border. For example, the following CSS

p {
    border: 2px dashed red;
}

will put a 2 pixel dashed red line around the contents of each paragraph.

Padding is the distance between the contents of the box and the border. By default, it's zero, but if you'd like a little more room between your text and the border, you can increase it. Even if you don't have a border, padding can be used to increase the distance between the contents of your box and the contents of any neighboring boxes.

Margins are the distance between the borders and the next element. However, it's not quite as simple as that, because the margins for vertical elements sometimes collapse. Margin collapse means that if a box A has a bottom margin of X and is followed by box B with a top margin of Y, the two are max(X,Y) apart, not X+Y. That sounds weird, but it's usually what you want. If you specify that both have a margin of Z, they will be Z apart rather than 2*Z.

Example

Here's an example that does uses all these measures:

Now is the winter of our discontent, turned glorious summer by this sun of York.

Now is the time for all good men to come to the aid of their country.

Here's the CSS. Notice we use a descendant selector, so as not to modify every paragraph on the page.

.eg_box p {
   border: 1px solid orange;
   background-color: yellow;
   padding: 5px 2em;
   margin: 10px;
}

Again, we've used short-hand properties. With padding and margins, if you give one number, as we did with the margin, you get 10px on all four sides. If you give two numbers, as we did with the padding, the first one is the top and bottom, and the second is the left and right. If you give four numbers, you can specify all four sides, in the order top, right, bottom and left (clockwise from the top). So the following is equivalent:

.eg_box p {
   border: 1px solid orange;
   background-color: yellow;
   padding: 5px 2em 5px 2em;
   margin: 10px 10px 10px 10px;
}

Note that margin-collapse means that the two paragraphs are 10px apart, which is reasonable and easy to specify. So margin-collapse is usually a help rather than a hindrance.

Exercise 1

Look at this modifying boxes using Inspect Element. (Dummy text courtesy of lipsum.com.)

In the exercise, you'll notice that contents of the box, including the padding, acquire the background color, but the margins are always transparent. Thus, padding and margins, which seem to be interchangeable when there isn't a border, aren't the same if you have a background color.

You'll also notice some big differences between blocks and inline elements. Not only are the inline elements put together on a line, but a <span> can be broken up if it's too wide (certain inline elements, such as images, can't be broken up). Also, the width and height, and top and bottom margins of inline elements are completely ignored.

You are probably wondering how to set all these distances. There are CSS properties to control the thickness of each side of the box (margin, border, and padding) as well as the style of the border if there is a border. There are also shorthand forms that let you define things more compactly. Consult a good reference on CSS properties

Lengths and Units

Now that you've seen some CSS properties whose values are lengths, you'll want to know what values they can have. For example, we indented this paragraph by half an inch. It's the only indented paragraph in the site. We did it using the following code:

<p style="text-indent: 0.5in">Now that you've seen some CSS properties ...

You might guess that in means inches. To specify lengths effectively, you need to know the units that CSS uses. They come in several categories:

  • Ruler measures. Inches (in), centimeters (cm), and millimeters (mm).
  • Pixels. These measures are in pixels, so they're less flexible if the web page will be printed out onto paper, but they're useful on the web. This unit is specified using px.
  • Printer units. You probably know that font sizes are measured in points, as in a 12 point font. One point is equal to 1/72 of an inch, and is specified by using pt.
  • Font-relative units. These measures are proportional to the size of the font, so they are bigger if the font is bigger, and smaller if it's smaller. This is great because visually impaired people may increase the font size to much greater than you'd ever expect, and you'd like the web page lengths to scale appropriately. These are appropriate measures for, say, the distance between lines (called the leading, from strips of lead that were put between the rows of type back in the olden days of actual lead type). The two font-relative sizes are em and ex. The em measure is named for the width of the letter M in the current font, and in CSS is defined to be equal to the size of the font. The ex measure is named for the height of the letter x in the current font, and in CSS is usually about half the size of the font.
  • Percentages. These are best for elements whose size you want to specify relative to the size of the enclosing element or the window.

    If you want a paragraph to be three-fourths the width of the enclosing <div>, you can use code like the following:

    #content {
       width: 800px;
       margin-left: 100px;
    }
    
    #note {
       width: 75%;
       margin-left: 25%;
    }
    
    <div id="content">
       <p>Here's the usual contents of the page ...</p>
       ...
       <p id="note">And here is a narrow note on the right side.</p>
    </div>
    

    Look at the percentage example in action.

Images are Inline Elements

Pictures (image elements, produced by the <img> tag) are inline elements. This may seem odd, since images look so much like big box-like things, and therefore ought to be block elements, but they are (by default), inline elements. So, the browser treats them like big words. Here's an example:

Bonnie and Chester were enjoying a picnic on the grass. Suddenly the sky filled with dark clouds. Soon, it began to rain. When the lightning began, they decided to head for home.

Centering Content

Before we get to more complex stuff, let's look at centering content, particularly images, since that's a common desire among CS110 students. Let's start, though, with centering lines of text within a block. Here's an eye chart:

E
F P
T O Z
L P E D
P E C F D
E F D C Z P
F E L O P Z D

All we had to do was to use the CSS property text-align: center. (Note that we used an inline style sheet in the example code, just for brevity. In practice, we would probably add a class to this div and define it in an external style sheet).

Since images are just like big letters, the same trick will work with images:

grass
clouds rain lightning
home

Centering Text

You should almost never center lines of text in a paragraph (unless you're making lots of eye charts). You get ragged edges left and right, which looks ugly. Also, depending on the font, amount of text and the width of the region, the last line may be weirdly short (and centered). Here's a Tolkien quote:

Do not meddle in the affairs of wizards, for they are subtle and quick to anger.

You probably don't want that single word centered on the second line. But that can happen (and all-too-often does) when you center text and don't have complete control over browser-width, font-size, and the like.

Instead, what you probably want is to have normal, left-aligned text in a box that is itself centered. Let's see how to center boxes.

Centering a Block

To center a block, you have to give it a width that is smaller than its parent (which might be the <body>), and setting its left and right margins to be auto. Auto means to take the leftover space on the line and distribute it equally among the auto elements. If both margins are auto, the element is centered. Thus:

Do not meddle in the affairs of wizards, for they are subtle and quick to anger.

Here's the code that accomplishes that:

#outer_box_example {  width: 80%; border: 3px solid blue; }
#inner_box_example {  width: 70%; border: 2px solid red; margin: 0 auto; }

This makes the browser calculate the necessary margin for centering, and works even when the widths are in percentages. When the width is a percentage, it is calculated as a percent of its parent, not the whole window. So in this case, the inner box is 70 percent of the outer box, and the outer box is 80 percent of the area where this paragraph is. You'll notice that the outer one is not centered, though.

Centering Images

An alternative technique for centering images is to use the same margin trick that works for centering other block elements, such as the paragraph above. The difference is that <p> is already a block element, while <img> is inline. However, we can change an <img> element to be a block by using the display: block style. That is, to make an image that is centered, use a style sheet that makes the image display as a block, and sets the margin-left and margin-right to auto.

Buffy Summers Angel

Note that by making the <img> be block, they stack vertically, even without the <br> tags. If we had tried to use the text-align: center technique, the two pictures would have appeared next to each other on the line. (Of course, that may be what you want, in certain circumstances.)

You should consult this web reference on Centering Things in CSS.

Box Widths

Consider the following example of an overfull box. Look at the CSS for it. Why does the browser have a horizontal scroll bar? The box is 100% of the container, not 110%.

The solution to this mystery is that the width of a box is defined to be the width of its contents, not the width of the box. (If you think this is a stupid definition, you would find many who agree with you, but we're stuck with this definition.) Thus, if you define a box to be 100%, it had better not have any margin, border, or padding, or it will be overfull.

One way to avoid the creation of overfull boxes is to nest two boxes, set the width of the outer one, and then use the inner one to set the margins, border and padding. By default, the dimensions of the inner box will be determined by the outer one, which is just what you want. Here is an example of a full, not overfull box created with this idea.

Background Images

You have already seen the property background-image in a few examples. The background-image property will cover the screen area corresponding to that element. If the image is smaller than the element, the image will be repeated horizontally and vertically (like tiles on a floor), unless you say it shouldn't be repeated. This paragraph is put on a wooden background image by using the following CSS:

#bgimage {
    background: url("wood-texture.jpeg");
}

The header for this section also uses a background image. We make the image not-repeat and slide the text over by using some padding (not margin), like this:

#background_images {
    background: url("cs110.png") no-repeat;
    padding-left: 35px;
}

You can learn more and try it out at this page: W3 Schools background image.

Rounded Corners

CSS3 introduces a way to round the corners of your elements using CSS alone. Each corner is treated as a quarter ellipse, which is defined by a curve that is drawn between a point on the x-axis and a point on the y-axis, as shown in the left graph below. A quarter ellipse can be regular, which means the length along both axes is the same, or irregular, which means the length along each axis is different (see graph on the right).

quarter ellipse
A quarter ellipse made by the curve between lengths on the x and y axes.
example of rounded corners
A regular curve (left) has identical values on both axes; an irregular curve has different values on each axis.

CSS3 introduced the border-radius property to implement the rounded corners. Similar to the border property that can be specified by -top, -right, -bottom, and -left, we can specifiy the x and y values for each corner separately. Below is a concrete example:

div {
    border-top-left-radius: 20px; 
    border-top-right-radius: 20px; 
    border-bottom-right-radius: 20px; 
    border-bottom-left-radius: 20px;
}

If only one value has been specified, that means that both x and y are using the same radius. Otherwise, we will specify two values in every line. Clearly, if the radius is the same for all corners, we can simply write the rule as: {border-radius: 20px; }. Additionally, we can use the shorthand syntax to specify different values for x and y using this syntax: border-radius: { horizontal-radius / vertical-radius; }, where each side of the slash can contain between one and four values, as with the shorthand for regular curves.

We have grouped different uses of this rule in one single page of rounded corner examples. Use the "View Source" on the browser (or Inspect Element) to look at the syntax for every rule and what it achieves on the page.

Even more CSS

You can stop here; the following material is optional. There are some fun, eye-candy effects that you can do with CSS3, but none of it is necessary for a functional, nice-looking website.

Multiple Background Images

Here is the example of a page with one background image, which was generated with this CSS rule:

header {
  height: 640px;
  background: url('images/blue-sky.jpg') no-repeat;
}

To make things more interesting we can add other images on top of an existing background image, again, only using CSS3.

Here is a new page created by adding the bird on the blue sky from the previous example.

This is the CSS rule we used:

header {
  height: 640px;
  background: url('images/bird.png') no-repeat,
              url('images/blue-sky.jpg') no-repeat; 
}

Notice that we use a , to list all images that we want to appear in the background. The order in which the images appear in this list is very important. The image that needs to be behind everything else should be last in this list as well.

However, in order for the effect to look nice, the foreground images need to have transparent background themselves. Here is how our bird image looks like if you open it with a image processing tool:

image of a bird

The background property has multipe subproperties that are useful to create more interesting effects. For example, using background-position we can place our bird in any location over the blue sky. Here is the center bottom example.

We needed to add one line to our CSS rule:

header {
  height: 640px;
  background: url('images/bird.png') no-repeat, 
              url('images/blue-sky.jpg') no-repeat; 
  background-position: center bottom, 0% 0%;
}

Because there are two images, we specify the position for both of them. This property takes several values and you can play with them in this interactive example from the W3Schools.

Additionally, by using another property, background-size, we can compose scenes with multiple images, as shown in this example with many flying birds.

header {
  height: 640px;
  background: url('images/bird.png') no-repeat 5% 105%, 
              url('images/bird.png') no-repeat 20% 60%, 
              url('images/bird.png') no-repeat 40% 80%, 
              url('images/bird.png') no-repeat 60% 40%, 
              url('images/bird.png') no-repeat 70% 45%, 
              url('images/bird.png') no-repeat 60% 50%, 
              url('images/blue-sky.jpg') no-repeat 50% 50%; 
  background-size: auto, 10%, 10%, 5%, 5%, 5%,  auto;
}

The background-size property can also take values of different kinds. The values in % shown in our example, refer to the size of the parent element of the background, in this case <header>. Since its size is 960x650 pixels, a 10% image will show as 96x65 pixels. Finally, notice that in this example, we have added the background-position values to each image (after no-repeat). Each of the pairs shows the left and top coordinate for where the image is placed.

Page Layout

We strongly recommend that you read Chapter 11 of the Head First HTML and CSS book as a gentle explanation for this topic. The material in these notes comes from Chapters 11, 12, 13 of the book CSS The Missing Manual.

Introduction

As you have noticed so far, HTML displays content from top to bottom, with most elements stacked as blocks. Today, we will see how to use CSS to put elements everywhere in the page, in order to create more visually appealing pages.

Most web page designs on the web fall in one of the two types of layout: fixed-width or liquid.

Fixed-width design gives you more control over how your pages will look, but will cause inconvenience for users with small monitor devices (a lot of horizontal scrolling, which people dislike). Liquid designs, which grow or shink to fit a browser window, are better for users, but make things more difficult for you the designer.

  • A perfect example of a fixed-width layout is the NY Times website. Resize your page. Once your screen has become less than 970px, you'll see that the scrollbars will show up and the page doesn't change. Most websites on the web have a fixed width, usually under 1000px (with a common value of 960px).
  • A perfect example of a liquid layout is the new Google Maps website. Again, resize your browser to see how the page content shrinks or grows with your window size. This type of design makes the best use of available space, but you'll need to make sure that it looks well on all different device sizes. Our own website is also an example of fluid design. Resize the window to experience it.

How CSS layout works

Web page layout involves putting content into different regions of the page. In order to do this, the content needs to be in container tags such as: nav, header, section, footer, picture, aside, and the ubiquitous div. Keep in mind though that you don't need to use div if it's not called for. Elements that are displayed as blocks, such as ul, ol, and p can be also moved everywhere in the page.

Two Techniques for CSS Layout

There are two general techniques used for layout: floats and absolute positioning. Floats are by far the most used, as it allows the layout to be fluid. Also, with float layout, content never overlaps other content, so even if the layout isn't pretty, it's functional. With absolute positioning, you have the power and burden of complete control. We'll look at both in this reading.

To use float, you start with the normal layout of boxes stacked vertically on the page, but you can allow certain elements to move to the side and have other material flow around them. To do that, HTML elements have a property float, which will make the element float to either the left or the right side of the page (your choice). Of course, other material can't flow around it unless it is narrow enough, so we also have to consider the width of the element. We'll look at that, too.

Absolute positioning allows you to place an element anywhere on the page with pixel-like accuracy. To do so, CSS has a position property that you set to absolute, and then use additional properties like left and top to specify the location of the element. This technique doesn't go well with the fluid design, but is good for positioning things like logos, etc. that need always be in a certain place. Absolute positioning is sometimes used in a limited way as part of an overall layout that mostly uses float.

Layout Strategies

Web page layout with CSS is more of an art than science; there is no formula for marking up your HTML page or creating the CSS. CSS layout is something that you will learn through experience, learning the different CSS propertis, following tutorials, and practicing a lot. What follows in this section is a set of guidelines that can be useful as you start learning about this topic.

  1. Start with your content. Design starts with your content (headlines, text, links, photographs, etc.), not with colors, fonts, or icons. It is the page message that should dictate the design. For example, if the goal of a student organization page is to get more students to join, you can put a large photo of the members doing something fun or interesting, together with quotes from them. Then you use style to make them compelling.
  2. Mock up your design. Don't start your design with code, start with a drawing. Using a drawing program (Paint, Photoshop, Illustrator, etc.) gives you freedom to explore different colors, fonts, images, and positioning, without having to write code. This way you can experiment faster with many choices. If your page needs user interface elements such as buttons, tabs, etc. you can use the free stencil kit from Yahoo, together with Photoshop.
  3. Identify the boxes. Once you are satisfied with your mockup, you can start thinking about the HTML structure. Basically you need to identify which elements look like individual boxes, because they will have to be in container tags in your HTML.
  4. Remember background images. Very often, you can more easily place an image with the background-image property than the <img> tag. This is because you can put other information on top of this image. However, you should know that background images are not printed, thus, don't put important information (such as maps) as background.
  5. Layering elements. Tools like Photoshop use the notion of layers to float several things on top of each other. To do the same on a web page, there are two options: use the background-image property to put text on top of images, or use the position property to lay images or icons on top of text. You can't use float to make content overlap.
  6. Don't forget margins and paddings. Often, you might not need to use sophisticated CSS for layout. A good use of the margin and padding properties can take you really far (especially when combined with the background image property).

Float-based Layouts

In this section, we will show with different examples how to build float-based layouts. Such layouts make use of the float property to position elements side by side and create columns. You can also use float to create a wrapping effect. This is because the floated element is removed from the flow of the document and what comes after it moves up and wraps around the float. (Note: Your book has a very detailed description of what the flow of a document is.)

Floating an image

As you know, an image is an inline element. To remind you of that, look at this example and resize the browser page to see what happens to the images. You also can use Chrome's Inspect Element to notice that <img> is nested within the p.

Now, let us look at the same page after applying the following style rules:

  • Made the body a fixed width by specifying the width in pixels.
  • Made the body centered by specifying margin: auto; for it.
  • Made the images float to the right by specifying img { float: right; }.

Notice how the images are now strictly on the right side of the document, and the text of the paragraphs wrap around them. The only step that is necessary for this is the last step, but the others are nice, too.

Floating a div (or semantic container)

Let us now see what happens when we float a container element, such as a div, figure, footer, etc. Here is the unstyled page, where we put the img inside the figure container. Notice how this time the images are not inline anymore.

If we apply now the floating property to the figure, element, we get the same effect as before, with the distinction that figure already has some default values for the margin assigned by the browser.

The float property takes only three values: left, right, and none. The last value is used when you want to prevent an element from floating. (There is no float: center property; we discussed centering in the reading on the box model.)

Now that we learned about the property float, let's see how it can be used to create a layout with columns.

Two-column layout

In order to have a two-column layout, we need to have two containers which can meaningfully stand next to each other; for example, a section and an aside. Let's add first a aside element to our Hunger Games example. The content will be a header and a list with short lines:

<aside>
    <h3>Characters</h3>
    <ul>
        <li>Katniss Everdeen</li>
        <li>Peeta Mellark</li>
        <li>Gale Hawthorne</li>
        <li>Primrose Everdeen</li>
        <li>Haymitch Abernathy</li>
    </ul>
</aside>

Then, we apply some minimal style to this element, in order to float on the left side, as shown below, getting this new version.

aside {
    float: left;
    border: 1px black solid;
    padding: 5px;
}

Important Note: The width and height of every floated container element depends on the amount of content (text or images) inside the container. This is the shrink-to-fit model. If the list above had had some very long items, so that the list was as wide as the page, the float property would have no effect.

As you see from the screenshot below, the aside box size can be calculated based on the values for margin, border, padding, and content size (e.g. the width: 185px = 0 + 1px + 5px + 173px + 5px + 1px + 0). The 173px comes from the how wide the text in the header and list are. Again, if you have a big paragraph of text in your floated element, it's likely to be as wide as its container, and the floating will have no effect.

screenshot of sidebar box screenshot of sidebar box
The size of a floated container box depends on its content and styling.

If you want the size of the column to be something you desire (e.g., instead of width of 185px, to be 200px), you can do the reverse calculation to find what the width of the content should be, using a simple equation. For example, 200px = 0 + 2*1px + 2*5px + Xpx. Solving this, we get width=188px. This means that in our rule we should set the width: 188px;, in order to get the real size of the column to 200px on the browser page.

One could do the same for the height, but this is not very useful, because if the adjacent column gets more content, we'll need to recalculate.

Now, to achieve our two-column effect, we simply add a margin to the non-floating element. Here, we add a margin to the section so that the aside floats next to it. Depending on whether the floating column would be on the left or the right side, we need to set margin-left or margin-right to a value slightly larger than the width of the floating column. Since the aside is 185px wide, a margin of 210px should look nice. Therefore, we add the following rule:

section {
    margin-left: 210px;
}

This is how the finished two-column layout looks: our two-column example.

Summary: The two-column layout

  1. Wrap each column in a container, for example, aside and section (or a div with an idattribute).
  2. Float one container (in our case, aside) either left or right.
  3. Set a desired width for the floated element.
  4. Add a margin (left or right, matching the floating side) to the fixed element.

Three-column layout

Going from a two-column layout to a three-column layout is a fairly straightforward extension. Can you think of the changes you will need to make to your HTML and CSS code? To challenge yourself, stop reading at this point and go and experiment with the code from the two-column layout (get the files from the links above). Then, check our solution. Here is a summary of the steps we performed:

  • Added a new aside element (before the section).
  • Added an ID attribute to each aside element.
  • Used these two new IDs as selectors in the CSS code (the rules are identical, with the exception of float.
  • Added margin-right: 210px; to the section rule, in order to allow space for the new floating element.

Important Note: When using this technique (known as positive margins), the floating elements need to be placed before the main content in the HTML file, otherwise, you will not get the desired effect.

Float Problems

Working with floating elements can often cause unexpected problems. In the following, we will describe two of them together with the solutions.

--- Optional Reading Starts here ---

Clearing Floats

We saw that one of the things that happens with floats is that other content wraps around them. Often that's what we want, but sometimes it isn't. A problem that occurs often is with the footer element of a page, when the main content is shorter than one of the floating columns. To illustrate this problem, we modified the Hunger Games example to show what happens with the footer. Here is a screen shot:

screenshot of problem with floating
The footer (copyright notice) has moved up, higher than the floating figure and the aside on the right (the District lists).

Fortunately, there is an easy fix for this problem. We add the property clear in the rule of the element we want to stay away from the floats, in our case, footer. What clear means is to move the cleared element down, below any floating elements. Like this:

footer {
  clear: both;
}

After making this change, the footer stays at the bottom of the page.

Containing Floats

Another problem occurs when a floating element contained within another element is larger than its container. This becomes obvious when the container has a background color or border. In our ongoing Hunger Games example, we changed the background color of the section element to olive, so that now you can see, in the screenshot below, that the floating element (the figure) had come out of its container (the section). It had always been outside its container, but we just hadn't noticed.

screenshot of problem with floating
The problem created by a floating element bigger than its container.

There are several solutions to this problem, but we will show the two simplest.

  1. Add an element at the bottom of the container, in order to use clear. In our solution using clear, we added a <br class="clear"> element before the end of the section and a CSS rule for it br.clear {clear: both;}.
  2. Use a dedicated CSS property for the container element, overflow: hidden;. Here is again solution using overflow hidden. While this CSS property works very well, its name can be confusing, since the effect is not to hide the overflow (the floated element that sticks out), but instead it enlarges the containing element so that the floated element no longer sticks out.

Positioning Elements on Page

At the beginning of these notes we mentioned that floats are the most used technique for designing layouts. However, there is another technique, positioning, which has its good uses in particular situations.

We achieve positioning of elements through the property position, which can take these values:

  • absolute
  • relative
  • fixed
  • static (this is the default value)

The values absolute and fixed are very similar in their syntax (though they create different effects) and more easy to understand. The value relative is a bit more tricky, because its meaning is not in par with how we use the word in everyday language. To explain these values, we will show in the following an example for each. You should look at the HTML and CSS files of each example to better understand what is going on.

position: absolute

We can use this style to set an element in a desired location in the page, by additionally specifying a horizontal and vertical position using the properties left, right, top, and bottom. These properties specify the distance (in pixels or some other units) from the (0,0) coordinates of some reference container. Usually, the reference container is the viewport (top-left corner of the browser viewing area).

To see this in action we have a modified version of our Hunger Games example, and we will try to position the figure to some other location, as shown in this styled version of the example. This effect was achieved with this CSS code:

figure {
  position: absolute;
  top: 350px;
  left: 500px;
  border: 1px black solid;
  padding: 3px;
}

Notice how the figure lays on top of the text. This is because by becoming absolute, the other elements are not aware of it anymore, so they cannot flow around it. Additionally, try to resize your browser window. The placement of the figure doesn't change.

position: relative

Suppose we want to put a caption on the figure, sitting on top of it, instead of below it. In this case, we will need to use the relative position. However to achieve this, we need to do two things:

  1. Declare which is the element relative to which this positioning is going to happen. This is the reference container that we mentioned in the previous section.
  2. Declare as absolute the element we want to position, and specify its coordinates relative to the reference container.

This new example, creates a caption over the figure with the following code:

figure {
  position: relative;
  border: 1px black solid;
  padding: 3px;
  width: 400px;
}
figcaption {
  position: absolute;
  bottom: 15px;
  left: 4px;
  right: 4px;
  color: yellow;
  background-color: black;
  opacity: 0.5;
  text-align: center;
  font-weight: 200%;
  padding: 5px;
}

So, the bottom and left lengths in the figcaption are measured from the upper left of the figure, not from the window.

position: fixed

This positioning is very similar to the absolute one, with the difference that the element remains in its position all the time, while the rest of the page scrolls up and down. You can think of it as positioning relative to the screen. It is useful for fixing navbars or sidebars in one position. See how the aside element remains fixed in our example, with the code below:

aside {
  position: fixed;
  top: 80px;
  border: 1px black solid;
  padding: 5px;
  width: 188px; /* this value will make sure the sidebar box will occupy 200px */
}

Computer Model

Computer Components

A computer is a complex electronic machine, but its operations can be understood sufficiently in terms of a few interconnected components:

  • The Central Processing Unit (used to be called the "brain" in the popular press). Since none of these words mean anything except the middle one, this is also called the processor. The processor is responsible for all the "intelligence" we associate with the computer. Its role is to follow a set of instructions written by the programmer and perform basic arithmetic calculations (like addition and number comparison).
  • The Memory Unit where the data and the instructions are temporarily stored.
  • The Input/Output Unit allows the processor to communicate with the outside world, such as output to monitors or input from keyboard.
  • The clock, a component that gives tempo (rhythm) to the operations. When all else is equal, the faster the clock, the faster the computer. Usually, all else is not equal, and the clock speed is more about marketing than computational speed.

The processor is further divided into two smaller components

  • The Arithmetic-Logic Unit (ALU) performs the basic arithmetic calculations (think of it as a very simple "calculator")
  • The Control Unit that follows the program's instructions and gives directions to the "calculator".

In the picture note that the components are connected through a set of wires called the bus.

computer model comprising processor, memory and I/O devices
A computer model showing the processor, memory, and I/O devices.

Watch and Learn

The article What's inside my Computer by Strickland, Jonathan, from HowStuffWorks.com, has videos that explain the internal parts of a computer.

The operations of any processor are as follows ad infinitum ("forever"):

  1. fetch instruction from memory
  2. decode the instruction. What is the processor supposed to do? Add? Subtract? Move some data to/from memory?
  3. execute the instruction. This may involve such things as telling the processor to add two numbers, getting some data from memory, storing some data to memory, or telling some I/O device to do something.
  4. REPEAT!

This is called the fetch/execute cycle. Note that the processor is so much faster than the I/O devices, that I/O doesn't appear prominently here. A modern processor is able to execute millions of instructions while waiting for an I/O device, even a fast device like the disk or the network.

The main point here is that the computer doesn't know how to do anything "automatically": there's always some program code (set of instructions) telling it how to do something.

The input/output unit is connected with the usual peripherals such as keyboard, mouse, the various "drives" (such as hard drives, floppy drives, zip drives, DVD drives, CDROM drives, etc), monitors, printers etc. So, the components and operations of a computer are remarkably simple. Complication enters only for performance reasons, but any computer that you are likely to see these days contains the above components.

Kinds of Memory

Looking at the picture above, you see a big yellow box labeled Memory, but you'll also see, if you look closely, hard drive attached to the bus. What's the difference? Does it matter?

Yes, it does. The memory we describe there is super-fast memory chips that are right on the circuit board, just a few inches from the processor, what is sometimes called RAM or Random Access Memory. The most important properties of RAM are

  • It's super fast, so it's almost fast enough to keep up with the processor, and
  • it's volatile, which means that the information in it is lost if the power is removed.

If you've ever lost a document you were working on using your computer because the power went out or your battery ran out, that's because the stuff you were working on was in volatile memory. The files that are saved on the hard drive weren't lost.

The hard drive of your computer is (usually) a spinning disk with magnetic coating that stores the zeros and ones of your files as a pattern of magnetization. The exact representation isn't important, but two properties of hard drives are crucial:

  • They are slow. Even though the disks spin really fast and they can read and write bits faster than you can blink your eyes, they are glacial compared to the speed of the RAM. They're at least a million times slower.
  • They are non-volatile or permanent. Removing the power from a hard drive doesn't lose any information, and when the power is restored, you can get the information back.

There are other kinds of drives, such as solid-state drives, but the same properties appear. These properties mean that your computer mostly works by copying information (both programs and data, such as your files) from long-term storage on the hard drive into fast memory in the RAM, and that's where it stays while the computer is running. But you should save your stuff in RAM to hard disk on occasion, in order to avoid losing your work should someone trip on your power cord and pull the plug, or your battery unexpectedly die.

Finally, the most recent technology (invented in the past 15 years) is the USB flash drive , which has become the ubiquitous choice for transferring information between devices.

Information Representation

How information is represented

Every description of a computer needs to explain how the computer handles information: numbers, text, pictures, sound, movies, instructions.

The computer is an electronic device. Each of its wires can either carry electric current or... not carry current. So, like a light switch, it understands only two states. It turns out that this is enough to make the whole idea work. In fact, any system that can represent at least two states can represent information. Take, for example, the Morse code that is used in telegraphy. Morse is a sound transmission system that can carry a short beep (represented by a dot) and a long beeeeeep (represented by a dash). Any letter or number can be represented by a combination of these two symbols. Click here to see a Morse translator.

Similarly with computers. To represent a number, we use the binary arithmetic system, not the decimal number system that we use in everyday life. In the binary system, any number can be represented using only two symbols, 0 and 1. (Morse is almost, but not quite (due to the pauses between letters) a binary system. A system closely related to Morse is used by computers to do data compression (more about this later). Here is how the binary numbers correspond to our decimal numbers:

DecimalBinary
00
11
210
311
4100
5101
6110
7111
81000
91001
101010
111011
121100
131101
141110
151111

And so on. Both systems are positional: a great idea that we owe to Arab mathematicians, because before them, counting in Roman was tough (DCCCLXXXII + CXVIII = M, you know...) and counting in Greek was almost impossible (omega pi beta + rho iota eta = alpha).

Positional means that the position of each symbol within the number determines its value. Thus, 32 is different from 23 because the 3 and the 2 are in different positions, and each position has a place value. You already know this, but you do it instinctively, and we are reminding you of this because we will do the same thing with binary numbrs.

For example, you know that the meaning of the number 1492 is:

1492 = 1*1000 + 4*100 + 9*10 + 2*1 = 1*103 + 4*102 + 9*101 + 2*10

Thus the meaning of every digit is defined by the power of 10 in that position.

Similarly, number 1101 in binary means 13 because

13 = 1*8 + 1*4 + 0*2 + 1*1 = 1*23 + 1*22 + 0*21 + 1*20

The numbers 8, 4, 2, 1 are, as you know, powers of 2, starting on the right and moving left: 1 = 20, 2 = 21, 4 = 21, and 8 = 23

The decimal system is also called "base 10" and the binary "base 2", because every digit in a number contributes to the whole based on the power of 10 (or power of 2) with which it is multiplied.

Of course, we can have positional systems on different bases, like base 12 (AKA "a dozen") and base 7 (AKA a week). Very soon in this course, we'll work with base sixteen.

Below is a form that can help you convert between bytes (8-bit binary numbers) and decimal numbers easily. Type in a decimal number and press enter or click elsewhere on the page to update the checkboxes. Or, click the checkboxes and watch the decimal number change. A checked box corresponds to a bit that is one. An unchecked box corresponds to a zero. Try creating the number 13 by clicking on the 8, 4, and 1 checkboxes. Play around with this to get comfortable with it.

Binary:

128 64 32 16 8 4 2 1

Decimal:

What's so grand about a positional system? Arithmetic calculations are much easier than in non-positional systems, Can you imagine what second grade would be like if you had to calculate that XLVIII + LXVII = CXV?

Here are some tutorial videos on binary numbers:

Fundamental Relationship

One of the key themes of this course is about representations. Computers represent lots of interesting things, such as colors, pictures, music, videos, as well as mundane things like numbers and text, or even complex things like programs. Ultimately, you know that, at the lowest level of all those representations, there are bits.

One of the important aspects of these binary representations is the relationship between the number of bits and the power of the representation. The more bits we have, the more stuff we can represent.

Let's be concrete for just a minute. You saw above that with one bit, you can number two things: the one labeled "zero" and the one labeled "one," because there are two possible patterns: {0, 1}. With two bits, you can number four things, because there are four possible patterns: { 00, 01, 10, 11 }. With three bits, you can number eight things. (Can you list the eight patterns? Take the four patterns of two bits and write them twice, once as 0xy and again as 1xy.) Thus, whenever we use an additional bit, we get twice as many patterns.

Here's a table of the relationship between the number of bits and the number of patterns:

Number of BitsNumber of Patterns
12
24
38
416
532
664
7128
8256
...
16≈ 65,000
...
24≈ 16 million
...
32≈ 4 billion
...
N2N

This fundamental relationship is important and is also unintuitive, because it is exponential. The last line of the table shows us the N bits yields 2N patterns. This is unintuitive because, if you double the number of bits, you don't get double the number of patterns, you get the square. For example, double 3 bits (8 patterns) to 6 bits, and you get 64 patterns.

We'll see this relationship come up in, for example, our discussion of indexed color, because the limits we place on the number of bits in the representation results in a limit on the number of colors. This is a key idea.

Text Representation

Text is represented with the so-called ASCII code. Years ago, the manufacturers of early computers decided to represent every possible character (visible or invisible, like the space or the newline) with a number. The result was (partially) the code you see below.

Part of the ASCII character set
Part of the ASCII character set table. To find the code for a particular character in the table, add its row number on the left (32, 48, etc.) to its column number on top. So, for example, capital A is represented by decimal number 64 + 1 or 65.

A more comprehensive ASCII table is the following, which includes control characters with their associated graphic symbols, and, for each character, its hexadecimal, decimal and binary codes:

The ASCII character set
The ASCII character set table. Click for bigger image.

For example the letter E has the ASCII code of 69 and a binary representation of 01000100. The 8 bits are depicted in groups of four, because four bits are used to represent a single digit in the hexadecimal system, that we will discuss later.

The first two rows of the table represent so-called control characters, characters that are not visible, such as backspace (BS), escape (ESC), CR (carriage return - an old word for enter), etc. If you are interested in all acronyms, the AsciiTable website explains them in detail.

Control Characters

You'll notice that the first table above starts with ASCII code 32, which is for the space character. (Yes, even the space character needs to be represented.) The actual ASCII system starts at 0, but the first 32 characters are "control" characters, because they were originally used to control the early printers. For example, the TAB character is ASCII code 9, the line feed character (which moved the paper up) is ASCII code 10, and the carriage return (which moved the print head back to the left edge of the paper) is ASCII code 13. Since those characters are not interesting in the context of this class, we've omitted them from the table.

Line Endings

If all we had to worry about was characters, text representation would be pretty straightforward. However, text is organized into lines, and for historical reasons, one of the subtle differences among Windows, Mac and Unix/Linux is how line endings are represented. In the olden days before Windows, Macs and Unix, the early teletype printers used two control characters at the end of each line: the carriage return character to move the print head back to the left, and the linefeed character to move the paper up by one line.

The Mac represents the end of a line with a carriage return character. Linux uses a line feed character. Windows uses both, just like the olden days.

Usually, when you transfer a text file from system to system, the FTP program (Fetch, WinSCP, or whatever) substitutes the appropriate line ending. The "text mode" of transfer says to make these substitutions; "binary mode" makes no substitutions and is more suitable for non-text files, such as images or programs. Note that HTML and CSS are both kinds of text. Most FTP programs have a "guess which mode" setting that usually works pretty well, but can occasionally make a mistake, which is why it's sometimes useful to know this obscure fact. It's also why copy/pasting between Mac and Windows often fails.

Unicode

The early ASCII system had space for 256 symbols, enough to represent all English characters, punctuation marks, numbers etc. It turns out that there are other languages on Earth besides English, (;-) and recent software is being written to accommodate those, too, via a much larger code called Unicode. We have already been using unicode when putting this tag in our HTML:

    <meta charset="utf-8" >

Your Head First HTML & CSS book talks about unicode on page 239.

Bits and Bytes

Groups of bits that are used to represent characters came to be known as a byte. Remember that a byte is 8 bits. That Wikipedia page also discusses the history of the word and the names for larger groups of bytes, such as

  • Kilobytes (kB), or 1000 bytes. About a quarter of a page of text.
  • Megabytes (MB), or 1000 kilobytes. About 250 small books worth of text.
  • Gigabytes (GB), which is 1000 MB. About the amount of text in a small library.

A note on the standard abbreviations

  • Uppercase B is used for bytes while lowercase b is used for bits. Network speeds, where bits go across a wire one at a time, are usually measured in bits per second, or bps. File sizes are always in bytes, hence kB or MB.
  • The abbreviation for kilo is a lowercase k, hence kB for kilobytes. The abbreviations for the other prefixes (mega, giga, tera, peta ...) are all uppercase: M, G, T, P ....

Historically, computer scientists have often used kilobyte to mean 1024 bytes, because 1024 is pretty close to 1000 and because bytes often come in chunks whose size is a power of 2, and 1024=210. For example, if you buy a 4 GB flash drive, it won't hold exactly 4 billion bytes, but a bit more because of this difference. Hard drives and network speeds, on the other hand, are usually measured in powers of 10 rather than powers of two. In practice, it rarely matters.

Computers these days come with huge amounts of storage space on the hard drive (often hundreds of GB), but they are usually able to process only a few GB of them at a time (their main memory or RAM). We will use these symbols often in future lectures.

SSI

Why use Server-Side Includes?

Very often in a website, there is repeated material on each page. For example, each of the lecture pages in this course has a navbar at the top that includes the links to the major components of the website.

You certainly could copy/paste the repeated items to each page, but that makes maintenance very difficult: if you decide to change the common content, you have to edit every page, and you have to make sure you don't miss any and that you edit them all in the same way. For example, adding a new section to your website that is accessible from the navbar would require changing every single page! For a small website, this is bad, but for a large website, it is completely unreasonable.

A solution is to break your page into pieces, each stored in a different file, and have the server cobble them together whenever it responds to a request for your web page. This technology is called Server Side Includes or SSI. Exactly how to use it depends on the server software. On the CS web server, we use Apache to serve web pages. For more detail, you can read the Apache tutorial on Server Side Includes.

Suppose we have three pages, A, B, and C, all of which should share a common header and footer, each of which is in a separate file. These shared pieces will be included into the main pages. Thus, we have five files, none of which is a complete page:

In the list above, there are two kinds of files:

  • .html This kind of file includes another file as part of itself. The .html files are the container files, so they have all the usual infrastructure: They start with a doctype element and have tags like html, head, and so forth.
  • .part This kind of file is included in another file. It's just a fragment of a web page, such as just the navbar or just the footer. It doesn't have a doctype element, thus, it is not a valid HTML document.

In the source code of the HTML files A, B, and C, we put a special marker, called a directive, that the server will look for and replace with the contents of the included files. The directive looks like an HTML comment, so that if the SSI doesn't happen for some reason, the directive won't otherwise mess up your code. Let's look at what page A's source code looks like:

<!--#include virtual="header.part" -->

<p>Here is some content that is unique to <strong>page A</strong> of the website.

<!--#include virtual="footer.part" -->

The text in quotes after the word virtual is a relative URL for the file to be included at that point in the main file.

Note that if you View Source on ssi/A.html, you won't see these directives. Instead, you'll see the included content. The server obeys the directives and constructs the page from the parts and sends it out, and the browser has no way of knowing what the original file was, or even that SSI was involved at all. SSI is completely invisible.

Important Note

In order for the server to know that it has to do some extra work in cases when the files contain directives, we must make the file executable. Files on the server can be readable, writable, executable, and any combination of these three operations. These are known as file permissions and can be set through the SFTP interface (CyberDuck, Fetch, WinSCP, FileZilla etc).

We will always have to set the execution bit on, in order for SSI directives to work. Figure 1 shows how the folder for our example looks like. All HTML files have an extra x value in their list of permissions. We will show in lab how you can do that for your files.

Note that it's the web server that does the work, so SSI will not work when viewing files on your local desktop.

Here is a copy of A.html as it appears on the server. If you view the source, you can see what the code looks like before the directives are included.

screenshot of how the file permissions look like
Figure 1: A screenshot of how the file permissions look like on the server.

Bugs

One common error is to put a space after the comment syntax:

  <!-- #include ... -->

Unfortunately, this is treated as an ordinary comment, not an SSI directive, so be sure you do it exactly like this:

  <!--#include virtual="relative/path/to/file.part" -->

Second, if you make a mistake in your SSI syntax or in the relative URL, you'll see something like the following in your main file, when you view it on the web:

  [an error occurred while processing this directive]

For an example of this, see the file C-broken.html, in which we intentionally put in a typo, changing the line

  <!--#include virtual="header.part" -->

to

  <!--#include virtual="jeader.part" -->
so that you can see such an error in action.

Finally, if you make a change to your .part file, you may not see any change when viewing the .html file in your browser. This is very confusing and frustrating: didn't you change that web page?!

This happens because the server told the browser that the .html file hadn't changed (which is true), and so the browser saved time by just showing you the copy in the cache, instead of re-downloading the .html file. On many browsers, you can tell the browser to ignore the cache and really reload the file by holding down the shift key while reloading the file (in a Mac: Shift + Command + R).

You also need to make sure that your .part file is accessible (readable by all) from the web.

Relative Paths

Just as with URLs, you should use relative paths in the virtual="path" part of the SSI directive, so that they will still work when you move your website to another server. (The server should be one that supports SSI.)

However, the issue of relative paths can be a little tricky. Suppose that the file harry.html uses SSI to include a file items/firebolt.part. Furthermore, the firebolt.part file in the items subdirectory has some code referring to Harry's friend ron.html. Is the URL for ron.html relative to the HTML file or the PART file?

The answer is that it's relative to the HTML file. This is because the relative linking is done by the browser, which is completely unaware of the use of SSI, since all the SSI magic happens on the server, before the browser even gets to see the page. SSI is like dynamic copy/paste, so the code in a part file is just the same as it would be in the HTML file.

Best Practice Advice

Overall, SSI is one of the right approaches to avoid redundancy in websites (there are others we won't cover). Done correctly, a visitor to your site will never know that you are using SSI; it's just the case that content that should be consistent from page to page (banner, nav bar, header, footer, and so forth) is indeed consistent.

However, SSI is often a pain for the people developing the website. The reason is that SSI is only done by the server. That means that if you have downloaded an HTML page from the server and are editing it locally on your desktop, and you view the local copy in the browser, all the SSI content will be missing. You won't see that banner, nav bar, and all that. If you view the source, you'll just see the comment. The layout of your page may be messed up because that content is missing.

So, what's the best thing to do? Our recommendation is the following. (For concreteness, assume you are editing fred.html and that page includes nav.part. )

  • When you edit fred.html, download both fred.html and nav.part.
  • Copy/paste the content of nav.part into the correct place in fred.html.
  • Do not accidentally edit the code you copied from nav.part. If you discover that that code needs editing, you have to realize that you are essentially simultaneously editing all the pages in your site. So, do the following:
    • Edit the copy in fred.html and test that it works.
    • When it does, copy the modified code to the nav.part file.
    • Upload the modified nav.part file to the server, and
    • Check that the modifications work in the other files that include nav.part.
    • If you are working in a team, notify your teammates of the change, since they will want to download the modified nav.part file to their own working copy.
  • When you're done with your modifications of fred.html, delete the copy of nav.part before uploading fred.html to the server. Otherwise, you'll end up with two copies of the content on that page!

Yes, this is a bit tedious, but hopefully you will rarely discover that the code from nav.part needs to be edited, so you'll only have the extra steps of copy/pasting and subsequently deleting.

Alternative Best Practice Advice

Once you've implemented SSI, an alternative to working on your files locally is to edit your files directly on the server. This way, when you're making edits, you can view your files live on the server, and the SSI will work. No copy/pasting necessary.

To do this in CyberDuck, connect to the server and locate the file you want to edit, right click it and choose "Edit With ... Atom."

The file will appear in Atom, but you'll be editing the version on the server. (Well, actually a local copy, but CyberDuck ensures that anytime you save the file, the local copy is immediately copied to the server.) You'll view the changed file using the usual http://cs.wellesley.edu/~username/ URL, not a file:/// URL.

Support

Since SSI is done by the server, using it depends on the server software. SSI is supported by Apache and lighthttpd, but not by IIS, which is Microsoft's web server software. Apache is currently the most widely used web server software, but your client's web hosting site may not use it.

Should this occur, you could try to replace the SSI code with JavaScript, but that may not be accessible for all users (for example, screen readers may disable JavaScript code). An alternative is to simply copy/paste the .part code in the .shtml, but that loses all of the advantages of using SSI. A last alternative is to use a more powerful and portable server-side scripting language, such as PHP, but that's outside the scope of this course.

SSI Recap

To do SSI, you must:

  • Put the duplicate code in the .part file (the one you'll be including in other files)
  • Put the directive in the .html files
  • Upload both files to the server
  • Make your HTML files executable
  • View the .html file. You may need to use shift+reload in your browser to ignore the cache when refreshing the page

Colors and Images

Building upon the idea of representation, we will discuss how images are represented in digital form. We'll work up to it, first starting with how color is represented (which is based on the physiology of the human eye), then looking at images as rectangular arrangements of spots of pure color. Finally, we'll calculate the file size of an image and discuss one way of compressing the file so that it is smaller and therefore faster to download. This compression is, in fact, a different representation of the information.

Standard Colors

In the present day, modern browsers support 140 color names. This means that we can use color names such as black, aqua, or chocolate as values for the CSS properties that except a color value, such as color, background-color, etc. Many years ago, browsers could only support 17 color names, known as standard colors: aqua, black, blue, fuchsia, gray, green, lime, maroon, navy, olive, orange, purple, red, silver, teal, white, and yellow. However, later that list was expanded with 123 more colors. W3Schools maintains a complete list of the 140 recognized color names. While you can achieve a lot by using only these named colors, very often you want something more specific from the color spectrum. It turns out that we can use numerical codes to refer to colors, because inside the computer, colors are represented by numbers. How? For that, we need to understand additive colors and color vision.

Additive (RGB) Colors and Color Vision

Human retinas happen to have rod-shaped cells that are sensitive to all light, and cone-shaped cells that come in three kinds: red-sensitive, green-sensitive, and blue-sensitive. Therefore, there are three (additive) primary colors: Red, Green and Blue or RGB. All visible colors are seen by exciting these three types of cells in various degrees. (For more information, consult these Wikipedia articles on additive color and color vision.)

Color monitors and TV sets use RGB to display all their colors, including yellow, chartreuse, you name it. So, every color is some amount of Red, some amount of Green, and some amount of Blue.

On computers, RGB color components are standardly defined on a scale from 0 to 255, which is 8 bits or 1 byte.

Play with the Color slider page to get a feel for this.

additive mix
An example of additive mixing.

Here is a list of examples:

  • Cornflower = 100 149 237
  • Forest Green = 34 139 34
  • Gold = 255 215 0
  • DodgerBlue = 30 144 255
  • Sienna = 160 82 45
  • HotPink = 255 105 180

We can use this knowledge about colors being represented as a mix of red, blue, and green when specifying color values in CSS. There are three ways to do this:

color: rgb(64,224,208);   /* three RGB numbers in the range 0-255 */
color: rgb(25%,88%,82%);  /* three RGB percentages */
color: #40E0D0;           /* three RGB numbers expressed as a hexadecimal triple */

The first two ways are self-explanatory, since they use decimal numbers and percentage values with which you are familiar. In the following, we will explain the meaning of the hexadecimal color codes such as #40E0D0. The # sign is used in this case to simply indicate that the sequence of digits and letters is in hexadecimal.

Hexadecimal

People use decimal (base 10), computers use binary (base 2), but programmers often use hexadecimal (base 16) for convenience.

Binary numerals get long very fast. It is not easy to remember 24 binary digits, but you can more easily remember 6 hexadecimal digits. Each hexadecimal digit represents exactly four binary digits (bits). (This is because 24=16.)

One way to understand hexadecimal is by analogy with decimal, but we're all so familiar with decimal numerals that our reflexes get in the way. (In fact, humans throughout history have used many different numeral systems; decimal is not sacrosanct.) So, we first need to break down decimal notation so that you can see the analogy with hexadecimal. For now, we'll stick with two-digit numerals, but the same ideas extend to any larger numbers.

Decimal notation works by organizing things into groups of ten, then counting the groups and the leftovers: Suppose you had a bunch of sticks on the ground and you bundled them all into groups of 10 with some left over (fewer than 10). Now, use a symbol to denote the number of bundles and another symbol to denote the number of sticks left over. You've just invented two-digit numbers in base 10.

Hexadecimal: Do the same thing with bundles of 16, and you've invented two-digit numbers in base 16. For example, if you had thirty-five sticks , they could be bundled into two groups of sixteen and three left over, so the hexadecimal notation is 23. Careful! That numeral isn't the decimal number twenty-three! It's still thirty-five sticks, but we write it down in hexadecimal as 23.

To distinguish a decimal numeral from a hexadecimal numeral, we use subscripts. So, to say that thirty-five sticks is written 23 in hexadecimal, we can write:

3510 = 2316

Both decimal and hexadecimal notations are based on place value. We say that 2316 means 3510 because it's a "2" in the sixteens place and "3" in the ones place, just like 3510 has a "3" in the tens place and a "5" in the ones place.

Let's take another example. Suppose we have 2610 sticks. That's one group of 16 and 10 left over. How do we write that number in hexadecimal? Is it 11016? That is, a "1" in the sixteens place followed by a "10" in the ones place? No; that would be confusing, since it would look like a three-digit numeral. We need a symbol that means ten. We can't use "10," since that's not a single symbol. Instead, we use "A"; that is, A16=1010. Similarly, "B" means 11, "C" means 12, "D" means 13, "E" means 14, and "F" means 15. We don't need any more symbols, because we can't have 16 things left over, since that would make another group of 16. The following table summarizes these correspondences and what we've done so far.

The correspondence between decimal numerals and hexadecimal numerals
Decimal 0 1 ... 9 10 11 12 13 14 15 16 17 18 ... 28 29 30 31 32 33 34 35 36
Hexadecimal 0 1 ... 9 A B C D E F 10 11 12 ... 1C 1D 1E 1F 20 21 22 23 24

To convert a big decimal number to hexadecimal, just divide. For example, 23010 divided by 16 is 1410 with a remainder of 610. Thus, the hexadecimal numeral is E616. To convert a hexadecimal number to decimal, just multiply: E616=E*16 + 6 = 14*16 + 6 = 230.

Exercise 1

Try the following conversions as an in-class exercise. You can use a calculator, you can ask your neighbors, anything you like.

Dec Hex Dec Hex
7
22
26
100
127
149
240
255

You can check your work with the following form:

Decimal Hexadecimal

Converting Hexadecimal to or from Binary

Now that we know both hexadecimal and binary, you can convert binary to hexadecimal (and vice versa). However, you would probably do so by converting the binary number to decimal and then the decimal number to hexadecimal. There's a better way, involving almost no arithmetic (or, rather, all the arithmetic is with one-digit numbers you can add in your head). Indeed, this technique is the reason that computer scientists like using hexadecimal. (Well, this and the fun of getting to spell words like ACE and DEADBEEF with hex digits.)

Example 1

Let's start with an example. Suppose you need to convert the following from binary to hexadecimal:

01010100 = ??16

What we're going to do is to take the bits in chunks of four bits, so to mark the chunks we'll insert a period in the middle of the number:

0101.0100 = ??16

Now, we just convert each chunk directly into hex. The first chunk, 0101, is just the number 5. The second chunk, 0100, is just the number 4. Those are already in hex, so we are done:

0101.0100 = 5416

(Try doing it via decimal, to check. The decimal value corresponding to both of these is 80+4=84.)

Example 2

Let's do another one, this time with slightly larger values:

10101100 = ??16

Again, take the bits in chunks of four bits:

1010.1100 = ??16

Now, we just convert each chunk directly into hex. The first chunk, 1010, is 8+2 or 1010, which is the digit A in hex. The second chunk, 1100, is 8+4 or 1210, which is the digit C in hex. So we are now done:

1010.1100 = AC16

(Again, check our work by doing it via decimal. The decimal value corresponding to both of these is 160+12=172.)

Explanation

Why does this work? Suppose we needed to convert 172 from decimal to hex: our first step would be to divide the number by 16. In binary, moving the binary point to the left by one place is equivalent to dividing by two, so moving the binary point four places is equivalent to dividing by 16. So when we put a period in the middle of the 8-bit binary number, it is exactly the same as dividing by 16. We then have the quotient to the left of the binary point, and the remainder to the right of the binary point. Just convert each to hex, and we are done.

Notice that the only arithmetic we have to do is converting each chunk of four bits to the equivalent hex digit. The mental arithmetic involved is limited: we know that (1) we are adding one-digit numbers, (2) at most four of them, and (3) the sum will always be less than 16.

Watch the rest of Prof. Kurmas from Grand Valley State University on binary numbers and hex numbers. This is a version he edited for us. You watched the first 5 minutes for last time; watch the rest for today.

Even better, here's a video with Tom Lehrer singing New Math. It's about 4 minutes long; you'll enjoy it.

Colors using Hexadecimal

We already know that every color in a computer is a combination of some amount of each of the three primary colors: red, green and blue. The amounts are always given in the same order: red, green, blue. The amounts are numbers from 0 to 25510, or, in hexadecimal, 00 to FF16. Each primary is expressed as a two-digit numeral in hexadecimal, using a leading zero if necessary so that the numeral is always two digits. Three pairs of hexadecimal digits completely specifies a color. Finally, the notation for a color always starts with a pound sign (#). For example, a color like (35, 230, 10) would be written #23E60A.

Exercise 2

Experiment with defining a color numerically. In the form below, enter a color value in the syntax #RRGGBB and press return/enter. The box will change its background color to display the entered color value.

Image Representation

Now that we know how to represent a color, we can represent images. You can think of an image as a rectangular 2D grid of spots of pure color, each represented as RRGGBB. A spot of pure color is called a pixel, short for picture element, the atom of a picture. Pixels are better seen if you blow up an image several times; here are some examples. Click on the picture to enlarge it.

A figure of a Scottish terrier as a set of pixels
A figure of a Scottish terrier as a set of pixels
Mona Lisa as a set of pixels, with enlargement of block of pixels
Mona Lisa as a set of pixels, with an enlargement of the pixels comprising one eye

Every image on the computer monitor is represented with pixels. The images on a web page are saved in files that, in addition to the image data, contain information on the size of the image, the set of colors used, the origin of the image, etc. Depending on how exactly this information is saved, we refer to them as image formats. GIF, JPEG, PNG, and BMP are some of the well-known image formats. We will talk more about image formats below. For now, we will focus on the number of pixels and the representation of each pixel, and consequently, the file size of the image.

We said above that the amount of each primary color is a number from 0 to 25510 or 00 to FF16. It is no coincidence that this is exactly one byte (8 bits). A byte is a convenient chunk of computer memory, so one byte was devoted to representing the amount of a single primary color. Thus, it takes 3 bytes (24 bits) to represent a single spot of pure color.

With 256 values for each primary, we have 256 x 256 x 256 = 16,777,216 colors. Humans can distinguish over 10 million colors, so 24-bit color is sufficient to represent more colors than humans can distinguish. All modern monitors use this so-called 24-bit color. Some old monitors used 16-bit or 8-bit color, which were relatively impoverished, being only able to represent 65,536 colors (for a 16-bit monitor) or 256 colors (for an 8-bit monitor). Of course, a black-and-white monitor can only represent two colors, which could be called 1-bit color. An example is the Scottish terrier picture, above.

Image size and download time

In an uncompressed file format, every pixel needs 24 bits (3 bytes) to be stored. Let's suppose you are going to take pictures of all your 30 class peers for a class website, using your iPhone4 camera. According to the phone specifications, its screen has 2592 x 1936 pixels, which amounts to about 5 million pixels, or 5MP (mega-pixels). Thus, if every pixel takes 3 bytes, and a photo with your camera has 5MP, to store the image you need 15MB (mega bytes). For all your peer photos, you will need 30 x 15MB = 450 MB.

Imagine now that you put all these photos online on your website, in one single page (using the attributes width and height to make them fit in one screen), and then you send the link to this page to your parents. They might have an average Internet connection (e.g. Verizon offers offers a 1-3 Mbs (mega bit per second) to non-FiOS subscribers).

The amount of time that it will take to load a page with all these pictures on your parent's computer can be calculated as below:

content size (450MB) x 8 bits/byte / 1Mbs = 3600 seconds or 1 hour.

If each of your photos have been only around 100KB instead (as we require in some of your homework assignments), then the amount of time to load all of them on the page would have been 24 seconds.

So, how do we get our images to be so small in size? There are two ways: resizing (decrease the number of pixels in the image by judicious cropping), and compressing (decreasing the necessary number of bits per pixel). We will discuss compression in the next section.

Compression

Short of making our images smaller (fewer pixels), what can we do to speed up the downloads? We can compress the files.

There are two classes of compression techniques:

  • lossless compression, where clever encoding allows the number of bytes to be reduced but where the original image can be perfectly reconstructed from the compressed form, and
  • lossy compression, where we discard less-important information in order to reduce the amount of information to be stored or transmitted.

We will look in detail at one kind of lossless compression, which is indexed color (GIF encoding), because it gives us a window into the kinds of ideas and techniques that matter in designing representations of information.

Indexed Color

The idea behind indexed color is that if a particular color is used many times in an image, we can create a "shorthand" for it. In fact, if we limit the number of colors, each one can be assigned a shorthand. What will be confusing is that the colors are, of course, represented as numerals and so are the shorthands! For example, instead of saying (for the umpteenth time), color #D619E0, we'll just say, for example, color number 5. This will only work, however, if the shorthands really are shorter. They are, and we'll see exactly how much.

One way to think about indexed color is that we are creating a "paint-by-numbers" picture. We choose:

  1. the numbered list of colors
  2. what color (number) each pixel is

Example: Two-color image

Imagine that a 300x500 picture uses only two colors, say red and yellow. Suppose we make up a table of colors (two entries) and then represent the image with an array of "color indexes," like a paint-by-numbers set.
  • What is the numbered list of colors? There are just two:
    indexcolor
    0#FF0000
    1#FFFF00
  • We then paint the picture using just two numbers, 0 and 1. A zero means a pixel is red, and a one means the pixel is yellow.
  • How many bits does it take to represent this image? Well, there are 300x500 or 150,000 pixels, but each one is just 1 bit, so it takes 150,000 bits or 150,000/8 = 18,750 bytes or about 18 kB. Compare that with the 450 kB (300 x 500 x 3 byte/pixel) of the uncompressed representation, and you can see this is much smaller. In fact, it's 1/24th the size, since each pixel takes 1 bit to represent rather than 24. It'll be 24 times faster to download.
  • What about that table of colors? That's called the color palette, by analogy with an artist's palette. That has to be represented too. Otherwise, the browser would know there were only two colors in the picture, but wouldn't know what colors they are. There are two entries in this palette, each of which is 3 bytes (24 bits), so add at least 6 more bytes to the representation.

You can see the general scheme at work: we create a table of all the colors used in the picture. The shorthand for a color is simply its index in the table. We will limit the table so that the shorthands will be at most 8 bits. Since the shorthands are all replacing 24-bit color specifications, the shorthand is at most one-third the size. In the example above, the shorthand is 1/24th the size.

Example: Four-color image

Let's continue with the example. What is the file size if the image uses 4 colors, say red, yellow, blue and lime? In that case, the table looks like this:

indexcolor
00#FF0000
01#FFFF00
10#0000FF
11#00FF00

As you can see, the shorthand is now two bits instead of one. Therefore, the 150,000 pixels require 300,000 bits or 300,000/8=37,500 bytes or about 37.5kB. Obviously, this is about twice the size of the previous example, since each shorthand is now twice as big. Nevertheless, it's still much smaller than the 450 kB uncompressed file.

What about the size of the palette? That's now twice as big, too. Four entries at 3 bytes each adds 12 bytes to the file size, which is a negligible increase to the 37.5 kB.

What's the pattern here? The number of colors in the original image determines the size of the palette, which determines the number of bits in each shorthand, which then determines the size of the file as a whole. The shorthand for a color is simply the binary numeral for the row that the color is in the table. For example, the color red in the last example was in row zero (00 in binary) and the color lime was in row 3 (11 in binary).

You can see that the number of bits required for each pixel is the key quantity. This quantity is called bits per pixel or "bpp." It's also often called "bit depth" so that the file size of an image is just width x height x bit depth, almost as if it were a physically 3D box.

Finally, we can state the rule:

The bit depth of an image must be large enough so that the number of rows in the table is enough for all the colors. If the bit depth is d, the number of rows in the table is 2d.

Here's the exact relationship, along with the size of a 300x500 image:

Mapping bit-depth to number of colors
bit-depthmax colorsfile size of 300x500 image
12 18kB
24 37kB
38 55kB
41673kB
53291kB
664110kB
7128128kB
8256147kB

Exercise 3

Consider an image that is 80 x 100 (pixels).

  • How many bytes are needed to represent this image if it's black and white? Don't forget to represent the color table.
  • How many bytes if the image uses 4 colors?
  • How many bytes if the image uses 16 colors?
  • How many bytes if the image uses 17 colors?

In summary, you can reduce your image file size by using fewer colors. Of course, this may reduce the quality of your image. It's a tradeoff.

Computing File Size

We've learned how indexed color works and how it affects file size. This is important not only for the theoretical understanding of why representations matter, but also for the practical usefulness of understanding how to reduce the sizes of your images. In this section, we'll review how to compute the approximate size of an indexed-color image. (Indexed color is one of the tricks used in GIF files, though GIF files use other tricks as well.) Why do we do this? Because it combines all the conceptual issues into one small calculation.

A key concept in the computation is the bit-depth of the image. Read on page 19 the definition of bit-depth. It's the number of bits necessary to represent the desired number of colors. Remember that the number of colors is 2d, where d is the bit depth. It's an exponential relationship. Adding just one bit to the bit-depth doubles the number of colors you can have.

Recall that the indexed-color representation comes in two parts:

  1. the pixels (represented by their shorthand values, each of size equal to the bit-depth), and
  2. the palette (in which the full-color definition is given for each shorthand).

Thus, our computation breaks down into two parts.

  1. The size for just the pixels is essentially the number of pixels, multiplied by the size of each. We divide by 8 because bit-depth is in bits but file sizes are expressed in bytes. Since a byte equals 8 bits, we divide by 8.

    width * height * bit_depth / 8

  2. The size for the palette is the number of colors multiplied by the 3 bytes needed to represent each color:

    num_colors * 3

To find the rough size of an image, we first determine the bit-depth, then we compute the file size using the two formulas above. (This is the rough size because, remember, we are omitting some fixed overhead and further compression techniques.) You can combine them into one formula:

(width * height * bit_depth) / 8 + (num_colors * 3)

Finally, because the file size will usually be large (thousands or millions of byte), we divide by 1000 or 1,000,000 to convert to kilobytes or megabytes, as appropriate.

We will continue to discuss file size calculations in lab and homework assignments.

Introduction To JavaScript

For diving deeper into JavaScript, please read Chapter 1 of the book Head First Javascript Programming.

Javascript Applications

So far we've learned two languages: HTML and CSS. Today, we start learning the third of the three languages taught in this course: JavaScript. We will just begin talking about it, so don't worry if you don't understand everything immediately.

JavaScript is a programming language for making dynamic web pages, i.e., pages that can interact with the user and vary each time they are loaded. Although the names are similar, JavaScript is not the same language as Java, which is the programming language used in CS111 (until Spring 2014).

Simple Javascript Examples

We will begin our investigation of JavaScript by presenting a series of simple but working examples. We'll show you the code, but you should not try to completely understand it at this point. Instead, you should read it, make some guesses as to what various things might mean, and try to get the gist of what is happening without worrying about all the details. Later, after we have explained some of the notation and its meaning, we can go back to these examples and understand them more fully.

(This is a little like trying to learn a foreign language by walking around the country, listening to the words people say and observing what they do. You'll miss a lot, especially at first, but it's way more interesting than trying to start by reading a dictionary and memorizing vocabulary and syntax.)

Example 1: Hello

Here, we gather data in the form of the user's name, then we compute a response string by gluing their name onto the end of a common greeting, and finally output the result with a popup window.


We would probably never do this greeting in a real website, but someone's name could be filled into a form, added to a roster, guest list or signup sheet, emailed to someone, ...

Experiment

Delete the part var name = in the first line and execute the code again. What happens? Can you explain it? What roles are name and response playing?

Example 2: Name Length

This is almost the same, but we tell them the length of their name.


Again, not useful in itself, but it's nice to know that we can find out the length of a string. For example, we can limit the length of people's posts in an application like a Facebook wall.

Experiment

  1. What is the result if you enter a full name, like Harry Potter. Is the length you get what you expected?
  2. Delete the part var aName = in the first line and execute the code again. Can you explain what happens this time? Open the View > Developer > Javascript Console menu item. Anything interesting there? (Ignore the complaint abour Google code prettify.)

Example 3: Weight Conversion

Here, we ask for a number and use it in a calculation.


Experiment

You probably saw a very long number as an answer. For example, the result for 130, is 59.090909090909086. It would be nice to round it off to the nearest integer. And you can. If you were to compute Math.round(59.090909090909086) you would get the result 59. Can you find a way to put the Math.round calculation in the code above, so that it gives you a rounded value in the alert window. (That's hard at this stage of your learning.)

Example 4: Homage to Monty Python and the Holy Grail

Here, we ask for the person's name, quest, and favorite color. We then modify the box below, which was created with the following HTML and CSS:

<div id="grail">
  Your name here
</div>
#grail {  
  border: 5px solid gray;
  color: gray;
  width: 50%;
}
Your name here

OK, here is the javascript code that will change the box above:

Experiment

Add at the bottom of the given code some other style property for the box. For example, try to set the padding to "10px". If you don't see the desired effect, check the Javascript Console. If there was an error in your code, it will show here in a message in red.

Javascript and HTML

Javascript, just like CSS, is a different language from HTML. You might remember that HTML is responsible for defining the structure of a document, CSS for defining its appearance, and Javascript for defining the behavior of a page. Similarly to the way CSS interacts with HTML through inline styles, document-level styles and an external stylesheet, Javascript has the same three ways, but with a different syntax.

  1. inline Javascript - In this case, the Javascript code is given as a value to the an attribute of the HTML element. Here is an example using some things we will learn today:

    Here is the code:

    <button id="greeter1" type="button" onclick="alert('hi there!');">Greet me</button>

    Notice the JS code in the onclick attribute; there are also other attributes where JS code can be put.

  2. document-level Javascript - In this case, the Javascript code will be entered within the tag <script>. Differently from CSS, where the <style> tag could be only included in the <head> part of the document, in Javascript you can put <script> either in the <head> or anywhere inside the the <body>. A good practice is to put the code just before the closing tag for body. Here is an example:

    <body>
      ...
      <button id="greeter2" type="button"">Greet me</button>
     ...
      <script>
        function sayHello() {
            alert('hello!!');
        }
    
        $("#greeter2").click(sayHello);
      </script>
    </body>
    

    In the preceding, you'll see that the button has no JavaScript code at all; the code is in the script tag. However, there's a slightly more elaborate mechanism for defining and attaching the code. We'll get to these later in the course.

  3. external Javascript - This is the most common way to have Javascript communicate with HTML (it's also good for modularity and website maintenance). The entire Javascript code that we put in the script element above would go in a separate file and we simply load it using an alternative form of the script tag. Here is an example:
    <script src="myJScode.js"> </script>

We'll be using all three ways in our examples, but like with CSS, if you were creating a larger website, you should avoid inline JS. You should use mostly external JS (when shared across pages) and document-level JS.

Learning the Language

In the following sections, we'll get a first look at various facets of the language. There's more to say about all of these, but this brief tour will help you see how these different aspects of the language fit together. After all, when you learn a natural language (e.g. French or Chinese), you don't try to learn all the verbs first, before tackling any of the nouns or adjectives.

Variables

Variables are just named storage locations for a program. We used them in the examples above to store stuff that we computed (such as weight in kg) or stuff that came from the user (such as their name or height). The technical name for stuff might be data or values.

You can put a value into a variable, using an assignment statement, like these examples:

    var name = "Harry Potter";
    var weight = 150;

Note that this use of the equals sign is very different from how it is used in mathematics. In math, the equals sign (=) is an assertion that two things have the same value.

In computer science, the equals sign means:
Put the value that you see on the right of the equals sign into the storage location that is mentioned on the left of the equal sign.

Because the equals sign doesn't mean equality, we often pronounce it differently. Instead of saying weight equals 150, we say weight gets 150, short for gets assigned the value.

After a variable has been assigned a value, the value can be retrieved and used just by giving the name of the variable. For example, the following two statements retrieve the values of name and weight, perform an operation on them, and then assign the new values to two new variables called len and kg.

    var len = name.length;
    var kg = weight/2.2;

We will return to the concept of variables in future lectures.

The alert() Function

The first few examples accomplished the reporting of the response by use of the alert() function. It looked like this:

      alert(response);

This built-in function will pop up a window that displays whatever value is supplied to the alert() function by placing it in the parentheses. In this case, it reported the value that was in the variable named response. In earlier examples, we saw alert() with an expression inside the parentheses. This expression is evaluated and then alert() reports the result.

Alerts are annoying in working code, but they are very useful when testing and developing code, because they stop the execution of the program until you acknowledge them:


Some terminology: A statement like alert("foo") is an example of a function call or function invocation, where alert is the name of a standard JavaScript function and the expression in parentheses (in this case, "foo") is the argument of (that is, input to) the function. We'll learn more about functions later, but knowing alert() is useful right away.

The console.log() Function

Very similar to alert() but much less annoying is console.log(). It's used in almost exactly the same way: you put a value (or a variable containing a value) into the parentheses, and that value gets reported. However, the difference is that alert() demands that the user acknowledge it, while console.log writes it to a hidden place that only web developers know about, and keeps going, so the user is not annoyed or delayed by the message.

The console is also where the browser writes error messages. It writes them there so that the muggles won't see them and worry about them. As of this writing, here's how you can find them:

  • Chrome: View > Developer > JavaScript Console. Or, use the keyboard shortcut: option-command-j
  • Firefox: Tools > Web Developer > Web Console. Or, use the keyboard shortcut: Control-shift-K on Winows, Command-shift-K on a Mac.
  • Safari: Develop > Show Error Console. Or, use the keyboard shortcut: option-command-C

Try it! Click the button below to execute those two console.log statements and then look for them in the console of your current browser.


We will use console.log and alert a lot as a way of getting some insight into what our code is doing and to help understand it and debug it. So it's worth becoming comfortable with finding and looking at the console.

JavaScript Comments

You should always add comments to your JavaScript code to explain its purpose. As shown in the example below, JavaScript supports two kinds of comments:

  1. A block comment starting with /* and ending with */ that may span several lines. (This is the same form as a CSS comment.)
  2. A line comment that starts with // and goes to the end of the line.
 <script>
                  
    /* (Block Comment) Pop up an alert box with a
      message making sure that you
    all are awake because at this time of day, you might be sleepy. 
    Of course, a lot of it depends on what you were doing last night...  */
    alert("Hey you there -- wake up!");

    // (Line Comment) The user must be awake if we reach this point!
    console.log("User has woken up"); 

</script>

In addition to explaining the code, we can use comments to comment out a line of code that we don't want to run (sometimes when we are debugging to find where the error lies).

Values and Expressions

JavaScript programs manipulate values. The two basic kinds of values we've seen today are:

  1. Numbers: These include both integers (e.g. 17, -42) and floating point numbers (e.g. 3.14159, -273.15).
  2. Strings: These are sequences of characters, which are written using matched pairs of the double quote character (") or the single quote character ('):
    "Harry Potter"
    'grail'
    

An expression is a JavaScript phrase that denotes a value. The simplest numeric expression is a number itself. We can also create more complex numeric expressions using the numeric operators +, -, *, / and %:

Expression Value
27 27
27 + 10 37
27 - 10 17
27 * 10 270
27 / 10 2.7
27 % 10 7

The % operator is the remainder or modulus operator. Its value is the remainder when the first number is divided by the second. Here is an example of when it can be used. An average size woman might be 64 inches tall. To find the number of feet, we divide 64 by 12 and round down, to get 5. To get the number of leftover inches, we divide 64 by 12 and take the remainder, using the % operator. That gives us the 4. The remainder operator is more useful than you might think. But don't worry about it; you can think of it as a weird kind of division.

Precedence

For the most part, JavaScript follows the algebraic precedence rules that you learned in school years ago.

  • Parenthesized expressions
  • Exponents (we won't use these much)
  • Multiplication and Division (and Remainder)
  • Addition and Subtraction

JavaScript follows these rules, so your prior experience will serve as a good guide. There are a few new operators that you'll learn, such as the % or remainder operator, which has, unsurprisingly, the same precedence as division.

Try to guess what the following will evaluate to:


Strings and Quotation Marks

Literal strings can be denoted by either single or double quotes, which gives you some flexibility about how to handle awkward situations such as quotation marks inside a string:

Expression Value
"Let's play Tag!" Let's play Tag!
'Not "it"!' Not "it"!

These examples show that you can put a single quote inside double quotes and a double quote inside single quotes.

Concatenation of Strings

The main operation on strings is the concatenation operator, +:

Expression Value
"CS" + "115" + " rocks!" CS115 rocks!
"Harry" + "Cho" HarryCho

We saw this many times in the examples, as we created our response text out of literal strings, values supplied by the user, and computations from them. Concatenation is also useful for splitting strings across multiple lines. Let's say we want to display a string that represents a table. If we try to fit it in one line, it may look something like:

  alert("id,name,age,height(ft),0,Amy,5,4,1,Ben,9,6,2,Cindy,5,5");

With all of those numbers, it can be hard to parse the information when reading the code. Unfortunately, we can't jump to the next line in the middle of a string, but we can use concatenation:

  alert("id,name,age,height(ft)," +
        "0,Amy,5,4," +
        "1,Ben,9,6," +
        "2,Cindy,5,5");

The parseInt() and parseFloat() Functions

We'll see that there are many situations where it's necessary to convert from a string of digits to numbers. The parseInt() and parseFloat() functions are used for this purpose. The first one is used with integer numbers and the second one with numbers with a fractional part (after the decimal point).

The function takes an (optional) second parameter that says what number base to use. We'll typically use 10 for decimal numbers.

Expression Value
parseInt("243",10) 243
parseInt("cs115",10) NaN (Not a Number)
parseInt("3.141",10) 3
parseFloat("3.141") 3.141

The second argument to parseInt is the radix or base that you want to use. It can be 10 for decimal number, 16 for hexadecimal numbers and 8 for octal numbers (base 8). It's a good idea to supply this value, to avoid JavaScript inadvertently doing the wrong thing.

You can test any of the above expressions here:


The prompt() Function

Like alert(), invoking the prompt() function pops up a small window, but (1) it also allows the user to type in a string and (2) the string entered by the user is returned as the value of invoking the prompt() function.

For example, the following statement prompts the user for a first name and then stores it in a variable.


Note

The prompt() method is not the best way to get input in Javascript but it is OK for now. Better ways are to use HTML forms, or the jQuery library, but we can ignore it for now.

Default values

The first argument of the prompt() function is displayed above the input area of the prompt box. The prompt() function takes an optional second argument that, if supplied, is used as a default value for the input area. For example:


Using a default value makes it easier on the user when the default is right, but allows him or her to correct (override) the value when it's wrong.

Values from prompt()

The result of invoking the prompt() function is always a string, NOT a number, even if it's all digits, so it's necessary to use parseInt() or parseFloat() to convert sequences of digits to numbers. Compare the following two examples:

In this first example, we just use the + operator on the strings returned by prompt():


However, in this example, we first convert the strings into numbers (a float for the first, and an integer for the second), then apply the + operator:


Note that if we never need the strings a and b, we can take the value of prompt and immediately convert it to a number using parseInt, so the second example can be written more succinctly like this:


You have already learned a lot of JavaScript. For diving deeper, please read Chapter 1 of the book Head First Javascript Programming.

JavaScript Conditionals, Part 1

Decisions, decisions, decisions ...

So far, the Javascript code we have seen has been executed unconditionally. When we wrote a sequence of statements, those statements were executed one after another, in order.

Many programming tasks, however, require conditional control, that is, the ability to react differently based upon some condition. For example, consider the task of assigning students' letter grades. Depending upon what the student's average is, a different letter grade must be assigned (e.g., 93 to 100 is an A, 86 to 93 is a A-, etc.). In this lesson, you will be introduced to booleans, truth values that represent a decision, and to the if statement, which performs conditional execution based on a boolean value. Based upon some condition, an if statement can choose among alternative sequences of code to execute, or even choose to execute no code at all.

Some examples, just to get us warmed up:

The following code asks a yes/no question ("ok" and "cancel") and does something on "yes":


The following code asks the same yes/no question and does something either way:


Those examples both used the confirm() function, which is like prompt() except that it returns a boolean value, namely either true or false.

Boolean Values

Before today, the JavaScript values we have seen are numbers and strings.

Today we meet the logical values true and false. These two values are called booleans. They are named after George Boole, a 19th century English mathematician who developed an algebraic framework for reasoning about the manipulation of truth values.

A boolean expression is any expression whose value is a boolean value. The simplest boolean expressions are the boolean literals true and false, which can be written directly in a JavaScript program. (They're not strings, so don't put them in quotation marks.) However, in a program, it is more typical for boolean values to be generated as the result of comparisons or other operations.

For example, relational operators on numbers produce boolean values. Put a number into the box below and click the "evaluate all!" button to see the boolean outcomes.

Expression Value Notes
num the meaning of the comparison in the first column
num < 50 less than
num <= 23 less than or equal to
num == 57 equal to (== tests equality, but = performs assignment!)
num != 17 not equal to
num > 110 greater than
num >= 42 greater than or equal to

Here are some examples of boolean expressions involving strings. Again, type a string into the box below (or use the default) and click the "Evaluate all!" button.

Expression Value Notes
str additional info about the comparison
str == "CS115 rocks!" == also tests equality of strings
str != "Grover" != also tests inequality on strings
str <= "CS111 is cool!" Strings are compared lexicographically (in dictionary order)
str > "CS24 isn't a course" Careful! Numbers in strings are also treated lexicographically.
str.length == 12 s.length returns the number of characters in s
str.indexOf("115") == 2 s1.indexOf(s2) returns the first (0-based) index of s2 in s1
str.indexOf("Rocks") == -1 indexOf returns -1 if string isn't found
str.charAt(1) == "S" s.charAt(i) returns the character at (0-based) index i in s
(In JS, a character is just a one-character string.)

if Statements

Conditional execution refers to the ability to execute a statement or sequence of statements only if some condition holds. The simplest form of conditional statement involves only one possible action. For example, displaying a message when the value of a variable is "Grover". However, conditional execution can also involve alternatives based on the same or related conditions. For example, we might want to display one message if the variable value is "Grover" and another message if it isn't. This type of conditional execution in JavaScript is performed using if statements.

The following example uses an if statement to greet Grover specially. Let's say we have gotten the name of the visitor stored in a variable first_name. The symbol == is used in JavaScript to test for equality (remember, just one = is for assignments!).


The following example uses the other form of an if statement to greet Grover and to be a bit hostile to everyone else.


In the first example, an alert box is displayed only if the condition (first_name == "Grover") holds. If the condition does not hold, then nothing special happens: the next JavaScript statement (if there is one) is evaluated.

The second example includes an else case which specifies the action to be taken when the condition does not hold (i.e., first_name is not equal to "Grover").

In an if-else statement, exactly one of the two actions will be executed.

In general, an if statement looks like this:

    if (BOOLEAN_EXPRESSION) {   // This is called the "test expression"
        STATEMENTS_IF_TRUE      // This is called the "then arm" or "then branch"
    } else {
        STATEMENTS_IF_FALSE     // This is called the "else arm" or "else branch"
    }

The else part is optional.

Try an example here, testing whether a number is positive.


The test in an if statement can be any boolean expression, that is, any expression that evaluates to either true or false.

Exercise 1

Add an else case to the if statement so that it displays an appropriate message in the event that the number is not positive. Test your modified page on various inputs and list the results. What will be displayed when the number is 0?


Gotchas

  • The parentheses around the test expression in an if statement are mandatory. So you cannot write the following:
    if input_num > 0 { // missing required parens for test expression
         alert("the number is positive");
    }
    
  • When there is only one statement in an arm of the conditional, the braces are optional. For example, the following is legal:
    if (input_num > 0) 
         alert("the number is positive"); // No braces for then arm
    

    However, we recommend that you always use braces to avoid bugs that come from adding more statements to the then arm.

JavaScript Conditionals, Part 2

Logical Operators

Boolean values can be tranformed and combined via three logical operators:

  1. ! (pronounced "not") is a unary (one-argument) operator that negates a boolean value: (! true) is false and (! false) is true. If sunny is a variable that contains a boolean value, you might use the not operator like this:
    var hot = true; 
    var sunny = true;
    if( ! sunny ) {
      alert("bring an umbrella");
      }
    
  2. && (pronounced "and") is an infix binary (two-argument) operator that returns true if and only if both arguments are true; otherwise it returns false. If sunny and hot are variables that contain boolean values, you might use the and operator like this:
    // assume you have already assigned values to sunny and hot
    if( sunny && hot ) {
      alert("wear a hat");
      }
    
  3. || (pronounced "or") is an infix binary (two-argument) operator that returns true if and only if at least one of its arguments is true; otherwise it returns false. If cold and windy are variables that contain boolean values, you might use the or operator like this:
    // assume you already have assigned values to cold and windy
    if( cold || windy ) {
      alert("wear a coat!");
      }
    

The meaning of the three logical operators is summarized by the following tables, where inputs are shown in blue like this and outputs are shown in red like this:

Negation (not) Conjunction (and) Disjunction (or)
  true false
! false true
&& true false
true true false
false false false
|| true false
true true true
false true false

Here are some examples of these operators in action. Type a numeric value into the box and click the Evaluate all! button to see the outcome.

Expression Value Notes
x
(5 <= x) && (x <= 20) x is between 5 and 20 (inclusive)
(x < 10) || (x > 25) x is not between 10 and 25 (inclusive)
!((15 <= x) && (x <= 30)) x is not between 15 and 30 (inclusive)

One way to think about these conditionals on numbers is by using the number line, where && means intersection. This is because both conditions have to be true, which is when the regions overlap. For example, consider modeling the expression:

(X >= 5) && (X <= 30)

x>=5 and x<=30 using the number line

Gotchas

  • To test whether b is between a and c (inclusive), in JavaScript you write (a <= b) && (b <= c). Unlike in mathematics, the JavaScript expression a <= b <= c does not have the same meaning. Why? Consider the evaluation of the following example:
    7 < 3 < 10      // You might think this expression is false, but it's true. Why?
    => (7 < 3) < 10 // Relational operator associates to the left
    => false < 10   // (7 < 3) is false
    => 0 < 10       // In a numerical context, false is treated as 0, true is treated as 1
    => true         // (0 < 10) is true!
    
  • ! has a higher precedence than &&, which has a higher precedence than ||. For example:

    ! true && false is parsed as (! true) && false (which evaluates to false)
    and not !(true && false) (which evaluates to true)

    Although && and || have a lower precedence than comparison operators, ! has a higher precedence. So ! 2 < -1 evaluates as (! 2) < -1 (whose value is false) and not ! (2 < -1) (whose value is true).

    Moral: Use explicit parentheses if you have any questions about operator precedence!

Exercise 2

Suppose that CS110 lectures are held between 8:30am and 12:20pm. Suppose that hour denotes the hour in military time (in the range 0 - 23) and min denotes the minute (in the range 0 - 59). Our goal is to write a single boolean expression involving hour and min that displays an alert box with true for times during CS110 lectures and false for other times.

  1. It seems reasonable to think of this as an and operation: the time is equal to or after 8:30 and before or equal to 12:20. But the following attempt does not work. Why? Sketch the number line regions corresponding to these expressions. List some times for which the code gives an incorrect result.


  2. Fix the boolean expression in the above alert so that it works.
  3. Another approach for comparing times is to keep track of time in total minutes since the beginning of the day. Based on this idea, flesh out the following skeleton so that it works:


.

Cascading if Statements

In its simplest form, an if statement can decide whether or not to execute a sequence of statements. For example, in one of our first examples of an if statement, repeated here, the code will either display a message on the condition that the name is "Grover", or otherwise it will do nothing at all.

if (first_name == "Grover") {
    alert("Hello Grover, great to see you!");
}

Using an else case, an if statement can decide between two alternative sections of code, as in the example where a different message is displayed for "Grover" and any other name:

if (first_name == "Grover") {
    alert("Hello Grover, great to see you!");
} else {
    alert("Who the heck is " + first_name + "?");
}

There are situations, however, in which more than two alternatives must be considered. For example, suppose you were to write code for assigning letter grades in a class based on the student's final class average.

    if (grade >= 90) {
        letterGrade = "A";
    } else if (grade >= 80) {
        letterGrade = "B";
    } else if (grade >= 70) {
        letterGrade = "C";
    } else if (grade >= 60) {
        letterGrade = "D";
    } else {
        letterGrade = "F";
    }

We call this a cascading if statement. The term cascading refers to the way that control cascades down the statement like water down a multi-tiered waterfall. The topmost test is evaluated first, in this case (grade >= 90). If this test succeeds, the corresponding statements are executed and the whole statement is done. If not, control cascades down to the next if test, in this case (grade >= 80). In general, control cascades down the statement from one test to another until one succeeds or the end of the statement is reached, possibly with a final else.

Exercise 3

Augment your solution to Exercise 1 (from Part 1) so that there are three possible messages displayed, identifying whether the number is positive, negative, or zero.


Exercise 4

This exercise shows how to generate different pronouns in a madlib based on the gender of the subject.

In the execution box below insert the statement that will use “his” if the person identifies as male and “her” if the person identifies as female, and “their” for anything else.


Nested if Statements

The braces about the then and else branches of an if statement allow any amount of JavaScript code to be under the control of the conditional — even other if statements. This has exactly the effect you would expect: the code comprised by the inner if statement is conditional on both statements. Let's outline an example, where we categorize something by whether it is positive or not and whether it's even or not. That gives us four possibilities:

if( even ) {
    ...
    if( positive ) {
        // 1. positive even
    } else {
        // 2. non-positive even
    }
    ...
} else {
    ...
    if( positive ) {
        // 3. positive odd
    } else {
        // 4. non-positive odd
    }
    ...
}

Of course, the inner blocks of code don't have to consist solely of the inner if statements. As indicated by the ellipses in the outline above, the inner blocks can have additional code precede or follow the inner if statements. Indeed, that elided code could include other conditionals!

Exercise 5

This exercise shows how to assign the correct honorific based upon a person's gender and age. Females under the age of 18 are referred to as Miss, while those 18 and over are referred to as Ms. Similarly, males under the age of 18 are called Master, while those 18 and over are called Mr.

In the execution box below insert the statements that will assign the correct honorific.


Exercise 6

In the two-player game rock/paper/scissors, each player secretly chooses one of three values (rock, paper, scissors) and both players announce their choices at the same time. The rules are:
  • rock beats scissors;
  • scissors beats paper;
  • paper beats rock;
  • a tie is declared if both players choose the same value.
  1. In the following program skeleton, assume that the variables p1 and p2 each hold one of the three strings "rock", "paper", or "scissors" for player 1 and player 2, respectively. Flesh out the program so that it pops up an alert box displaying
    • players tie if the players tie.
    • player 1 wins if player 1 wins
    • player 2 wins if player 2 wins


  2. Modify the program so that it complains if either player enters an invalid value. .

Responsive Web Design

Acknowledgment

This material was prepared by Gabriela Lanza '14, a long-time tutor for CS110, MAS major, and passionate website developer. Visit her beautiful website.

Usability

This semester, we've learned the nuts and bolts of web design: HTML, CSS, JavaScript (and we'll learn jQuery starting soon). But nuts and bolts don't tell you how to make something, and whether the result will be both functional and usable. This falls generally under the umbrella of usability, or user-centered design, which means, according to usability.gov designing your website so that users can effectively, efficiently and satisfactorily achieve their goals. We return to that topic today, which is particularly important as we prepare for implementing your websites.

Schneiderman's Eight Golden Rules of Usability

Usability isn't an easy thing to master. There's no magical formula that you can follow to make your site user-friendly. There are, however, some guidelines that will make your site much easier for your users. These rules are based off of user interface design (such as interactive applications), but can easily be adapted to websites:

  1. Strive for Consistency - Keep your design consistent across pages. Users will be confused if your website follows one design pattern on one pages and another design pattern on another page. Keep your navigation bar, the way your links look, your text size, etc. consistent.
  2. Cater to Universal Usability - Your website should be easy for people of all ability levels to use.
  3. Offer Informative feedback - If your website has interactive elements, such as form submission or an AJAX back-end, make sure to inform the user what your interface is doing. Has the form been submitted? Has the information been saved successfully? If you were the user, what would you like to know?
  4. Design Dialogs to yield closure - This rule is more important for user interfaces than for more static sites, but still applies in situations like in Rule #3.
  5. Prevent Errors - This is one of the hardest to master. It involves stepping through the process that users take to achieve tasks on your website, and thinking about where on your site users might become confused. User testing can help illuminate some of these problems.
  6. Permit easy reversal of actions - Don't let a user get lost on your website. Make it easy for them to get back to whatever page they came from.
  7. Support internal locus of control - This rule is similar to Rule #6. Make sure your users always know where on your website they are located. A map of the sequence of clicks taken to reach their current page (i.e. "About/Our Story/The Beginning"), or "breadcrumbs", are helpful in achieving this.
  8. Reduce short term memory - Don't make your users remember information from page to page. If your site has a page that requires users to use information from another page, put all of the information together instead of making your user jump back and forth between pages.

More Usability Suggestions

  • Make sure you don't have broken links!
  • Make the most important information easiest to find
    eye tracking study
    Eye tracking studies (shown above) conducted by Jacob Neilsen show that users read in an F-shape, the first two paragraphs are the most important, and sub-headings and lists stand out from paragraph text.

  • On a similar note, Provide a hierarchy of information - Use headers, lists, and breaks to make information easier to find and read.
  • Use White Space - One of the most common web design follies is to try to fit as much information on a page as possible. In fact, the opposite should be true. More white, or blank, space looks better and makes sites easier to read.
  • And last but not least, test for usability - You become so intimately familiar with your site in the process of making it that you might miss problem areas for users simply because they seem obvious to you. Often you won't know about usability issues until your test subjects find them for you.
Side note: One of the most important things about usability testing is to inform the test subject that you are testing the system not them, and that any confusion or issues they have is valuable information to you. Your usability test won't be effective if the test subject is nervous because they feel they are being judged on how well they use your site!

What is Responsive Web Design?

Responsive web design is certainly one of those things that falls under the umbrella of usability, but is so important that it deserves its own section. Making a website "responsive" means designing your website so that it is adaptable and accessible to users on any device.

Think of the multitude of devices out there today: computers with large-screen monitors, big laptops, small laptops, tablets, e-readers, phones, and many more. If users from any of these devices cannot get the information or achieve the tasks they need, your website loses a lot of effectiveness. The below chart shows the growth of mobile phone use in accessing the Web.

the rise of mobile web access

And that's just phones.

What does a responsive website look like?

Well, it's much easier to show what a non-responsive website looks like. For example, the CS110 Schedule page of the old website (before Spring 2014) was not responsive:

the cs110 schedule page

At smaller screen widths, the user cannot see the whole schedule at once, which is a problem in and of itself. And because the menu on the side is fixed, it overlaps the menu when you try to scroll sideways to see the rest of the schedule. The spigotdesign.com site, however, is designed to be responsive. Try visiting the site and re-sizing your browser. The following image shows what the site looks like on a computer, on a tablet, and on a mobile phone.

a responsive web site

Elements have been adjusted in size, moved, and even taken away entirely to adapt for different screen sizes. There are really no hard-and-fast rules for making a website responsive. Much of the process of responsive web design involves designing for big screens, testing for different screen widths, and then adjusting your site accordingly. There are, however, some helpful guidelines for designing for smaller screens.

Guidelines for Designing For Smaller Screens (Tablets, E-Readers, Phones, etc.)

  • Resize your content to fit on the screen. - If your content does not fit horizontally, stack it vertically, since there is often more vertical space than horizontal space on these types of devices.
  • Remove non-essential content - There is some content that users simply may not need when they are browsing on-the-go. Do not be afraid to remove it if it is taking up valuable screen space.
  • Increase font size for legibility - It's already difficult to read on mobile devices. Increase the font size to make your site easier to read.
  • Make your links and buttons recognizable and clickable - On touchscreen devices, users are using their fingers to click on links instead of a mouse or trackpad, which can be much less accurate. Increase the size of your buttons and links to account for this.
  • Whitespace is still important - Resist the urge to fill the screen space since there is so little of it. As with before, this blank space is still important for the overall readability of your site. Increase your margins and padding, if need be.

How do you adapt for responsiveness?

In order to adapt your website to different screen widths, you first must determine your screen's width, then apply certain rules to your screen under those circumstances. This is done with a media query. A media query is like an if statement in JavaScript: if your screen is within a certain range, then apply the CSS rules.

Exercise 1

Read the CSS code below and try to guess what will happen to the div elements of class colorblock, if you resize the page.

    .colorblock {
        width: 100%;
        max-width: 850px;
        height: 30px;
        background-color: red;
      }

      @media screen and (max-width: 700px) {

        .colorblock {
          background-color: blue;
        }

      }

      @media screen and (max-width: 500px) {

        .colorblock {
          background-color: green;
        }

      }
  

Then, try it out by playing with this page.

Notice that:

  1. The media queries comes after the original CSS definition. This is so that the later rules can overwrite the previous ones.
  2. Only the rule in question (in this case, the background color) is changed. All the other original rules still apply.

In the example above, 700px and 500px become special numbers. In the web design world, these are called breakpoints, since they are screen widths where things on the page change. In general, it is good to have as few breakpoints as possible - it can be confusing if things are constantly changing when you resize your screen, and difficult to maintain. Thereis a lot of debate in the web design world about the best breakpoints for your media queries, but, generally, safe bets are 768px and 480px, the screen widths of an iPad and an iPhone.

Other Responsive Fixes

On another note, you'll notice that the div itself is responsive and resizes along with the screen. This is because we gave it a 100% width and a max-width of the largest pixel size we want our element to be. This is a great trick for making images responsive. Percentage widths are one of your biggest tools in making a site responsive; instead of fixed-pixel widths, use percentages of the screen size. Other tricks include:

  • Remove things using display: none
  • Set inner elements to be percentage widths of outer elements (for example, four blocks in a row on the page to each have 25% width, adding up to 100% width in total)
  • Load lower image resolutions as narrower screen widths
  • Arrange things vertically instead of horizontally, by switching from display: inline or display: inline-block to display: block

    Side Note

    display: inline-block is a useful CSS rule we didn't talk about in class. It allows elements to act as block elements in terms of size and containing other elements, but is treated like an inline element for display purposes, allowing it to line up side-by-side with other inline elements.

Besides that, just try things! You'll never know what works until you spend some time finding out what doesn't first.

Example: Let's Fix the CS110 Schedule

Here's a responsive version of the CS110 schedule. Try resizing your browser, then read the explanation.

Here's a fancier responsive version, which automatically generates day labels in the narrow version.

Example: Let's Adapt a Page to be Responsive

Start with this non-responsive page, and use media queries to make it adaptive to smaller screens. Your solution may look something like this page.

Testing

Google Chrome Developer Tools allow you to emulate the screens of many devices so that you can check how your website will look like in such devices. To get to this emulation mode, once you open Inspect Element, toggle the Emulation button (on the left side of Inspect Element tab name). Then you can use the drop-down menu to choose any device you'd like to test.
emulator screnshot

More Resources

You're probably thinking by now, Wow, this sounds like a lot of code! But don't be afraid! There are tons of frameworks on the Web that make creating responsive websites easy. Most of these are built on something called a fluid grid, which, in most cases, takes care of the responsiveness for you. One of my favorites, and an industry standard, is Bootstrap, a framework built by two software developers at Twitter. If you plan on continuing in web design after this class, or if you're just interested, check it out.

Further Reading

Date Objects

Using Objects and Methods

Imagine that your web page would like to be aware of the current data. You could be prompting the user for time-related values such as month, hour and minute but it would be better to dynamically compute the date and determine, say, whether it is spring or lunchtime and so forth. We'll now see how to do that using the computer's clock instead of prompt(). Note that this is not the processor (CPU) clock that keeps a tempo for the hardware, but the conventional time, day and date clock.

Displaying the Date Dynamically

We can display the current date and time on a web page, using some built-in JavaScript to access the computer clock, and the string concatenation operators we already know. For example, the following box displays the current date and time, as reported by your computer:

You loaded this page on at

By the way, the HTML code for that box above is as follows:

<div id="date_today">
  <p>You loaded this page on <span id="date1"></span>
    at <span id="time1"></span></p>
</div>

Notice that we have two spans with CSS id's. This will make it easy for us to create JS code that will insert date and time values in these two spans using their id's. For example, executing the following JS code would assign a value to the first span box equal to January 1st of the year Wellesley College was founded!

document.getElementById("id").innerHTML = "01/01/1870"

If you reload this page, you'll notice that the date and time change to the current time of your reload. (You may see a slight flaw in the appearance (missing a leading zero in the minutes or seconds); we'll fix that later.)

Before we explain the JavaScript code that can do this, we need to understand how time is represented in JavaScript. We begin by creating a Date object:

var dateObj2 = new Date();  // The name tries to convey that this is a date object

Similarly to what we've seen before, the keyword var in var dateObj2 creates a new variable box named dateObj2 for storing a value. What we haven't seen before is the keyword new, which causes a JavaScript object to be created. In this case, the object represents the current date and time. JavaScript comes equipped with lots of pre-defined object types like Date. For those who have the time and interest, there is optional reading for a general description of objects. For now, you can think of an object as a collection of information, not just a single value.

Example Date Methods

We can extract information from a Date object by invoking methods on it. The table below shows some of the important methods that Date objects understand. The elements of the Value column are dynamically computed by evaluating the JavaScript expressions in the Expression column, so reloading the page will update these appropriately.

Expression Value Notes
dateObj2.getFullYear() Full year
dateObj2.getYear() Avoid this! Varies from browser to browser
dateObj2.getMonth() 0=Jan, 1=Feb, ..., 11=Dec
dateObj2.getDate() 1 to 31
dateObj2.getDay() 0=Sun, 1=Mon, ..., 6=Sat
dateObj2.getHours() 0 to 23
dateObj2.getMinutes() 0 to 59
dateObj2.getSeconds() 0 to 59
dateObj2.getTime() Milliseconds since Jan 1, 1970 (the "epoch")

You'll note that all of these methods "return" numbers, extracting one piece of information out of the collection that the object comprises. Usually, they are pretty intuitive:

  • .getMinutes() returns a number from 0 - 59
  • .getFullYear() returns a number like 2015
  • .getHours() returns a number from 0 - 23, which is intuitive for everyone in the world except for Americans.
  • .getDate() returns a number from 1 - 31, depending on the month.
  • .getDay() returns a number from 0 - 6, depending on the day of the week. You might think it would be 1-7, but the designers of JavaScript chose to number the days of the week starting at zero. Odd, but bearable.
  • .getMonth() returns a number from 0 - 11, depending on the month. This is deeply unintuitive for anyone except computer scientists, who are accustomed to things being numbered starting at zero. And they still get tripped up by things like .getMonth()

Later, when we talk about arrays, we'll try to justify why certain things are numbered starting at zero. But for now, we'll just understand that these are what we have to work with.

W3 Schools has a complete list of methods for Date objects.

Object Notation

Let's discuss the notation for objects. First, imagine that we create two Date objects, a few seconds apart:

var obj1 = new Date();
alert("obj1: "+obj1);
var obj2 = new Date();
alert("obj2: "+obj2);
var sec1 = obj1.getSeconds();
var sec2 = obj2.getSeconds();
alert("seconds in obj1: "+sec1+" and in obj2: "+sec2);
var diff = sec2 - sec1;
alert("difference is "+diff);

You can think of each new Date() expression as taking a snapshot of the computer clock, recording those values at that moment in time.

Our mental picture of this example might be like this:

two date objects
Two date objects and info extracted from them

Because objects contain a collection of information, possibly quite large, we picture it as a round thing. (Here, each object is a light blue circle.) We can store these things in variables (labeled boxes), just like we store anything in variables, including numbers, strings, and booleans. The other variables just contain numbers; we're used to those.

Given an object in a variable, we use a method to do something with it (such as extracting some data) using the following syntax:

var_containing_object.method_name(args);

The dot is important: it separates the object (or a variable containing an object) from the method that is being used. Some methods need additional arguments; we haven't seen any yet, but we will later in the course. For now, we'll just see an empty pair of parentheses, but these are required.

The examples we saw above fit that pattern:

var sec1 = obj1.getSeconds();  // get seconds out of obj1
var sec2 = obj2.getSeconds();  // same, but for obj2

Date Formatting

Now let's return to our date and time display. A date object contains a collection of information about the date and time, but for human-readability, we will need to format that data in some conventional way, using, for example, slashes and commas to separate the various numbers.

Here is the date, formatted as is done in the United States and a small handful of other countries. This box has text in Spanish, unlike our earlier box:

Ha cargado esta página en a las .

The HTML for that box above is just this:

<div id="date_today2">
  <p>Ha cargado esta página en <span id="date2"></span>
    a las <span id="time2"></span></p>
</div>

Here is some JavaScript code that inserts the formatted date and time into the box above. (Note the two empty span elements with IDs that we'll use below.)

// create a date object, representing this moment, and store it
var dateObj = new Date();

// format info about the day
var the_date = dateObj.getDate();
var the_month = dateObj.getMonth() + 1; // Add 1 because Jan is 0, etc.
var the_year = dateObj.getFullYear();
var current_date = the_month + "/" + the_date + "/" + the_year;

// format info about the time
var the_hour = dateObj.getHours();
var the_minute = dateObj.getMinutes();
var the_second = dateObj.getSeconds();
var current_time = the_hour + ":" + the_minute + ":" + the_second;

// insert the formatted strings into the document.
document.getElementById("date2").innerHTML = current_date;
document.getElementById("time2").innerHTML = current_time;

(You can also view the page created by embedding this code in a complete HTML file for displaying the date.)

Let's examine the code. It is a sequence of JavaScript statements, which will be executed sequentially by the browser. The first statement (line 2) creates a Date object representing the current date and time, and stores it in a variable named dateObj. The next block of statements (lines 4-8) extract components of this Date object and piece them together to construct a description of the date, like 10/13/2015. The next block of statements (lines 10-14) similarly extract components of this Date object and piece them together to construct a description of the time, like 17:22:44.

The final document.getElementById("id").innerHTML statements each inserts a string into the span with the given ID, thereby displaying the date and time on the page. The surrounding text is fixed. You've seen this sort of trick in lab; we'll do more with this later in the course. Here's another copy of the HTML code they inserted it into:

  <p>Ha cargado esta página en <span id="date2"></span>
    a las <span id="time2"></span></p>

Practice the behavior of the code by using the execution box below. Change the code to display the date in the format that most of the world uses, namely, DD/MM/YYYY.

Remember:

  • In the execution boxes you do not need the <script> tags. They are implied.
  • We suggest replacing the .html() code with an alert(), so that the code is obvious when it's running.

Exercise on Date Formatting


Objects in General (OPTIONAL READING)

Dates are one kind of object. In JavaScript, an object is a kind of value that has two important characteristics:

  • state, which is given by what JavaScript calls properties. This is the collection of information in the object. Different kinds of objects have different kinds of information in them: an object about an element of your document might have information like width, height, margins, color and much more. Date objects wouldn't have that.
  • behaviors, which are specified by what JavaScript calls methods. Methods allow you to operate on the object, extracting information and even modifying the information. For example, we can change the text inside a document element to dynamically change what the document shows.

Both properties and methods are selected from an object using dot notation. In the examples above, we only used methods. You can tell we're using a method rather than selecting a property by the presence of parentheses after the name.

Other Methods

We've used the example of dates to teach you about:

  • Objects (encapsulations of data and methods to operate on it)
  • Methods (ways to extract or modify the data in an object)

Lots of other objects and methods exist in JavaScript.

Here's another method, this time on numbers, the toFixed() method:


The toFixed() method returns a string representation of the number, with the number of decimal places given by the argument. It does not change the value of the variable, as the last step shows.

The toFixed() method operates on numbers. A method that operates on strings instead is the .indexOf() method. See if you can guess what it does:


Yes, the indexOf() method searches for one string inside the main string object.

Wait, are numbers and strings objects? Earlier in this reading, we suggested that objects (pictured with light blue circles) were collections of information, unlike simple values like numbers and strings. It turns out that objects and methods are such a useful way of organizing information that many programming languages treat everything as a kind of object. JavaScript allows numbers and strings to be treated as objects when it's convenient, as it is here.

Later in the course, we'll see how parts of the HTML document can be represented and manipulated using objects. This is the Document Object Model, or DOM.

Names for Months and Days

The earlier date manipulation code was all numerical. That's partly because JavaScript is used around the world, and they decided not to have a built-in function to map month zero to January when it could just as easily have been Janvier (French), Enero (Spanish) or Styczen (Polish).

Despite this, we decided to implement a simple function that maps month-numbers (ranging from 0 to 11) to English month-names. The function is named monthName(). We also wrote one to map day-numbers (ranging from 0 to 6) to English day-names. Try them out:


We'll show you how it's implemented a bit later, but for now, please take it on faith.

Exercise

How would you print the name of the month 10 months from now?

Date Objects for Other Dates

All along, we've created Date objects as a snapshot of the current computer clock, but we don't have to. We can create a Date object for any date of our choosing, just by giving a string to the Date() function. Here's a bit of code that will tell us what day of the week Christmas falls on in 2015:


Note, though, that if you mess up the syntax of the string describing the date and time, you'll get an invalid Date object and nothing good will happen:


You can fix the above by removing the "am" part; remember that "13:15" would be "1:15pm", so the "am/pm" part is unnecessary.

Summary

  • The Date object is used to manipulate dates and time. The expression new Date() creates a Date object representing the current date and time. Methods like getMonth() and getHours() are used to extract components from a Date object.
  • We've taught you about Date objects primarily to introduce the concepts of
    • complex data that is encapsulated in an object, and
    • methods that can pull that data out.
  • In general, objects are collections of related data. Objects have methods to extract information from the object and to modify the object.

Solutions to Exercises

  • Exercise on Date formatting, non-American style:

  • How would you print the name of the month 10 months from now?

JavaScript Functions

Functions Conceptually

In this reading, we'll learn a very powerful aspect of programming languages, namely the ability to define and use our own functions. We have used many "built-in" functions, such as alert and parseInt; now we will be able to build our own.

Why is this so important? Consider a function like parseInt: it does something that is useful in many situations and we can use it without understanding how it works (its implementation). If we are involved in a large software project, someone else on our team can implement a function that we can use, and vice versa. We can use their code without understanding all the details of its implementation, which saves us mental effort. This idea also allows the team to be more efficient than if each person had to understand everything.

This is another manifestation of the idea of modularity. A function is a kind of module. It can be defined in one place and used in many places, just as a single CSS rule can be defined in one place and used in many places. Furthermore, if we discover a bug in the function, its definition can be fixed and every user of that code gets the improvement. This is similar to modules in the real world, where if you drop your headphones into the bathtub and short them out, you can replace them without having to replace your music player, too.

So far, this may seem pretty intuitive; I certainly hope so. Nevertheless, functions can be pretty complex at times. To explain them, I will use three metaphors:

  • A function is like a recipe, say for chocolate cake, in the sense that it is a procedure for accomplishing something. This metaphor is particularly useful when we talk about functions as step-by-step written directions. Indeed, part of the magic of computer programming is that words do stuff.
  • A function is like a machine, say a blender or a meat grinder. This metaphor is helpful when we talk about a function having inputs (cubes of ice or meat) and outputs (crushed ice or ground meat).
  • A function is like a workspace, like a kitchen or study carrel. This metaphor is most important when we want to talk about the local storage of a function, which is part of how it works. Kitchens have their own cupboards and mixing bowls, which are separate from those found in other kitchens.

We can even combine all these metaphors and imagine a function as kitchen with a chef inside. The users of the kitchen don't need to know anything about the workings of the kitchen. All they need to know is that they give it certain inputs (eggs, flour, cocoa, or maybe just money) and outputs are generated (a chocolate cake).

Definition and Invocation

Defining a function is like making up a recipe. We have to give it a name and list the steps that need to be done. Once the recipe is defined, anyone can use it.

Let's look more precisely at the syntax of a function definition:

<script>
// comment about your lovely function
function functionName()
{ 
                            .
                            .
        JavaScript code to define the function goes here
                            .
                            .
} 

To define your own function you need:

  • the keyword function
  • a name, which you make up, that replaces functionName in the template
  • parentheses, (), after the name. Any parameters must be included within the parentheses.
  • curly braces {} to demarcate the start and end of your function
  • your JavaScript code inside the body of the function — that is, within the braces

It is also considered good practice to put a comment before the function describing what the parameters are for, what value gets computed if any, what actions are performed, etc. Anything that isn't obvious from the code. (Comments that just repeat the code in English are bad.)

Here's an example:

function chocolateCake() {
    // step 1, combine sugar and flour in a large bowl
    // step 2, add two large eggs
    // ...
    // frost and serve
}

The chocolate cake example is a little silly, because we don't know any JavaScript for the definition. Here's a better one that formats the date on the page. You'll recognize this code from our recent discussion of the Date object, though I've abbreviated the code a little.

function formatDate() {
    // create a date object, representing this moment, and store it
    var dateObj = new Date();

    // format info about the day
    var the_date = dateObj.getDate();
    var the_month = dateObj.getMonth() + 1; // Add 1 because Jan is 0, etc.
    var the_year = dateObj.getFullYear();
    var current_date = the_month + "/" + the_date + "/" + the_year;

    // insert the formatted string into the document.
    document.getElementById("date2").innerHTML = current_date;
}

Now we come to an interesting situation, because we have defined a function, but how do we use it. Here, I'll use the metaphor of a machine: we have a blender, but how do we turn it on?

Computer scientists have a special word for running a function (making it do its job), and that is invocation. (Like invoking the gods.) We say that we invoke the formatDate function to get it to run and insert the date onto the page. In less formal circumstances, we say that we call the function. (This is like call a friend for help.)

You've been doing this all along, calling or invoking the built-in functions. Here are some examples:

var name = prompt("what's your name?");  // invoke prompt
var now = new Date();                    // invoke Date
formatDate();                            // invoke formatDate

Invoking our formatDate function is no different from invoking the built-in functions. True, those built-in functions have arguments, which makes the invocation look a little different, so we'll turn to that in a moment.

Your code can define lots of functions, maybe in several external .js files so that the definitions can be shared by many files in your website. None of those functions need ever be invoked, in which case they will be useless, like those recipes and kitchen gadgets you never use and which just collect dust. It's important to keep in mind the difference between definition and invocation of a function.

Parameters and Arguments

The function above was fairly inflexible: it only formatted today's date and it always inserted the date into the date2 element on the page. Imagine a kitchen gadget that could chop up ice but nothing else. If you want to chop carrots, you have to buy a different machine. To chop celery, yet another machine. A more flexible and general function would allow you to input the date to be formatted, and the ID of the element you want to insert the date into. For that, we have to use a definition syntax that specifies parameters. We will also have to change the invocation of the function to supply these associated arguments.

Here's our modified function. Note that I've changed the name to formatDate2 only so that it's clear what version of the function we are discussing. I could have used the same name as the first version, or I could have named it something different, like formatDate_version_2 or even fred.

function formatDate2(dateObj, targetId) {
    // format info about the day
    var the_date = dateObj.getDate();
    var the_month = dateObj.getMonth() + 1; // Add 1 because Jan is 0, etc.
    var the_year = dateObj.getFullYear();
    var current_date = the_month + "/" + the_date + "/" + the_year;

    // insert the formatted string into the document.
    document.getElementById(targetId).innerHTML = current_date;
}

Now, to get the same effect as we had before, namely to format the current date into date2, we would invoke the function like this:

formatDate2( new Date(), "date2" );

So far, this seems less powerful than what we had before. In fact, let's compare them side by side:

Definition
function formatDate() {
    var dateObj = new Date();

    // format info about the day
    var the_date = dateObj.getDate();
    var the_month = dateObj.getMonth() + 1;
    var the_year = dateObj.getFullYear();
    var current_date = the_month + "/" + the_date + "/" + the_year;

    // insert the formatted string into the document.
    document.getElementById("date2").innerHTML = current_date;
}
function formatDate2(dateObj, targetId) {
    // format info about the day
    var the_date = dateObj.getDate();
    var the_month = dateObj.getMonth() + 1;
    var the_year = dateObj.getFullYear();
    var current_date = the_month + "/" + the_date + "/" + the_year;

    // insert the formatted string into the document.
    document.getElementById(targetId).innerHTML = current_date;
}
Original Invocation
formatDate();
formatDate2(new Date(), "date2");
Additional Invocation
???
formatDate2(new Date("10/31/2016"), "halloween");

If you look at the original invocation, it looks like some of the code has just migrated out of the function definition and become part of the invocation, so it's now harder to use the function. We've transferred work from the implementation to the caller.

This is true. But this burden is useful, because it allows us to use the function in other situations, such as formatting the date of Halloween in another place on the page. You can see that that's impossible with the original version.

Notice, by the way, in that side-by-side comparison, that we are able to make the function more flexible by replacing particular parts of the definition with variables and then those variables are placed between the parentheses in the first line of the function definition:

variable specific
dateObj new Date()
targetId date2

This is a fairly common trick: making something more flexible by replacing constants with variables, and supplying values for those variables when the function is invoked.

The names in the parentheses in the function definition are called parameters, and the values that are supplied when the function is invoked are called arguments. (This terminology is not standardize in computer science, but it's common and we will use it.) The parameter is a kind of variable, in that it's a storage location; it stores the corresponding argument.

In the examples above, we had:

ParameterArgument
Original Invocation
dateObj new Date()
targetId "date2"
Additional Invocation
dateObj new Date("10/31/2016")
targetId "halloween"

If you like, you can think of the beginning of the function invocation as a sequence of assignment statements, assigning the value of the each argument, one at a time, to the corresponding parameter.

Return Values

If arguments are like inputs to a machine, can we also have outputs from our machines? Yes, a function in JavaScript can have a return value. One slight restriction is that a JavaScript function can have any number of distinct inputs (arguments), but it can only have one return value, just like you can put any number of ingredients into your blender, but you only get one output.

Let's define another function. This one will map day numbers (0 through 6) to the corresponding English name. If we assume that the day number is in a variable called dayNum and we want to compute the result in a variable called dayName, we might write code like this:

var dayName = "unknown";
if( dayNum == 0 ) {
    dayName = "Sunday";
} else if ( dayNum == 1 ) {
    dayName = "Monday";
} else if ( dayNum == 2 ) {
    dayName = "Tuesday";
} else if ( dayNum == 3 ) {
    dayName = "Wednesday";
} else if ( dayNum == 4 ) {
    dayName = "Thursday";
} else if ( dayNum == 5 ) {
    dayName = "Friday";
} else if ( dayNum == 6 ) {
    dayName = "Saturday";
}

That code just uses our skills in cascading if statements. Now, we need to package that code up into a function, a little machine that will take in a number and give us back a string. By take in, we mean the function takes an input in the form of an argument. Here's what we might write:

function dayNameEnglish(dayNum) {
    var dayName = "unknown";
    if( dayNum == 0 ) {
        dayName = "Sunday";
    } else if ( dayNum == 1 ) {
        dayName = "Monday";
    } else if ( dayNum == 2 ) {
        dayName = "Tuesday";
    } else if ( dayNum == 3 ) {
        dayName = "Wednesday";
    } else if ( dayNum == 4 ) {
        dayName = "Thursday";
    } else if ( dayNum == 5 ) {
        dayName = "Friday";
    } else if ( dayNum == 6 ) {
        dayName = "Saturday";
    }
   return dayName;
}

Here's an example of the function in action (that is, an invocation of the function):

var name = dayNameEnglish(0);   // should be "Sunday"
alert(name);

Again, we refer to the 0 in the invocation as the argument. Inside the machine, the parameter dayNum will have the value 0.

At the end of the function is something new: return dayName. That code says that the value of the function is whatever is in that variable.

Armed with this new function, we can re-write our date formatting function as follows, now named formatDate3

function formatDate3(dateObj, targetId) {
    // format info about the day
    var the_date = dateObj.getDate();
    var the_month = dateObj.getMonth() + 1; // Add 1 because Jan is 0, etc.
    var the_year = dateObj.getFullYear();
    var dayName = dayNameEnglish( dateObj.getDay() ); // e.g. "Friday"
    var current_date = dayName + ", "+ the_month + "/" + the_date + "/" + the_year;

    // insert the formatted string into the document.
    document.getElementById(targetId).innerHTML = current_date;
}

So that you can test this, we've created the following element:

That date is formatted as YOUR DATE RIGHT HERE

Note how the formatDate3 function invokes the dayNameEnglish function:

    var dayString = dayNameEnglish( dateObj.getDay() ); // e.g. "Friday"
    var current_date = dayString + ", "+ the_month + "/" + the_date + "/" + the_year;

This code is very abstract! The dateObj variable contains an object that somebody wants formatted (whoever invoked the formatDate3 function). We use a method, .getDay() to extract the number for the day of the week. That number is then sent as an argument to the dayNameEnglish() function. That function runs and returns a string, which we store in dayString and use on the next line.

When we are programming and defining functions, we often are in a situation where we don't know the particulars. We are trying to create a general solution. We don't know what date is being formatted or where it's going to go on the page. We have to trust that the caller knows what they are doing. In a way, this is like the chef in the kitchen who gets an order for a chocolate cream pie. The chef doesn't know whether the pie will be for dessert or used as a weapon, but that's not their concern. Their job is just to make the pie.

Sequence of Execution

You probably noticed in that last example that we had two functions that we defined, one of which invoked the other. That often happens, and you might think that the computer could get confused about what line of code should be executed when. But, it's actually pretty intuitive.

  1. formatDate3 starts at line 1
  2. When it gets to the invocation of dayNameEnglish, the computer puts this function on hold and
    1. dayNameEnglish starts at its line 1
    2. when it gets to the return statement, it returns to the caller (with a value)
  3. formatDate3 picks up where it left off

This can be nested as deeply as you like (theoretically infinite, albeit not infinitely deep in practice) and the computer never gets confused, even when different functions are invoking dayNameEnglish. It always knows who and where to return to.

Local Variables

Throughout our examples, we've never been reluctant to create new variables inside our functions when we wanted them, such as the_date and the_month. This is perfectly legal and desirable. These are called local variables, because they only exist inside the function. They are created when the function is invoked, and they cease to exist when the function is finished.

If you had very sharp eyes, you might have noticed that our two functions had a local variable that had the same name, namely dayName. That is also legal.

To explain what's going on, I appeal to our third metaphor of functions, as separate work spaces, like an enclosed kitchen. Kitchens have lots of storage containers that are not inputs or outputs --- things like mixing bowls and measuring cups. Different kitchens have different storage containers, even if they are called the same thing. Here's an abstract example:

function fred() {
    var snackbox = "puking pastille";
    alert(snackbox);
    ...
}

function george() {
    var snackbox = "nosebleed nougat";
    alert(snackbox);
    ...
}

Here we have two functions named after Weasley twins in Harry Potter. Each function has a local variable called snackbox, but these are completely different storage locations. Think of them as being in different kitchens, each presided over by a different Weasley twin. The local variables come into existence when the function is invoked and disappear when it finishes. (Easy cleanup!)

Local variables are distinguished from global variables which are shared by everything. The following example may help. Read the code, then run it, and see if you can make sense of the behavior.


You saw the following sequence of output:

  1. fever fudge, from the alert of the global
  2. puking pastille, from fred
  3. nosebleed nougat, from george
  4. fever fudge, from the second alert of the global

The amazing thing is that all three of these variables are separate storage locations, so none of the assignments affects any of the others. There's a "snackbox" in Fred's private area; another, different, one in George's private area, and a third one in the common room that everyone shares.

Usually, that's exactly what you want. Occasionally, a function wants to modify the global variable rather than a local variable. To do so, just omit the var before the variable name:


This time, you saw the following sequence of output:

  1. fever fudge, from the alert of the global
  2. puking pastille, from fred
  3. nosebleed nougat, from george
  4. nosebleed nougat because fred and george modified the global, but george was second.

The best practice is always to use local variables, creating them with var, and only to use global variables when necessary.

A bit of terminology: the places that a variable is visible or usable is called its scope. We might say that some variables have scope that is local while others are global.

Functions as an API

Earlier, we noticed that the improved version of date formatting, namely formatDate2, resulted in more work for the caller:

Original Invocation
formatDate();
formatDate2(new Date(), "date2");
Additional Invocation
???
formatDate2(new Date("10/31/2016"), "halloween");

In both of these, the first argument is an expression that involves the Date function and so on. As programmers, we can make the caller's job easier with just a bit of work. Here's what we would like to say instead:

Original Invocation
formatDate();
formatDate2b("today", "date2");
Additional Invocation
???
formatDate2b("10/31/2016", "halloween");

That's much clearer and easier, and just involves a little bit of work for the implementation. Here's one way, with the conversion of the dateSpec parameter (date specification) into the desired kind of Date object. This happens in the lines 2--6 of the function, and everything else is the same.

function formatDate2b(dateSpec, targetId) {
    if( dateSpec == "today" ) {
        var dateObj = new Date();
    } else {
        var dateObj = new Date(dateSpec);
    }
    // format info about the day
    var the_date = dateObj.getDate();
    var the_month = dateObj.getMonth() + 1;
    var the_year = dateObj.getFullYear();
    var current_date = the_month + "/" + the_date + "/" + the_year;

    // insert the formatted string into the document.
    document.getElementById(targetId).innerHTML = current_date;
}

The point here is that these interfaces between functions and other bits of software are designed by humans, and they can be easier and more convenient if we want them to be. This is part of creating an Application Programmer Interface (API). An API is a term for a set of software interfaces, such as functions and their arguments, that allow an application programmer to get something done.

Functions as Values -- OPTIONAL READING

At this point, you know most of what you need to know about functions for this semester, but one mind-blowing concept remains. Programming languages describe certain values as being first class objects when you can do normal things with them like store them in variables and pass them as arguments to a function. In JavaScript, as you know, numbers are first-class objects, and so are strings and even booleans. Date objects are first-class.

The mind-blowing thing is that functions are first-class objects! That means we can store them in variables and pass them as arguments to a function. For example, we can do the following:

var dayNamer = dayNameEnglish;

If the function is stored in a variable, can we still invoke it? Yes! It turns out that the parentheses in a function invocation are sort-of like the on button of a machine. Here's how we could invoke that function above:

dayNamer( 0 ); // Sunday

So what? Imagine we define another day naming function:

function dayNameFrench(dayNum) {
    var dayName = "unknown";
    if( dayNum == 0 ) {
        dayName = "Dimanche";
    } else if ( dayNum == 1 ) {
        dayName = "Lundi";
    } else if ( dayNum == 2 ) {
        dayName = "Mardi";
    } else if ( dayNum == 3 ) {
        dayName = "Mecredie";
    } else if ( dayNum == 4 ) {
        dayName = "Jeudi";
    } else if ( dayNum == 5 ) {
        dayName = "Vendredi";
    } else if ( dayNum == 6 ) {
        dayName = "Samedi";
    }
   return dayName;
}

Our date-formatting function seems to be always using the English days of the week. Could it be made even more flexible, where we supply a function that returns the correct day name? Yes, we can. Here's the latest version, now named formatDate4:

function formatDate4(dateObj, dayNamer, targetId) {
    // format info about the day
    var the_date = dateObj.getDate();
    var the_month = dateObj.getMonth() + 1; // Add 1 because Jan is 0, etc.
    var the_year = dateObj.getFullYear();
    var dayName = dayNamer( dateObj.getDay() ); // e.g. "Friday" or "Vendredi"
    var current_date = dayName + ", "+ the_month + "/" + the_date + "/" + the_year;

    // insert the formatted string into the document.
    document.getElementById(targetId).innerHTML = current_date;
}

So, the dayNameEnglish function on line 6 has now become a variable, a parameter whose value will be supplied when the function is invoked.

So that you can test this, we've created the following element:

That date is formatted as YOUR DATE HERE

Here's the key thing to notice and remember. When we have dayNameFrench in the invocation, we don't use parentheses. That's because we are not invoking it right now, but we are passing it (the dayNameFrench function) into the formatDate4 function. This is like handing someone a blender or other kitchen gadget instead of the output of the gadget.

This may seem like an esoteric usage, and it is. We won't be asking you to define functions as sophisticated as formatDate4. However, we will expect you to understand the difference between invoking a function, where the parentheses are used, and passing it as an argument to another function, where the parentheses are omitted.

Summary

We covered a lot of difficult ground in this reading. The main points are:

  • Functions are defined and later can be invoked, which means the code in the definition actually executes. The code does not run until the function is invoked.
  • Functions are text (like recipes) that have names. They are also like machines in that they have inputs and, optionally, outputs, and there is a distinction between defining one and running (invoking) it.
  • Functions can define local variables as part of their definition, and these belong only to the function. They are created when the function executes, and they disappear when it completes.
  • Functions are also a kind of value, and they can be stored in variables and passed as arguments to other functions.

DOM and JQ

This reading introduces the Document Object Model, or DOM, and a widely-used JavaScript library called jQuery. jQuery is used in thousands of websites and is supported by Google, IBM and other tech companies because it makes working with the DOM much easier and more reliable.

Document Object Model

Earlier in this course, we use HTML to structure our web pages and supply them content. We used CSS to give them some style. Then we introduced JavaScript, but the JavaScript barely seems to have anything to do with the HTML and CSS, other than running in the web browser.

There's one exception, and that is code like the following:

document.querySelector("#fred").innerHTML = "I'm Fred";

The preceding JS code will actually modify the web page, changing the contents of the #fred element (the element whose id is fred), to contain the string "I'm Fred".

The first part of the JS expression above, namely:

document.querySelector("#fred")

returns an object that represents something in the web page. That thing could be a paragraph, a header, a div, or any other element. The object has properties, such as innerHTML, and modifying that property modifies the web page. Thus, the web page is dynamic.

To understand this better, let's review what we know about web pages.

The DOM

The Document Object Model (DOM) is the application programming interface (API) to represent and interact with an HTML document.

The DOM represents the HTML document as a tree of nodes. Every node represents a portion of the document. Explore below an example of how a simple HTML file is represented by its DOM.

<!doctype html>
<html lang="en">
<head>
  <title>My blog</title>
  <meta charset="utf-8">
  <script src="blog.js"></script>
</head>
<body>
  <h1>My blog</h1>
  <div id="entry1">
    <h2>Great day bird watching</h2>
    <p>
      Today I saw three ducks!
      I named them
      Huey, Louie, and Dewey.
    </p>
    <p>
      I took a couple of photos ...
    </p>
  </div>
</body>
</html>
Graphical representation of the DOM for the listed HTML example above. Image from the chapter of your reading.

Important Note

The DOM represents both the structure and the content of the HTML page. All elements of the structure (i.e., tags) are represented by nodes surrounded with a border in the tree. In the Javascript representation they are all objects. The content of these objects is shown in the graphical representation without a border, and it's accessed by properties (such as innerHTML) of the objects that contain them.

DOM as a Bridge

The DOM is a bridge between the HTML world of elements (paragraphs, lists, divs, and so on) and the JavaScript world of variables, functions, objects, and methods. Every web browser has the DOM built-in, and the code we saw earlier is part of it:

document.querySelector().innerHTML

However, we will not be using the built-in DOM. Instead, we will be using an add-on library called jQuery. We prefer jQuery for several reasons:

  • Consistency: Different browsers often build their DOM slightly differently, and jQuery hides those differences. It will translate our jQuery code into whatever works in the user's browser.
  • Brevity: jQuery code is wonderfully concise, and so everything is much easier to accomplish.
  • Power: there are a few things that jQuery does that are so powerful that, while you could implement them in the native DOM, in practice you wouldn't.

Let's start with an example of jQuery's conciseness. The following two lines of code are equivalent:

document.querySelector("#fred").innerHTML = "I'm Fred";
$("#fred").html("I'm Fred");

The latter, of course, is jQuery, the topic that we turn to now. If you want to learn a bit more about the DOM, the following answers the question What is the DOM? in a brief page consisting of four big pictures and a small amount of text.

jQuery Basics

jQuery is a library written in Javascript that is specialized for changing web documents on the fly. It is one of the most used libraries on the web. However, because it's not built-in to the browser, it has to be loaded. If you don't load jQuery, none of these examples will work.

Load jQuery

In order to use jQuery in a webpage, we need to include it with the <script> tag. The library itself is a big Javascript file with hundreds of lines of code. We can either download this file from the jQuery website, or we can use an absolute URL to some web server that keeps a copy of the library online. For simplicity, we will do the latter. Here is how we will include jQuery in our programs:

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>

As of this lecture, the most current version of jQuery is 2.2.1, but 1.11.0 will do. (The main difference between the 2.x and 1.x versions is whether older browsers like IE 6/7/8 are supported.) In your reading or examples from the Web, you will notice other version numbers. The .min part of the filename means mininfied. This refers to the practice of deleting all newlines and other space to reduce file size. If you open this file, you'll notice that it doesn't show the structure of a normal Javascript program with indentation and nesting. Thus, it is not for human consumption. However, it does load faster, because the file is smaller.

jQuery wrapper

Once we have the jQuery library linked to our page, we can start using its main method, the jQuery Wrapper. This is a function that has two forms:

$()   // Short form is common

jQuery()  // Long form is rare

In practice, the dollar sign is used almost always. The long form is only used in a few odd cases when your page is loading several libraries, both of which use the dollar sign. In this course, you will always use the dollar sign.

As we said earlier, jQuery is a bridge to the web page, so most of what we will be using it for is to dynamically modify the web page, or to attach behaviors to it. Here are some of the things we might want to do:

  • Modify the HTML inside an element
  • Modify the CSS of an element or other attributes of it.
  • Add new elements to the page
  • Remove elements from the page
  • Hide/show elements on the page

We'll see most of those today. In later readings, we'll see even more that jQuery can do.

Syntax

Code using jQuery has a very nice, consistent, concise syntax, so let's take a minute to learn that syntax using an example we already understand, namely modifying the HTML in an element.

Our example uses a element created by the following HTML/CSS code that creates an empty, green-bordered box on the page, whose ID is pandora.

<div id="pandora">This is Pandora's box</div>
<style>
  #pandora {
      width: 80%;
      margin: 0 auto;
      border: 2px solid green;
      padding: 5px;
  }
<style>
This is Pandora's box

Suppose we wanted to put some text dynamically into Pandora's box (replacing what is there). The following lines of JavaScript/jQuery do the trick.


Try putting hope into the box instead.

Let's try to understand this example of jQuery code. (Remember, jQuery is an extension of JavaScript, not a whole different language, but it can seem like a different language at times.) Here it is again:

var contents = prompt("What to put in Pandora's box?", "all evils");
console.log("putting "+contents+" into Pandora's box");
$('#pandora').html(contents);

The first two lines of code are things we have seen before: prompt() gets a string from the user and the first statement stores that string in a variable called contents. The second line glues a few strings together (some of which are string literals and one of which is in the contents variable) and then writes the combined string onto the console log.

The third line puts the string into the box, using a jQuery incantation:

$('#pandora').html(contents);

How does the incantation work? There are basically three things going on here:

$(selector).method(stuff);
  • selector This is a string that selects an element or set of elements within the document. We can then do something to all of those elements. jQuery uses the same ways of selecting elements that CSS does. In this case, it is choosing exactly one, unique element, the one whose id is pandora. Hence it uses #pandora, exactly like the CSS does. Thus, all your skills with selecting elements using CSS will serve you well when using jQuery.
  • method The word after the parens and the dot names one of the built-in jQuery methods. Here, we used the the html method, which replaces the contents of an element with some string. Using the .html() method replaces the contents of all the elements that were chosen by the selector (in this case, just one).
  • stuff This is the stuff that we want to replace the contents of the selected elements. In this example, we replaced it with the string that the user gave us in the first line. In general, the method may take additional arguments, and they are listed here.

So, in summary, we used jQuery to find the div and insert the user's input into it. What we haven't shown you is how to trigger this behavior in a more elegant way than one of these execution boxes. That will have to wait for a later lecture. Be patient. For now, though, we'll demonstrate some of the abilities that JQ has to dynamically alter a web page. We won't go into great detail in any of them; we just want to give you the basic idea.

The html() Method

As we've seen, the html method modifies the contents of the page. It doesn't have to take just text; in general, it can take any HTML. (To learn all there is about it, read the documentation for the html method.) Here's another example, using a list.

<ol id="horcruxes"><li>currently empty</li></ol>
  1. currently empty

Let's replace that with some other HTML


Modifying Attributes

jQuery has several ways to modify the attributes of an existing elements. Let's start with changing the CSS of a figure:

<figure id="fig1">
  <img id="img1" src="potterpics/harry-potter-thumb.jpeg" alt="Harry Potter">
  <figcaption id="cap1">Harry Potter as played by Daniel Radcliffe</figcaption>
</figure>
Harry Potter
Fig1: Harry Potter as played by Daniel Radcliffe

We could change the CSS by adding a border, centering, a background-color and some padding. Click the button to implement these changes. Notice the descendant selectors we use for the caption.


The .css() method takes two arguments, a property and a value, just like static CSS. It works exactly like inline CSS. Try inspecting the figure and figcaption elements above; you'll see that they have had inline CSS attributes added to them. (However, this is not a bad use of inline CSS, because the CSS is not mixed with the static HTML code; it's being dynamically specified.)

There are other attributes we could change, such as the SRC and ALT for the image here:

<figure id="fig2">
  <img src="potterpics/hermione-granger-thumb.jpeg" alt="Hermione Granger">
  <figcaption>Hermione Granger as played by Emma Watson</figcaption>
</figure>
Hermione Granger
Fig2: Hermione Granger as played by Emma Watson

The attributes above can be changed using jQuery's attr() method. Watch what we can do with it; it's like magic!


Hide/Show Elements

If you want to make something disappear, you could modify its CSS to have the property display:none. You could undo that change to make it re-appear. This is so common that jQuery has special methods, .hide() and show(). Here's our figure again, this time as fig3:

Hermione Granger
Fig3: Hermione Granger as played by Emma Watson


We could describe more methods, but hopefully you are seeing the pattern: select an element and operate on it using a method. So, let's turn to some slightly different tricks jQuery has up its sleeve.

Wrapped Sets

So far, we've always seen the selector part of the jQuery expression pick out just a single element. However, jQuery is more general and powerful than that. In most cases, if the selector matches more than one element on the page, jQuery operates on all of the elements in one fell swoop. Here's an example:

<ol id="characters1">
  <li class="gryffindor">Harry</li>
  <li class="gryffindor">Ron</li>
  <li class="gryffindor">Hermione</li>
  <li class="gryffindor">Fred</li>
  <li class="gryffindor">George</li>
  <li class="ravenclaw">Cho</li>
  <li class="hufflepuff">Cedric</li>
  <li class="slytherin">Draco</li>
  <li class="slytherin">Crabbe</li>
  <li class="slytherin">Goyle</li>
</ol>
  1. Harry
  2. Ron
  3. Hermione
  4. Fred
  5. George
  6. Cho
  7. Cedric
  8. Draco
  9. Crabbe
  10. Goyle

Method Chaining

The jQuery wrapper function always returns the set of elements it matches, so you can operate on it again, if you like. Knowing that the jQuery wrapper always returns something is very useful for chaining jQuery methods. This is done to avoid storing results in temporary variables, or repeating a search for set of matches. So, some of our examples above could be even more concise:

Harry Potter
Fig4: Harry Potter as played by Daniel Radcliffe

We could change the CSS by adding a border, centering, a background-color and some padding. Click the button to implement these changes.


This is not only less to type, it's easier to understand and it's faster to execute, because it now finds the element once and does a series of operations on it.

Note, though, that we also omit the semi-colon on all the lines except the last. The semi-colon breaks the chain of method calls.

Let's turn to a more advanced case of chaining, along with some other cool tricks that jQuery can do, namely

  1. Creating elements, which you can do by putting HTML code (with angle brackets) in the selector. Such an element is not (yet) attached to the web page. You can think of it as being off stage.
  2. Modifying the created, unattached element.
  3. Attaching the element to the web page.

Let's see it in action on this list, repeated from above, but now with the ID characters2

  1. Harry
  2. Ron
  3. Hermione
  4. Fred
  5. George
  6. Cho
  7. Cedric
  8. Draco
  9. Crabbe
  10. Goyle

The code above creates a new empty list item, sets its contents to Percy, adds the Gryffindor class to give it the correct styling, adds some addition CSS to strike him out (since he's such a git), and finally attaches it to the page at the end of the element whose ID is characters2 (our list).

You don't have to use the chaining technique if you don't want to, but it can be very clear to read (once you are used to it) and it is commonly used in online tutorials and examples. We will use it whenever it's convenient.

A Pitfall

Common practice for many years has been to put JS code in the HEAD of a web page, but that lays a trap for us. If we write some JQ code to find an element and do something to it, as we've done many times in this reading, but the HTML for that element is further down on the page, the element will not exist when the JQ code runs. Here's an example:

<head>
   <!-- load jQuery -->
   <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
  <script>
    var d = new Date();
    $("h1").html("News for "+d.toLocaleDateString());  // insert date into H1
  </script>
</head>
<body>
  <h1>News for Today</h1>  <!-- replaced by today's date -->
  ...

Our intention is pretty clear: find the H1 and insert today's date in it. However, when the JavaScript/jQuery code runs, the H1 does not yet exist, so it won't get filled in with today's date.

Even worse, we won't get an error message! jQuery successfully matched a set of elements; it just happened to be the empty set, which is fine by jQuery, if not for us.

Is the DOM ready?

The pitfall we just described leads to the important question of when our jQuery code should be executed. Putting the code in different parts of the HTML file might have different effects on the page, based on when the browser reads and interprets the code. This is why, normally, the jQuery code should be executed only after the DOM has been created and is ready for dynamic manipulation.

Most examples you'll see in the provided reading, will show code usually wrapped in a big event handler for the document object, as shown below:

$(document).ready(function(){

  // all other jQuery code goes here

});

For example, the date insertion we did above would be done like this:

<head>
   
   <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
  <script>
   $(document).ready(function () {
      var d = new Date();
      $("h1").html("News for "+d.toLocaleDateString());
   });
  </script>
</head>
<body>
  <h1>News for Today</h1>
  ...

This works correctly, but is complex to understand. It uses the jQuery wrapper function with the special document object and the result gets the ready() method is triggered when the DOM is ready), and to this method it passes as an argument an anonymous function. It's also a syntactic nightmare: notice that the final line is });.

Another way to make sure that the DOM is ready is to put the JavaScript code at the very end of the page (right before </body> instead of in the head. This way, we know that the previous HTML lines have been already processed by the browser and the DOM is ready. In other words, the following code would also work for putting today's date in the H1 element, and is simpler and easier to understand:

<head>
</head>
<body>
  <h1>News for Today</h1>
  ...
   
   <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
  <script>
    var d = new Date();
    $("h1").html("News for "+d.toLocaleDateString());
  </script>
</body>

In this class, we'll load jQuery and put our code at the end of the file, when the DOM has been built and is ready.

Avoiding $(document).ready(function(){..});

We taught you about $(document).ready() not because we will use it in this course, but because it is extremely common in examples and tutorials about jQuery on the web. We want you to be able to understand those.

We'll learn more about jQuery this semester. If you can't wait, there are many good tutorials online. One place to start is W3Schools jQuery Tutorial.

Loading Code From Another File

jQuery can help us with a common pitfall in larger websites: the problem of copied code. For example, suppose every web page of a 10-page website (like your CS 110 project sites) has the same navigation bar. So, all 10 pages have the same HTML, something like the following (assume there's also some nice CSS to lay out the links and make them look pretty).

The obvious thing to do is to copy/paste those lines to each of the 10 pages of your site. That works fine, but if the boss decides to change the nav content (say, adding another link), you'll have to edit all 10 pages of the site. Note that if the boss just wanted to change the CSS, you'd be able to just change the shared CSS file. Having things just written once is a big advantage.

Using jQuery, we can mitigate this problem. We can put the master copy of the nav on the home page, and use jQuery to dynamically copy that content to the other pages. The other pages have an empty element where the nav will be copied to:

    <div id="nav-goes-here"></div>

Then, they have some jQuery code that looks like this:

$("#nav-goes-here").load("home.html nav");

That incantation dynamically loads home.html into memory, pulls out the <nav> element and inserts it into the element whose ID is #nav-goes-here.

Additional Material

You can stop here if you like. The following is for the interested reader.

Suppose we had some class definitions that we wanted to use:

.gryffindor { border: 2px solid red; background-color: gold; }
.slytherin  { border: 2px solid green; background-color: silver; }
.hufflepuff { border: 2px solid black; background-color: yellow; }
.ravenclaw  { border: 2px solid blue;  background-color: bronze; }
Hermione Granger
Hermione Granger as played by Emma Watson

Here's the source code for the figure above:

<figure id="fig2a">
  <img src="potterpics/hermione-granger-thumb.jpeg" alt="Hermione Granger">
  <figcaption>Hermione Granger as played by Emma Watson</figcaption>
</figure>

Click the button to change the figure to use Slytherin's colors. Try changing the code and clicking again to change to Gryffindor's colors.

Append Elements

TBD

Remove Elements

TBD

Some jQuery Methods

Here is a list of jQuery methods used in our interactive example or in the assignment for this week.

  • .ready()
  • .append()
  • .appendTo()
  • .click()
  • .show()
  • .hide()
  • .html()
  • .text()
  • .attr()
  • .val() // for input fields
  • .parent()
  • .clone()
  • .addClass()
  • .removeClass()
  • .find()

To see more examples and explanations for these methods, you should consult the jQuery API documentation.

Forms

Reading: Chapter 14 of your book Head First HTML and CSS discusses HTML Forms. At this lecture, we will not discuss how forms talk to the server, but will only focus on the HTML elements that go into a form, see pages 652-659 (What can go in a form) and 662-672.

This reading is entirely about HTML, but forms are the primary way of getting input from the user, and we will then turn to how that input can be accessed using the DOM and jQuery and then processed by our JavaScript code. To add the form processing functionality, we'll have to learn about events and event handlers, which is in the next reading. This reading is just HTML.

We will not be covering all aspects of HTML forms. We'll focus on just a handful that are useful in this course. If you want to learn more, there's some additional material at the end, and you're welcome to talk to one of us. The most important kinds of inputs we'll learn are:

  • text inputs (a single line of text, such as someone's name or favorite color
  • textareas (longer blocks of text, such as someone's address or blog entry)
  • menus (one of a set of choices, pre-defined by the form's author, such as
  • buttons, which don't so much give input as trigger behavior.

The form tag

HTML has a dedicated tag, form that is used as a container to package data that might be sent to a web server. The attribute method of the element allows the form to either request data from the server (method="GET"), or send data to the server (method="POST"). However, in order for both these operations to happen, the server needs to have some dedicated programs (also known as scripts) that can deal with the form data. At this point, we will not talk about how this happens (we'll postpone this discussion for later in the semester), and only concentrate on the HTML elements that are contained inside the form.

Let's see an example form, and then we'll look at the code that creates it.

A note on styling

If you see the above form outside an HTML page with CSS, it will look different. Our lecture page applies styling to it that is not the default way a browser will display a form. Please see how the unstyled form looks like.

Additionally, keep in mind that all form elements are inline elements, therefore, in order to appear in separate lines, we wrap them in p elements.

Here's the code that creates that form:

  

As you can see, there's an outer FORM element that wraps up the form inputs. There are input elements that correspond to different places where the user can enter information. Most of the inputs use the INPUT tag, but some use tags like SELECT (for a drop-down menu) and TEXTAREA (for larger blocks of text). The general term is control. Finally, there's a BUTTON input at the end. In a more complete example; clicking this button would send the form data to the web server; this one doesn't do anything.

Form Fields

Let's look at the different input elements. The following table shows the HTML syntax for including different HTML elements in a form. As you will notice, the most common element is <input>, which, based on the value for its attribute type will display a different kind of input. Play with the rendered version of a tag in every row in the table.

Tag Name Rendered Tag More Info
<input type="text">
Your Age: <input type="number" min="1" max="120">
Your Age:
<input type="range" min="100" max="200">
<input type="date">
<input type="time">
<button type="button">Click me</button>
<textarea rows="2" cols="10"> You can type here</textarea>
<select><option>Black <option>White </select>

For more information on the form elements and all its fields, consult the W3Schools page on forms.

Let's look at some of the more important controls, and then other aspect of

The INPUT Tag

The input tag is fairly straightforward, but you can specify the type of input you are looking for, using the TYPE attribute. It has many more types, which we are not listing here; consult W3Schools page for input to see the complete list. Here are just a few:

  • TEXT: allows the user to type in a word or phrase
  • PASSWORD: allows the user to type in a word or phrase, but its value isn't echoed, so no one can look over their shoulder and see it.
  • email: like a text type, but should look like an email address. New with HTML5.
  • date: for entering dates. New with HTML5.
  • time: for entering times. New with HTML5.

Some of these types (such as time, date, number, range, etc.) were introduced in HTML5, which means that not all browser versions are able to support them. For maximum portability, you should stick to type=text. However, sliders like we get with type=range are fun, and we'll use them in this course.

The SELECT input

To specify a menu, from which the user can choose only one option, you use the SELECT tag inside the form. You specify the NAME of the input in the SELECT tag, and each menu item is specified using the OPTION tag. Here's an example:

<form action="">
  <p>Drink:  <select name="beverage">
      <option value="">choose one
      <option value="Coke">Coca-Cola</option>
      <option value="Pepsi">Pepsi-Cola</option>
      <option>Beer</option>
      <option>Wine</option>
   </select>
</form>

(The closing </option> tag is optional, like a closing </p> tag or </li> tag, but it's best to use it.) Any option can have a separate "value" attribute; if none is specified, the value is the option itself.

Specifying a non-option as the first item in the list helps to tell whether someone has actually made a choice or just overlooked this menu. Making the non-option have a value of the empty string helps with validating the form.

The TEXTAREA input

If you want to allow your user to type in a long response, you should define a textarea inside your form. This tag has attributes called ROWS and COLS that let you specify the size of the area.

<textarea name="thoughts" rows="3" cols="40">
A chicken is an egg's way of making another egg
</textarea>

The default value is the region between the beginning and ending tag. Typically, you want the default value to be empty, so put the tags right next to each other, as in this example here:

<textarea name="thoughts" rows="3" cols="40"></textarea>

Don't let even a single space creep in, or the initial value will be a string of one space, and not the empty string. That will affect any code that cares about the default or original value, such as certain kinds of validation

Labels

A form consisting of a bunch of bare boxes would be useless, so how is the user to know what input box means what? That's done with the label tag. There are two ways the label can be used. One option is to wrap the input in the label:

<label>
  Given Name
  <input type="text" name="givenname">
</label>
<label>
  Family Name
  <input type="text" name="familyname">
</label>

The other is to give the input an ID and reference that ID in a for attribute of the label:

<label for="givenname">Given Name</label>
<input type="text" name="givenname" id="givenname">
<label for="familyname">Family Name</label>
<input type="text" name="familyname" id="familyname">

The latter is a bit more work, but is necessary in some cases where the structure of the HTML doesn't allow the input to be a child of the label, as with a table.

Name and Value

When the form gets submitted, the form data gets sent to the server. It gets sent as a set of name/value pairs, which we can think of as like a little table. Here's some data as if from our pizza form:

namevalue
customerHermione
phone555-8888
addrhgranger@hogwarts.ac.uk
sizelarge
due21:00
instructionsplease deliver by owl

Since the fields of a form need to be processed both by Javascript code on the client-side (by the browser) and the scripts on the web server, it is necessary to use the different attributes of these elements to distinguish and access them.

Consequently, the two most important attributes that we will use very frequently are name and value.

  • The name attribute is used by Javascript to reference the HTML elements that use it, but most importantly is used by the server to distinguish between the different fields of the submitted form. We will discuss it again later when we talk about submitting the form to the server. In the meantime, it will be good practice to start using it everytime we create form fields.
  • The value attribute is an attribute that can be either set explicitly in the HTML code to give an initial value to the elements, or will be set implicitly by the browser when the user enters a value in the field or selects some option (as from a menu). For example, <input type="text" value="Wellesley"> will show an initial value in the text field: , that can be overwritten by the user.

Size of Text Inputs

To control the width of the text input field, you don't use the attribute width, but the attribute size. For example, <input value="Wellesley" size="10"> will now be much smaller than in the example above: .

Placeholder

Another useful attribute for input controls is placeholder, which can be used to provide a hint for the kind of value that should go in a field. For example, this HTML <input type="text" placeholder="Enter your name"> will be rendered like this: .

Form Validation

Later in the course, we'll talk about submitting the form data to a server for more elaborate processing, but before we do that, we should discuss validation. What is form validation? Essentially, it means checking to see that the form has been filled out correctly (as far as we can tell).

Form validation could be used to ensure that someone hasn't overlooked a text input, menu or radio button group, and can check that, for example, the zip code is 5 digits (or 9) and that a telephone number is 10 digits, and that an email address looks like an email address.

Form validation can actually cancel the submission of the form, so that the data never leaves browser. The reason we validate forms is twofold: to give the user immediate feedback that they've missed something, instead of waiting for the server to respond, and to protect the server from having to handle all those invalid forms. Of course, a determined nefarious person can simply disable our form validation JavaScript and hammer our server with invalid forms, but that's rare. The vast majority of invalid forms are just human error.

Obviously, the browser can't tell whether you entered your correct phone number, but it can check that you typed the right number of digits (and only digits). Similarly, it can't check that your spelled your name correctly (and whether your name really is Mickey Mouse), but it can check that you didn't leave that input blank.

With HTML5 and modern web browsers, form validation has gotten a lot easier. In the past, web developers would write JavaScript code that would look at the values in the form to check for bogus values. They wrote libraries and jQuery plug-ins to make the job easier for others. Indeed, there is a jQuery plug-in by Jörn Zaefferer called validation that does a good job and is well described in our book, JavaScript & jQuery: The Missing Manual, pages 278-300. Please read that, and the on-line documentation linked above, if you're curious.

However, the vast majority of form validation can be done with a few simple things:

  • Add the attribute required to any input that you want to require the user to fill out.
  • Use the fancy new form input types that HTML5 has added, such as:
    • tel, for telephone numbers
    • email, for email addresses
    • date, for just a date (year, month, day)
    • time, for time (hour, minute, seconds)
    • datetime, combining date and time inputs
    • and others

Here's a demonstration. (Note that I didn't re-use the input names from the earlier example because the JavaScript code above referred to the inputs by name, and so we need to make those unique. I could also have used a nested selector and given each form its own ID.)

<form action="/cgi-bin/dump.cgi">
  <p>Username: <input required name="username">
  <select required name="hogwarts_house">
    <option value="">Hogwarts House</option>   
    <option>Gryffindor</option>
    <option>Hufflepuff</option>
    <option>Ravenclaw</option>
    <option>Slytherin</option>
  </select>
  <p>Email address: <input required name="email" type="email">
  <p>Birthday: <input required name="birthday" type="date">
  <p><input type="submit" value="submit form">
</form>

Here's the actual form, so you can change the values of inputs:

Username:

Email address:

Birthday:

Try to submit an incomplete form!

Additional Material

You can stop here. The following information is just for those interested in learning more.

TBD

Radio Buttons

Important: Radio and checkbox input items should all have the same name, so that they are considered as related. (Our radio buttons on the pizza form were all named size.) Without the same name, radio buttons will not be mutually exclusive.

Tag Name Rendered Tag More Info
<input type=radio> Small Small
<input type=checkbox> Bacon Bacon

Checkboxes

Fieldset and Legend

There are additional elements related to a form, that we saw in the example above, such as label and legend, who are used for accessibility, or fieldset to group together elements in a form. By default, the browser will draw a box around all the elements in a fieldset (as we saw in the unstyled form).

Access Keys

Events

Events

Our websites have so far been pretty passive: they present material for the user to read or look at, but nothing more interactive. Now that we know about forms, our code can process input from the user and dynamically modify the page. We just need a few more concepts to make a page that is interactive:

  • Events: these are things the user does, such as clicking on something or submitting a form.
  • Event Handlers: these are functions that we define and that the browser will invoke when a particular event occurs.
  • Getting values out of forms when we want to know what the user entered.

Let's start with the last item.

Getting Form Values

jQuery has a convenient method for retrieving the value of an input, the .val() method. The selector should be anything that selects the input, such as its id. Here's a form with three inputs:

The IDs of the three inputs are customer1, pizza_kind1, and num_slices1.

Fill out the form and use the following execution box to retrieve the values:


The .val() method works just like other jQuery methods: the wrapper function selects the element you want to operate on, and the method does the work. Here, it pulls the value out of the input.

Note that values from forms are always strings, even if the form says that the input is type number. If you want it to be a number, you have to use parseInt or parseFloat, just as we did with values returned by prompt.

Now that we know how to use forms, we'll never need prompt again.

Units Conversion

Let's build a slightly useful form: one that will allow the user to do metric conversions. They will enter a number of pounds, and the form will compute the conversion to kilograms. (One kilogram is 2.2 pounds.)

We'll define two functions to do the work:

  • pounds2kilograms, which takes an argument of pounds (a number) and converts it to kilograms, returning the number of kilograms. This is a generic function that might be useful in a wide variety of problems.
  • doConversion, which pulls the numberof pounds out of the form, converts it to a number, invokes the first function to get the number of kilograms, and then inserts the answer, formatted with 1 decimal place, into the span above.

Here's the source code for the form we will use:

<form>
  <p><label for="pounds1">Pounds</label>
    <input type="text" name="pounds" id="pounds1">
  <p><button type="button" id="convert1">Convert</button>
  <p><span id="kg1"></span> kilograms</p>
</form>

Here's the live form. The button doesn't do anything yet.

kilograms

Here's the code to execute:


At this point, we almost have a working form. What we need is to set things up so that instead of the execution box invoking the doConversion function, the user can cause it be be invoked by clicking on the button.

To re-phrase that in the terminology of this reading, we want the doConversion function to be an event handler for the event of the user clicking on the button.

jQuery has a convenient method of attaching a function to some element in the document so that the function gets invoked when the element is clicked on. That method is the .click() method. Here's how we will do it:

$("#convert1").click(doConversion);

Notice, by the way, the lack of a pair of empty parentheses after the function name, doConversion. That's because we are not invoking the function here. Instead, we are handing it to jQuery to be attached to the web page as an event handler. To use our earlier metaphor, we are passing the function as a machine, like a blender or meat grinder, for someone else to use, but we are not pressing the on button right here.

Here's our revised code:



Let's see the code in action. Here's a duplicate form, but now the IDs end in 2 instead of 1:

kilograms

Go ahead and try the form!

Events and Event Handlers

The preceding section showed a particular example of a event handler (the doConversion function). It will be invoked to handle a "click" event on that particular button. Let's step back and discuss more generally what these things are.

An event is something that happens in the browser, often initiated by the user, but not always. Some examples:

  • an element is clicked on
  • an element is moused over
  • the HTML is loaded and the DOM is ready (we saw this in the reading on the DOM)
  • some data finishes loading from the server
  • a timer has expired
  • some keys are pressed on the keyboard

There are others, but these are more than enough for our purposes.

An event handler is just a function that will be invoked when a particular event occurs. In other words, it's not a special kind of function, it's a particular use for a function. That said, for our purposes, an event handler will be a function that takes no arguments and returns no values, because that's how it will be invoked. (That's not strictly true, but it is close enough for now.)

Hide and Show

Our forms don't have to have lots of inputs; they can consist of just a button or two. Here is a form with just two buttons. Try them, and watch the picture below!

Harry Potter
Fig1: Harry Potter

Here's the code. You'll notice that there are two simple functions that hide/show the element whose ID is fig1. You're welcome to try them from the JS console; there's nothing special about them. Then, we have two lines of JQ that attach those functions to the two buttons.

function hideFigure1() {
    $("#fig1").hide();
}

function showFigure1() {
    $("#fig1").show();
}

$("#hide1").click(hideFigure1);
$("#show1").click(showFigure1);

The this Object

Suppose we had a long list of items, and we want to allow the user to click on any one of them to make them disappear. Here's an example of the behavior we want:

  1. Harry
  2. Ron
  3. Hermione
  4. Neville
  5. Luna
  6. Ginny
  7. Draco
  8. Crabbe
  9. Goyle
  10. Cho
  11. Cedric

Clearly, we could give each of these 11 items a different ID, we could define 11 functions that are all pretty much the same except for the ID of the thing they are hiding, and attach each function to one list item. Something like this. I've written the functions on one line both for brevity and to make it easier to compare their code.

function hideItem1() { $("#elt1").hide(); }
function hideItem2() { $("#elt2").hide(); }
function hideItem3() { $("#elt3").hide(); }
...

$("#elt1").click(hideItem1);
$("#elt2").click(hideItem2);
$("#elt3").click(hideItem3);
...

Code like that is tedious and boring, and it doesn't scale well. If we had a list of the 50 states in the US, or 196 countries in the world, the code is excessively tedious and boring. There must be a better way, and there is.

The idea is to attach the same function to each item in the list, so we only have to define one function. The function, however, has to figure out which item to hide. In this case, the answer is the one that was clicked on.

Any time an element is clicked on, the special variable this contains the element. So, in the example above, if you click on the first element in the list (Harry), the hideItems1 function runs, but this contains that LI. Similarly for all the others.

Here's our revised code:

function hideItem() { $(this).hide(); }

$("#char_list li").click(hideItem);

Try it!

One important part of the code is the selector, "#char_list li", which matches all 11 LI elements in that list in one, easy but powerful bit of code.

The key piece of code, of course, is the following:

$(this).hide();

That code uses this as the selector, taking that element on the page and wrapping it up with all the jQuery methods, including the .hide() method. Before, we've always seen the selector contain a string literal, describing the element or elements to be operated on. Here, we have, essentially, a magic variable whose value is just the thing we want.

The technique of using the this variable is fairly complex and advanced, and we won't need it often, but it's good to know about.

Galleries and Drop-Downs

In this reading, we'll see the DOM and jQuery in action. We'll create an image gallery and then a drop-down menu.

Image Gallery

Often, you want to display a set of pictures and allow the user to choose which ones to look at more closely, something like an art gallery. Therefore, we'll call this JavaScript application a gallery. We'll have an arrangement of small pictures, often called thumbnails, and, if the user clicks on any one of them, a larger version is displayed.

Note that one advantage of a gallery is that a set of thumbnails can load quicker than even one of the larger versions, if the file sizes are much smaller. Therefore, you should go to the extra effort to make thumbnail-size images, using an image editor (like PhotoShop or Pixlr or the Gimp), rather than just using the width and height attributes to make the squeeze the big files down to a small screen area.

Gallery Example

This will just be a small gallery, with just four pictures. In this version of the gallery application, we'll allocate space on the page for the larger version. In this example, we'll put a boring pale-yellow image there. If you decide to build a gallery application, you could choose one of the large images, either randomly or deterministically, or something else entirely.

Please try this gallery example

Lightbox Gallery

An alternative is to have the large image take over the window, putting everything else behind a semi-transparent dim filter, so that the user's attention is necessarily on the large image. This is called a Lightbox, and has been implemented many times since its originator, Lokesh Dhakar. We've implemented a very simple version of it; there are many more sophisticated ones. The lightbox, of course, requires an additional bit of coding to make the image go away so that the user can look at another image or do anything else.

Please try this lightbox gallery

How It's done

Creating a gallery involves first putting a set of thumbnails on the page. That can easily be done by copy/pasting a bunch of HTML, like this:

<figure data-bigsrc="../potterpics/harry-potter-big.jpeg" data-alt="Harry Potter">
  <img src="../potterpics/harry-potter-thumb.jpeg" alt="Harry Potter">
  <figcaption>Harry Potter</figcaption>
</figure>  
<figure data-bigsrc="../potterpics/hermione-granger-big.jpeg" data-alt="Hermione Granger">
  <img src="../potterpics/hermione-granger-thumb.jpeg" alt="Hermione Granger">
  <figcaption>Hermione Granger</figcaption>
</figure>  
...

That's acceptable, but a bit tedious and error prone. When you copy/paste the code, you have to remember to change all the places where we see "Harry Potter" to "Hermione Granger." If you miss one, rabid fans will notice when the caption for Hermione says Harry.

An alternative is to define a function to create one of these gallery items:

function addToGallery(galleryID,thumbsrc,bigsrc,alt) {
    console.log("add figure "+thumbsrc);
    var img = $("<img>")
        .attr("src",thumbsrc)
        .attr("alt",alt);
    var cap = $("<figcaption>"+alt+"</figcaption>");
    $("<figure>")
        .attr("data-bigsrc",bigsrc)
        .attr("data-alt",alt)
        .append(img)
        .append(cap)
        .appendTo(galleryID);
}

You can then invoke it with the necessary info. You'll notice that there's still a lot of repetition, but because only the key info is shown, it's easy to be thorough. (We could also define a higher-level function that could create the proper URLs, if we used a simple naming scheme. We won't describe that here.)

addToGallery("#gallery1",
             "../potterpics/harry-potter-thumb.jpeg",
             "../potterpics/harry-potter-big.jpeg",
             "Harry Potter");
addToGallery("#gallery1",
             "../potterpics/hermione-granger-thumb.jpeg",
             "../potterpics/hermione-granger-big.jpeg",
             "Hermione Granger");
...

DATA attributes

You probably noticed the two attributes starting with data-. Here's the code again:

<figure data-bigsrc="../potterpics/harry-potter-big.jpeg" data-alt="Harry Potter">
  <img src="../potterpics/harry-potter-thumb.jpeg" alt="Harry Potter">
  <figcaption>Harry Potter</figcaption>
</figure>  

We've learned about lots of tag attributes in HTML, such as SRC for IMG and HREF for A. Those are all built into the HTML language. These data- attributes are something new. They aren't built into the language, but we (the authors of the web page) get to make them up. More precisely, the prefix data- is built into the language, but we get to make up the suffix.

When we click on the figure, which we'll turn to in a moment, we'll need the SRC and ALT for the big version, so we stash the values here. Is this legal? Yes. The design of HTML5 anticipated the need for data sprinkled throughout the DOM tree, and explicitly allowed the user to create any attributes they want, as long as they start with data-. So, we're putting that information there so that it'll be there when the event handler needs it.

Where the Big Picture Goes

We also need a place to display the big version of the picture. (This is the main difference between the simple and lightbox version of the gallery.) For the simple version, we just need a figure:

    <figure id="large_image">
      <img src="../potterpics/pale-yellow-266x200.png" alt="filler image">
      <figcaption>A pale yellow image filler image</figcaption>
    </figure>

We put the pale yellow box there just so that the IMG has a SRC when the page loads. We should probably put an image from the gallery in there, but this explanation is a little clearer if there's a different image there at the beginning. We would use CSS to make this figure larger.

Adding an Event Handler

Finally, all the pieces are in place for the image gallery. We'll define a function that will be attached to each thumbnail, and it'll cause the larger version to be displayed in the figure#large_image that we just saw. Here's the code:

function enlargeGalleryImage() {
    var bigsrc = $(this).attr("data-bigsrc");
    var alt = $(this).attr("data-alt");
    $("#large_image img")
        .attr("src",bigsrc)
        .attr("alt",alt);
    $("#large_image figcaption").html(alt);
}

Next, we have to attach it to every thumbnail in the gallery:

$("#gallery1 figure").click(enlargeGalleryImage);

This function is hard to understand because it is abstract: there's just the one function, but it's used for 4 or 400 thumbnails. For each of those thumbnails, a different enlargement has to be loaded. Fortunately, we put the URL of the enlargement on the figure that was clicked on, so we can find out the URL using the magic variable this. Here's the key part:

    var bigsrc = $(this).attr("data-bigsrc");

Each thumbnail as a data-bigsrc attribute, and the event handler can grab that attribute out of the thumbnail. Which thumbnail? The one that was clicked on, which is stored in this.

All the rest of the code is stuff we've seen before. The key step is here:

    $("#large_image img")
        .attr("src",bigsrc)

That sets the src of the large img to the appropriate value.

The other lines of code are doing similar things for the alt attribute, and we also use the alt attribute to fill in the figcaption.

How Lightbox Works

The lightbox is pretty similar, except that the destination is large and takes over the screen, using CSS:

    <div id="lightbox_display">
      <div id="lightbox_inner">
        <figure>
          <img src="../potterpics/pale-yellow-266x200.png" alt="filler image">
          <figcaption>A pale yellow image filler image</figcaption>
        </figure>
      </div>
    </div>

Here's the CSS.

      #lightbox_display {
         position: fixed;
         top: 0px;
         left: 0px;
         width: 100%;
         height: 100%;
         background: black;
         background: rgba(0,0,0,0.8);
         display: none;
      }

      #lightbox_display figure {
         background-color: white;
         width: 75%;
         margin: auto;
      }

      #lightbox_display figure img {
         width: 100%;
      }

The key ideas are that the outer box, lightbox_display, is fixed and as big as the screen. Inside that is a figure that is slightly smaller and centered, with a white background. Inside that is an image where the big version is displayed.

The event handler is very similar to the simple version, except we add the .show() at the end to make the lightbox visible.

function openLightboxImage() {
    var bigsrc = $(this).attr("data-bigsrc");
    var alt = $(this).attr("data-alt");
    $("#lightbox_display img")
        .attr("src",bigsrc)
        .attr("alt",alt);
    $("#lightbox_display figcaption").html(alt);
    $("#lightbox_display").show();
}

Of course, since the big version takes over the display, we have to set up a click handler to hide it when the user wants to make it go away:

function closeLightboxImage() {
    $("#lightbox_display").hide();
}

$("#lightbox_display").click(closeLightboxImage);

That's the essentials of how image galleries work.

Drop-Downs

We now turn to drop-down menus, which will use many of these same ideas:

  • The this variable
  • Things that appear and disappear when clicked on, or
  • make other elements appear and disappear.

Drop-downs also involve some new concepts:

  • finding a child element
  • determining whether an element is shown or hidden
  • event propagation

This will take us a few steps, so be patient.

Positioning

When we first learned about .hide() and .show(), the page would have to be re-arranged based on whether the target element was shown or hidden. Try the following example, clicking on the header list item:

  • header
    • Harry
    • Ron
    • Hermione

Notice how the page (particularly this paragraph) jumps up and down based on whether the submenu is shown? We don't want that with a drop-down menu.

We solve this by using position:absolute on the menu, and positioning it relative to the header. Here it is in action:

  • header
    • Harry
    • Ron
    • Hermione

The html code looks like this:





And the CSS like this:





The auto value makes the browser calculate the value to use, thereby positioning the menu in the same place as it was in the first example, but using absolute positioning. We added the height just so the menu wouldn't overlap this paragraph when it was shown.

Toggling

Now let's turn to the JavaScript. Let's start with toggling whether something is open or closed, as we did above. Here's the JavaScript code for the previous example:




The event handler gets the menu, using the selector #ex2 ul, and determines whether it is hidden. It's hidden when its CSS is display:none, which we can determine via an alternate usage of the .css() method. We're accustomed to a 2-argument usage, like this:

$(selector).css("property","value");

Instead we have this:

var curr = $(selector).css("property");

This usage reads the current value of the property. In this case, we're reading the display property and putting it in a variable of the same name. The next lines check the value and if it's "none", the child is hidden, so we should show() it, otherwise, hide() it.

If we replaced those list items (Harry, Ron, and Hermione) with hyperlinks, we actually have a working drop-down menu:

Presto! A drop-down menu!

Multiple Menus

Chances are, you will have multiple drop-down menus, like this:

  • Characters
    • Harry
    • Ron
    • Herminone
  • Houses
    • Gryffindor
    • Hufflepuff
    • Ravenclaw
    • Slytherin
  • Teachers
    • Dumbledore
    • Flitwick
    • McGonagal
    • Snape
    • Sprout

We've done a little CSS magic to lay those out horizontally. Note that we use several selectors of the form A < B. That is a child selector, which is a variant on the descendant selectors that we already know, but instead of B being any descendant of A, B must be a child of A.








Let's take a look at the JavaScript code to toggle these menus (at least the first one):





The code is the same as before, but we'd need two more copies of it (suitably modified), one for each sub-menu. Later in the course, if there's time, we'll discuss a better, more abstract way to do this. For now, if you'd like, we'll turn to an important but complicated improvement.

Click Anywhere to Close

(The rest of this reading is optional.)

There's one small flaw with our drop-down menus, and that is the expectation that users have. If they open a menu and then decide that they don't want to go to any of those pages, they have to click again on the header to close the menu. Most people are used to being able to click anywhere else on the page to close an open menu.

Doing that is cool and worthwhile, but tricky and requires some additional concepts. The first concept is putting an event handler on the whole document (the top of the DOM tree). That event handler will close the open menu. Let's go back to a simpler menu, but with our first attempt at that behavior. Try the following, which doesn't work. We'll soon see why, but for now, let's try to understand this attempt.

  • header
    • Harry
    • Ron
    • Hermione

Here's the source code for the additional behavior, which adds an event handler on the document that closes everything, so that we can close an open menu by clicking someplace else in the document.

  



Note that we named the function closeAll, because it will close any open menu on the screen. As we've seen, there might be multiple menus, and this function won't necessarily know which one is open, if any. We could go to a lot of effort to figure out which menu is open, or we could just use the power of jQuery to close every one of them, whether they are open or not. We prefer the simpler approach. That is to put a CSS class on each header LI and then select every UL child of those LI elements. We then invoke the .hide() method on them.

You'll notice that the menu is initially hidden, which is what we usually want to do with drop-down menus. We do this by invoking the closeAll function in our code, above.

We then attach the closeAll function as a click handler to the document.

But why doesn't clicking on the header work to open the sub-menu? Is the event handler even running? Let's look more closely at the code:





First, we defined a log5 function. That's just for debugging: it prints a message to the JS console, along with a counter, so we can tell one message from another. Next, the same event handler code as before, only augmented with the log5 calls.

Now, open your JS console and try clicking on the header. You'll see that the toggle5 function is indeed being invoked, but the closeAll function is also invoked!. So, the menu is opened and instantaneously closed. Why?

The answer is that clicking on the header not only counts as clicking on the header but also counts as clicking on the document.

Event Bubbling

In retrospect, it makes sense that clicking on the element also counts as clicking on the document, but it's still surprising. This phenomenon is called event bubbling, because an event bubbles up the DOM tree from the leaves to the root, like champagne bubbles going from the bottom to the top of the glass. Every element on the path from the leaf (like the LI) to the root (the document) gets a chance to react to the event. It's also called event propagation.

In this case, the normal event bubbling gets in our way. Is there a way to cancel the event propagation? Yes, but it takes a few steps.

First, our event handler is, in fact, invoked with an argument; it's just that we've been ignoring it up to now. jQuery ensures that our event handlers is invoked with an object that represents the event, including information about what event it was (click, mouse motion, keyboard events) and stuff like that. That event object has a method called stopPropagation(), which does exactly what we want.

So, our new and improved toggle function is going to accept an argument that is an event object, and it will use that argument to stop the propagation of this event up the tree:

  • header
    • Harry
    • Ron
    • Hermione

Here's the source code for fancy new toggle6 function:

  



Try it!

You're now prepared to understand all the code in this drop-down example.

Arrays and Slideshows

In this reading, we'll learn how to build slideshows, both manually advanced and automatic (sometimes called a carousel). We'll also see how to put a random image on a page.

All of these cool JavaScript applications rely on several ideas:

  • We'll have a numbered list of images
  • We need a way of getting one of the images using its number

Both of these ideas are implemented in a fundamental data structure called an array.

Arrays

Arrays are found in every programming language; they're that important. There are sometimes minor differences, but the basic idea is the same:

  • A storage structure for multiple pieces of information (data),
  • where each piece of information (datum) is in a numbered position, and
  • a particular piece of information can be retrieved by its number (called its index).

Imagine that we have a JavaScript program that needs to record some information about Hermione, including her name, age and the courses she is taking in her third year. (The list of courses is not complete.) Here's how we might picture it:

visualization of hermione's array of courses
Visualization of hermione's array of courses

Here's the JS code that would produce that arrangement of data:

var name = "Hermione Granger";
var age = 13;
var courses = [ "Astronomy",
                "Arithmancy",
                "Ancient Runes",
                "Care of Magical Creatures",
                "Muggle Studies",
                "Potions",
                "Divination" ];
  

Try copy/pasting that code into the JS console and then looking at the contents of each variable.

Syntax

In the previous example, we used the syntax for an array literal, where all the values are known in advance. That's what we'll do most of the time in this course. A few things to note about the syntax:

  • The array is enclosed by square brackets: [].
  • Each item is separated from the others by commas. An array of three elements looks like this: [ "Harry", "Ron", "Hermione" ]
  • There's no comma after the last item. An array of one element looks like this: [ "Voldemort" ]
  • It can appear on the right-hand side of an assignment statement just like any other value. It's just longer, so we typically spread it over multiple lines. But short ones can be done on one line:
    var friends_of_harry = ["Ron", "Hermione"];
  • Arrays can hold any kind of data, not just strings. Here's an array of numbers stored in a variable.
    var scores = [17, 23, 25, 29, 37];

Compound Data and Indexing

So far in this course, we have learned about different types of data:

  • Numbers
  • Strings
  • Booleans
  • Dates

With the exception of dates (and objects in general), each of these seems like a single piece of information. With arrays, we have a collection of information, so we call an array a data structure. Indeed, it is a compound data structure.

So, given the different items in the array of Hermione's courses, how do we extract a particular item? We do that using an index, which is just the numerical position of the item in the array.

Note: the numbering of the items starts at zero. So, item zero in the array above is "Astronomy" and item 6 is "Divination". This is an oddity of Computer Science, but it's quite consistent. (The reason for it is that the low-level implementation is that the index is the distance from the beginning or the number of items to skip to get to the desired one. So, naturally, the first one is index zero.)

Try the following:

var courses = [ "Astronomy",
                "Arithmancy",
                "Ancient Runes",
                "Care of Magical Creatures",
                "Muggle Studies",
                "Potions",
                "Divination" ];

alert( "course 0 is "+ courses[0] );
alert( "course 6 is "+ courses[6] );
alert( "course 2*3 is "+ courses[2*3] );
var index = 6;
alert( "course "+index+" is "+ courses[index] );

Note the syntax for getting an item out of the array. We give the name of the variable containing the array, then square brackets enclosing the numerical index of the one we want. In the previous example, we saw three equivalent ways to get element 6 out of the array.

We can even replace an item in an array if we want to. If Hermione drops Divination and replaces it with "History of Magic", we could do this:

var courses = [ "Astronomy",
                "Arithmancy",
                "Ancient Runes",
                "Care of Magical Creatures",
                "Muggle Studies",
                "Potions",
                "Divination" ];

alert( "course 6 is "+ courses[6] );
courses[6] = "History of Magic";
alert( "course 6 is "+ courses[6] );

In our course, we will rarely modify an array. We'll mostly use arrays as numbered lists of information. Nevertheless, it's good to understand. You can think of an array as a bunch of variables, addressed by both name and number.

Length of an Array

Arrays also have a built-in property called length that tells how many elements are in the array. So, for example, if we want to know how many courses Hermione is taking, we can execute code like this:

var courses = [ "Astronomy",
                "Arithmancy",
                "Ancient Runes",
                "Care of Magical Creatures",
                "Muggle Studies",
                "Potions",
                "Divination" ];

alert( "The courses array has "+ courses.length + " elements." );

The indexes of an array will be from 0 up to one less than its length. If the length is 7, the indexes will be from 0 to 6.

Note the syntax:

courses.length

The variable has a dot and then the name of the property. This should remind you of the syntax for a method on an object and that's no coincidence, except that we omit the parentheses because it's just a value, not a function.

Days of the Week

Let's see another example. Earlier, we learned that the date object would tell us the number of the day of the week, but not the name. Partly, this is because the days could vary with language (English versus French) or with the amount of abbreviation ("Wednesday" vs "Weds" vs "Wed" vs "W").

Suppose we want to map the day number to the day name. We could use arrays for this. Not coincidentally, the fact that days are numbered starting at zero will help us. Consider the following function:

function dayNamesEnglishAbbr(dayNum) {
   var names = [ "Sun", "Mon", "Tues", "Wed", "Thurs", "Fri", "Sat"];
   return names[dayNum];
}

alert( "day 0 is "+dayNamesEnglishAbbr(0) );
alert( "day 1+2+3 is "+dayNamesEnglishAbbr(1+2+3) );

This function works like any other, so its argument is still enclosed in parentheses. The value of the dayNum parameter is then used in the square brackets to retrieve the desired name for that day of the week.

If we wanted to be more careful (perhaps the programmers invoking our function are sometimes sloppy), we can check that the value is okay. We can use the length property here:

function dayNamesEnglishAbbrCareful(dayNum) {
   var names = [ "Sun", "Mon", "Tues", "Wed", "Thurs", "Fri", "Sat"];
   if( 0 <= dayNum && dayNum < names.length ) {
      return names[dayNum];
   } else {
      return "invalid daynum";
   }                               
}

alert( "day 13 is "+dayNamesEnglishAbbrCareful(13) );

Slide Show

We now have the foundation on which we can build our slide shows. Here's the basic conceptual structure:

  • We'll have an array of URLs, one for each picture we want to show. We'll call that slides.
  • We'll have a global variable that keeps track of which image we are showing by storing the index of the current picture (slide). We'll call that currentSlideIndex.
  • We'll have a place in the document where we display the current slide. This will work just like a gallery.

Note: it's helpful if all the images are the same dimensions (width and height) or at least the same aspect ratio, so that they will all comfortably fit in the target IMG, without the page having to change its layout. Here, we resized all the images to be 1024 x 768 px, which you'll see reflected in the filenames.

Here's the code we'll write:

var slides = [ "harry-potter-1024.jpeg",
               "ron-weasley-1024.jpeg",
               "hermione-granger-1024.jpeg" ];

var currentSlideIndex = 0;

The HTML for our slide display is familiar. We put a button on top of it to use for advancing the slideshow.



Displaying the Slide

Let's write a function that will display the slide. Since we kept the URLs simple, instead of the full relative URL of potterpics/harry-potter-1024.jpeg tack on that folder name now.

function displaySlide() {
    var file = slides[ currentSlideIndex ];
    var url = "potterpics/" + file;
    document.getElementById("slideshow").src = url;
}

We really should do something about the ALT and the FIGCAPTION, but we'll leave that as an exercise for the reader. Hint: you could have an array of values for each of those.

Advancing the Slide

The easy part of advancing the slide is just to increment the currentSlideIndex and then invoking displaySlide, like this:

// advance and display next slide
currentSlideIndex++;
displaySlide();

The tricky part of advancing the slide comes when we get to the last slide. In our example, we have just three slides, so the indexes will be 0, 1 and 2, but not 3. What do we do then? An easy thing to do is to start over again at zero. To make the function more general, we can have it use the length of the array, so that if we add another image or two, we don't have to modify this code at all. Here's the function:

// advance and display next slide
currentSlideIndex++;
if( currentSlideIndex >= slides.length ) {
    currentSlideIndex = 0;
}
displaySlide();

This will have the effect of making the slideshow seem circular, where it starts over again seamlessly.

The next step is to package this up into a function that can be attached to the button under our figure to act as an event handler. Here's the next step:

function nextSlide() {
    currentSlideIndex++;
    if( currentSlideIndex >= slides.length ) {
        currentSlideIndex = 0;
    }
    displaySlide();
}

We then can add a button to the page and attach this function to the button, like this:

        < img id = "slideshow" src="potterpics/harry-potter-1024.jpeg" height = 200 alt="" >

Here's the final slideshow:

Later, when we learn about animations, we'll learn a cool effect for transitions between slides.

Implementing a previous slide button is left as an exercise for the reader, possibly in lab.

Carousels

A carousel or automatic slide show is just one that advances without the user clicking a button. It's a nice effect, though it can also be annoying if (1) the movement distracts from other information on the page, or (2) the user would like to linger longer on some slides than others. Nevertheless, a carousel is often a very nice effect, so let's learn how to do it.

We already have a function that will advance the slide show, namely the nextSlide function. If there were a way to have the browser automatically invoke that function every so often, we'd have an automatic slide show. It turns out that the browser provides exactly the tool we need, namely setInterval. The setInterval function takes two arguments:

  • A function. This function is being given to the setInterval function, not being invoked, so we'll use the name without the parens after it.
  • A time interval in milliseconds. Every time this many milliseconds has elapsed, the function will be invoked again.

Here's how we would arrange for our nextSlide function to be invoked every 2.5 seconds:

setInterval( nextSlide, 2500 );

Let's see it in action:

Here's the final carousel, with no button needed.

Random Images

In the slideshow and carousel, the code marched steadily through the array from 0 to the end, and then started over again. Something different we can do is to choose a random element of the array. Perhaps you want the opening page of your website to be a little different from visit to visit, so your code will display a random element each time.

To do that, we'll use the following function. This function is not built-in to the JavaScript language or to jQuery, so you'll have to copy its definition to your own .js file. In a later section, we'll learn how the function works, but for now, we'll just trust it.

function randomElt(array) {
    var len = array.length;
    var randIndex = Math.floor(Math.random()*len);
    return array[randIndex];
}

/* ================================================================
example */

var myArray = ["H", "He",
               "Li", "Be", "B", "C", "N", "O", "F", "Ne",
               "Na", "Mg", "Al", "Si", "P", "S", "Cl", "Ar"];
alert("Random Element is "+randomElt(myArray));

Try executing the code above a few times. You should get a different element each time.

So, to display a random element each time the page loads, we just have to employ this randomElt function in a script element, so that it runs when the page loads. Remember that the code has to be after the IMG into which it will be loaded exists.

  var file = randomElt( slides );
  var url = "potterpics/" + file;
  document.getElementById("randomPicture").src = url;

Here it is in action. Try reloading the page a few times:

How randomElt Works

The following is a little mathematical, but explains how the randomElt function works. Here's the code again:

function randomElt(array) {
    var len = array.length;
    var randIndex = Math.floor(Math.random()*len);
    return array[randIndex];
}

We can describe the operations in 4 steps:

  1. Generate a random decimal between 0.00000 and 0.9999999. Call it x (0 ≤ x < 1)
  2. Multiply x by the length of the array. If the length of the array is 3, then 3x is between 0.0000 and 2.999999. Call the value y. (0 ≤ y < 3)
  3. Take the Math.floor of y, which chops off the decimal part and gives us one of {0, 1, 2}. Call that value i.
  4. Use i as the index into the array, returning whatever element is there.

The following figures illustrate the procedure:

How randomElt works
How randomElt works. The number line is oriented vertically. In the leftmost figure, the light blue area shows that x is in the range from 0 up to but not including 1. The five blue dots are example values, corresponding to values like 0.04, 0.23, 0.48, 0.93, and 0.97. The second figure shows that multiplying by 3 spreads the numbers over a wider range, from 0 up to but not including 3. The third figure shows that Math.floor causes each value to drop to the next lower integer, like weights dropping to the floor. Finally, these integer values are used to index into the array. Here, we only show the index value of 1 getting Ron out of the array.

Ajax

In this reading, we'll learn how the data in a form can be sent to a server, rather than staying in the browser. In web development, the browser, tablet, phone or other device that people work directly with is often called the front end, in contrast to the servers, databases, and other invisible infrastructure that is called the back end. Forms and Ajax are one of the primary ways that the front end communicates with the back end.

Form Attributes

When we introduced forms earlier in the semester, we didn't talk about any of the attributes of the <form> element. Here is how it will usually look like:

<form id = "form2" action = "some-script" method = "GET/POST" >
   <!-- Here go all elements of the form, such as <input>, <button>, etc. -->
</form>

We have seen the id attribute before, so, let's focus on the two other attributes, action and method.

  • action specifies where the form content will be sent for processing
  • method specifies how the form content will be sent to the server

There are two methods of sending the data to the server using the HTTP protocol: GET and POST. The main difference between GET and POST is how the data is sent to the server.

  • GET will append the form field names and values onto the end of the URL as key/value pairs.
  • POST sends the data at the end of the request, rather than in the URL, and so values are not visible in the URL.

The two forms below are identical and they have the same value for action (referring to the script simple-script.php), but one uses method=GET and the other method=POST. Try them out and look at the URL bar to see the difference.

GET Form

Your Name:

Your Class:

POST Form

Your Name:

Your Class:

You probably saw something like this, depending on how you filled the form out:

GET:

POST:

The URL bar after submitting the two forms

Because submitting forms generates an HTTP request, you can use the Network tab in the Inspect Element window of the browser to inspect the details of sending forms, including how the data is packaged to be sent to the server.

In this course, we'll stick to POST, but the default is GET, so make sure you always specify method="post" in your forms.

Scripts on the Server

Where does the form data go? What happens to it? These questions are mostly outside the scope of this course, but we'll give you a peek at it. The data goes to a server somewhere on the internet, wherever you specified in the action attribute of the form. Once there, it gets processed by some script (a program running on the server).

That script could do anything (update a database, charge your credit card, transmit instructions to someone at a warehouse, etc.) In this course, we won't explore those further. We will, however, look at some scripts that can do a few simple things.

Simple PHP to process your Forms

A widespread, server-side language called PHP can be used to process the form data sent from a browser and email it to someone. To avoid the PHP script being exploited by spammers, the PHP script will have the destination hard-coded into the script. That is, the form data can only be sent to a destination of your choosing, not the sender's. This is perfect for emailing a "contact us" form to your organization's secretary, emailing the contents of an order form to your organization's fund-raising chair, and so forth.

We will not burden you with having to learn PHP just to use this ability. Instead, we'll provide you with a mechanism for creating a PHP script that sends email to your desired recipient (the to address). It will work a lot like the following, except that you won't be able to specify the recipient. (Here, we've limited the appeal to spammers by fixing the text that is sent.).

Fill out and submit the form below, and then check your email.

RSVP to Nick's Deathday Party

(Here is the form in its own web page.)

In order for the script to access your name and address, the form needs to contain an input named from_name and another named from_email. Here is the code of our simple form:





Ajax Technology

The problem with the first above-shown technique is that it redirects the user to a new web page. In fact, every time a form is submitted, the browser page is automatically either refreshed, or redirected to the result sent by the server. In the example above, the response was fairly ugly (JSON notation), while in practice we would make the result look a lot prettier. Nevertheless, it will still be a new page.

Sometime we might desire this, but sometimes not. In fact, it is quite common to expect to get notifications on the same page that we are already using. For that purpose, we will use a technology named Ajax.

Ajax, which stands for "Asynchronous JavaScript and XML", is a way of passing data in a structured format between a web server and a browser, often without the user being aware of such a transaction, because there is no page refresh or redirection to a new page. Thus, with Ajax and some DOM manipulation, you can load or reload only a portion of the page with jQuery and JavaScript. It's spelled either AJAX or Ajax; we'll use the latter.

To think about Ajax in action, consider Facebook: when you like an item, that doesn't just update the page you're looking at; it sends information to scripts running on FaceBook's servers to record that fact in a database, so that it can count and display the number of likes. The browser sends that information using Ajax, so that nothing interferes with your reading of the page. When you comment on a post, you're filling out a little form and submitting it to Facebook's servers, again using Ajax. When Facebook sends you new updates without your having to re-load the page, that's Ajax again.

(Although when the technology was introduced, the XML format (a relative of HTML) was used for exchanging data between the server and the client, nowadays, JSON (Javascript Object Notation) is the preferred format. This is what we will use as well. In fact, you might have noticed that the ugly non-Ajax response above was, in fact, JSON notation, which is a variant of our JS Object literal notation. The main difference you've seen is that property names are in quotation marks.)

The way Ajax works is summarized in the graphics below:

The Ajax technology for client-server communication. From "Head First jQuery" book.

The Ajax technology is implemented within the jQuery library and can be used easily in our Javascript applications. In this course, we won't explore Ajax in all its glory, but we will use it to gracefully send email using a special PHP script on the server.

Posting Data Using Ajax

We can use Ajax to send data to a back-end server in the same way as method=post in our form.

Let's first see it in action. Here is the previous RSVP example, with the addition of a button to submit the form via Ajax. Try both! (In real life, we would probably remove the type=submit button, rather than have both. But for now, we want to compare the behavior.)

You can also use the form in its own web page: Deathday form Ajax.

First, let's look at the HTML:

  



You'll notice that we added a type=button button. We also created a place on the page to put the response from the back-end server. We don't have to do that; we could signal the user in some other way, or we could completely ignore the response.

Now, let's examine the JavaScript code:





The first line just makes sendmail the event handler for the Ajax button, which is just a plain button, rather than a submit button.

The sendmail function prepares for just one call to the jQuery .post() method. Notice that the .post() method doesn't have a selector, because it's not operating on a particular element, but instead is doing an Ajax request, submitting the form using POST.

The .post() method takes four arguments:

  1. The first argument is where to send the data. This is typically a URL. Here, we've just retrieved the data from the form's action attribute.
  2. The second argument is what data to send. This is a JavaScript Object, consisting of properties and values corresponding to the names and values of form controls. Here, we only have two inputs to send.
  3. The third argument is a function that will handle the response from the back-end server. Here, we've said that the handleResponse function will get and process the response. More on this in a moment.
  4. The fourth argument is the type of data we expect the response to be. Here, we've specified JSON. (The particular scripts we will be using in CS 110 will always respond using JSON.)

It takes us a few steps to get ready for calling .post(). First (line 14), we retrieve the action attribute. Then, on lines 15 and 16, we pull two values out of the form. On line 17, we construct a JS object out of both of them. Finally, we call .post().

The JSON response from the back-end will be converted into a JavaScript object, and the handler function will be invoked with that object. So, let's look at the handleResponse function next.

As we know, that function gets invoked with a JS object. In this case, the object will contain two properties: status and text. The status property has two possible values: "ok" and "fail", both strings. The rest of the handleResponse function is straightforward code using a conditional to check whether the status is "ok", and if it is, giving a cheery green notice, and other wise giving notice in scary red. In either case, the notice is just the text of the response, inserted into the response_element.

Sending Mail to a Fixed Address

The next step is to discuss a more general kind of back-end script, than the script above that is only good for accepting an invitation to Nearly Headless Nick's Deathday party. The script we'll discuss is one that will send email to a predetermined address, such as the secretary of your student org or the sales clerk for your fund-raiser — whoever should get the email that your website will allow people to send.

In class, we'll talk you through the process of creating and downloading a special-purpose PHP script that you can put on your back-end server (in the same folder with your HTML pages) that can be the action for your forms. It will have an email address of your choosing embedded in it.

Here's an example of the kind of email script we will use.

You'll notice that it takes four fields:

  • from_name: this is the real name of the sender (the person filling out the form), like "Wendy Wellesley" or "Cathy Customer"
  • from_email: this is the email address of the sender, like wwellesley@gmail.com or ccustomer@hotmail.com.
  • subject: this is just like the subject line of any normal email message.
  • body: this is just like the body of any normal email message.

The last two are self-explanatory, since all of us are very experienced with email. The first two are sorta new, because that's usually handled by our email software, like Gmail or whatever. Here, we need them because the person visiting our website is otherwise anonymous. (In fact, we can't prevent them from lying to us, or sending useless emails; let's hope that doesn't happen.)

When we write our JavaScript to use this PHP script via Ajax, we'll have to construct a JS object using those four properties. Like this:

var what = {from_name: "Harry Potter",
            from_email: "hpotter@hogwarts.ac.uk",
            subject: "My Scar",
            body: "Dear Padfoot, my scar's been bothering me lately ..."};
$.post(where, what, ...);

Formatted Email Messages

Of course, we don't want to restrict our forms to those four fields. We'd like to have forms where we can ask to be added to an email list, order Weasley Wizarding Wheezes, or any of many other things we might want.

To do that, we're going to build on our knowledge of how to do Madlibs. Think of the madlib as the body of the formatted email message that we want to send. We can write JavaScript code that will take our arbitrary form, insert the key data into a hidden element much like our MadLibs story, then extract the whole contents of the MadLibs using jQuery's .html() method. (Or, better, use .text() method, which will give us just the text, omitting all the HTML markup.)

The following form demonstrates the idea. It really sends the data to a back-end script, but this script just describes the email that would have been sent (but doesn't really send one). So, feel free to try this as much as you'd like. The response text is printed to the JS console; open it up to see.

Here's the madlib letter that we will send. In real life, we would use display:none in CSS or the jQuery .hide() method to make this text invisible, but you'll want to see it:

Dear Fred and George,

Please send by return owl the following:

fainting fancies

fever fudge

nosebleed nougat

puking pastilles

Signed ()

Finally, of course, you should take a look at the JavaScript. You can see that we've added one new function, formatLetter, which looks a lot like your MadLibs code. The placeOrder function first calls formatLetter, and then proceeds as it did before, except that now the body comes from the formatted letter.





          

Modularity

    Modularity in Websites

    Modularity is something that has come up several times in this course, in different guises. We'll discuss this important principle both in general and how it specifically might apply to the web sites we'll build.

    Modularity: The Big Picture

    In this reading, we'll be looking at several ways to make your website more modular — i.e., created out of reusable parts that make the website easier to maintain.

    Reusability

    Reusability has become one of the watchwords of the environmental movement, and for good reason. Reusing objects that have taken much time, energy, and other resources to create is eminently sensible.

    Reusability makes a lot of sense in the programming world, too. Suppose that a programmer has spent a lot of time developing code that solves a problem. This code can often be reused by the same programmer in a different program, or by other programmers in their programs.

    In JavaScript, we've seen that functions are a good way to make code reusable. Once code is encapsulated in a function, that function can be invoked in many different contexts.

    Groups of related functions and data structures are often collected together in reusable units called modules or libraries that are used by large communities of programmers. These play an important role in the adoption of programming languages. Languages like Java, C/C++, Fortran, and Python have become popular in large part because of the impressive modules/libraries that have been built for these languages. jQuery is a library that makes JavaScript programming easier.

    Modules are particularly reusable when they have been designed to be used in mix-and-match ways — think Legos, standard parts from a hardware store, USB peripherals, mix-and-match clothing, etc. That's the idea behind the logo at the top of this section. Crafting a module that is easy and useful to reuse is more art than science, but it's a worthy goal.

    As a concrete example with web pages, suppose that you've figured out how to make a beautiful navigation bar for one page in a website. You'd like a way to package up your navbar code into some sort of module that you can reuse on other pages for the same site, and perhaps for pages in other sites. What you don't want to do is simply copy & paste your navbar code into other pages, because that's a nightmare to maintain. Which brings us to the topic of ...

    Maintenance

    What is maintenance and why is it important? We all know what, say, car maintenance is: changing the oil, keeping the tires inflated, fixing stuff that breaks. It keeps your car running better and longer. But that doesn't have anything to do with web sites, since they don't have physical parts that wear out.

    But they do need to be changed and updated from time to time, which computer scientists have come to call maintenance. Countless studies have shown that, over the lifetime of a software project, about two-thirds of the overall cost is in maintenance. Surprising, but true. You may not be maintaining your cs110 project, but someone will, and we should make their job easier.

    You're already doing some of the most important steps:

    • keeping the HTML simple, neat and clean, which makes it easier to add new content, and
    • keeping the style information in a external style sheet, so that stylistic changes to the site can be easily made in just one place.

    The techniques we will see today are similar to the idea of an external style sheet, because they allow us to put shared code in a single file that is used by more than one page. This general idea is known by computer scientists as modularity: a module is any kind of distinct, separable thing that can be used more than once.

    JavaScript Code Files

    As we saw when we introduced JavaScript, very often you have some JavaScript code that you'd like to use on several web pages. The best example would be a collection of useful functions, all stored in a single file. You could have the browser load the file of functions, and then your web page could invoke the particular functions you want. Let's look at some examples.

    Accessibility Bar

    The top of this page features a set of font sizes formatted in various sizes, where clicking on them changes the font-size for this page to the selected size. We're calling this the accessibility bar (like a navigation bar, but with accessibility controls). All the code is in a separate file, so the only thing we had to do to put the accessibility bar on this page was the following:

    <script src="accessibility-bar-jq.js"></script>
    

    Let's look at the contents of the accessibility-bar-jq.js file. You don't have to read every line, but the first three functions are important (lines 20-45). The rest of the code defines function to add clickable items to the page.

        
    
    
    
    

    Some key things to look at and think about are:

    • How does JavaScript control and change style elements? Could we make a control that would change, say, the thickness of the bar in the H2 elements?
    • Why didn't we supply a stylesheet along with the accessibility bar? Why did we specify the style rules separately?
    • What functions are parameterized and what aren't? Can you think of ways to make this accessibility bar more general and therefore more useful?

    Tax Rate Functions

    Another example is some JavaScript that processes a form. Here's an example:

    The HTML for the form is straightforward. We'll learn about this a bit later in the course, so don't worry about the details. The main point is that we can get the amount of the bill from the user, rather than usingprompt().

    
    
    
    

    The JavaScript code associated with this form is the following, which uses the jQuery .val() method to get the value that the user filled into the form. Again, we'll cover this a bit later, so don't worry about the details.

        
    
    
    
    

    (The change() method attaches a handler that is invoked whenever the value in the form changes. We'll learn about event handlers very soon.)

    As you've probably guessed, the taxRate variable and the calculateTax function are defined in the external JavaScript file, tax-calculations.js:

    
    
    
    
    

    The latter part of this example assumes that the form, in addition to the bill input, also has outputs named tax_amount and total_amount. When the user fills out the bill amount, the JavaScript code calculates the other two. It puts the values into form inputs so that they can be sent to the CGI script if desired.

    The calculateTax function is defined in the tax-calculations.js file. One nice effect of this technique is that if the tax rate changes (say, the state legislature declares a tax holiday), we can change the definition of the function in that file, and any web page that uses the file will immediately start using the new definition.

    Improved Modularity

    If we create a file of JavaScript code for reuse in other web pages, it could just be a collection of random, unrelated, and disorganized functions. There's nothing in this mechanism to enforce any kind of conceptual organization to the JavaScript code. You could simply have one file, say mystuff.js, and put anything you want in it.

    That would work, but it has the disadvantage that you probably will end up loading code you don't need (a small drag on page loading time). More importantly, it's harder to find the code you want and to keep things organized. Instead, you could divide your code into conceptually coherent groups. For example:

    <script type="text/JavaScript" src="date-functions.js"></script>
    <script type="text/JavaScript" src="form-validation.js"></script>
    <script type="text/JavaScript" src="rollovers.js"></script>
    <script type="text/JavaScript" src="lightbox.js"></script>
    

    These files are more worthy of the term module. If someone asks to use your lightbox code, you can point them to that file, and they won't have to wade through irrelevant stuff to use your code.

    (Unfortunately, dividing your code into several small files increases the loading time of your website, since the browser needs to make a separate connection for each one. Therefore, professional web designers use tools to combine a bunch of modules into one file, thereby getting the best of both worlds.)

    Protecting Your Implementation

    Suppose you're the one who implemented the tax-calculations.js module above, and other web designers are using your code on their websites. You know that the variable taxRate is the rate that we pay, and so can anyone reading your code. However, you worry that someone might mistakenly or maliciously set that variable to the wrong value. If the true tax rate is 5 percent, they could set the variable to 5 (which would be a 500 percent rate) or accidentally set it to 0.50 instead of 0.05 (just a typo), or even set it to a non-numerical value.

    To avoid these mistakes, one thing you could do is provide a programmatic way to set the tax rate, rather than just assigning to the variable. For example, something like this:

    function setTaxRate (newRate) {
        if( isNaN(newRate) ) {
            alert("Error: the new value is not a number: "+newRate);
        } else if( newRate < 0 ) {
            alert("negative tax rates don't make sense");
        } else if( newRate > 0.3 ) {
            alert("This tax rate is higher than any legal rate "+newRate);
        } else {
            taxRate = newRate;  // finally, set the global variable.
        }
    }
    

    Then, people set the tax rate using this function, instead of just assigning to the variable taxRate. Of course, our setTaxRate can't check for every possible error, but it could be a help.

    But, you object, a malicious person could still set the taxRate variable directly, instead of using this function. That's true. However, there are programming techniques (which we won't go into) that protect values absolutely, so that you must go through a setter function like this in order to set the value. Thus, our module can build up walls around itself, controlling how it is used.

    Computer scientists endeavor to create programming languages that are powerful, easy to use, and also encourage and enforce useful modularity. This makes programming better and more effective.

    Modularizing Headers and Footers

    Suppose we have three pages, A, B, and C, all of which should share a common header (with banner image and navbar) and common footer.

    We've already studied one way that this common markup can be shared among the pages, namely using the jQuery .load() function to load the code from a master copy, probably on the main page. In the following sections, we'll describe a second approach.

    We would like to be able to describe these pages in such a way that we generate the shared parts so that they are easy to change. For example, to add a new menu item or footer item, we should only have to change one piece of code, not code on each of the pages.

    Modularity via JavaScript Functions

    Another way to achieve the modularity we desire in the A, B, C example is to use JavaScript functions to generate the shared HTML code in each file.

    As shown below in the HTML source code for A.html, we can accomplish this using the JavaScript functions addHeader() and addFooter(). (The code for B.html and C.html is exactly the same except for a different content paragraph.)

    
    
    
    
    

    The file header-footer-jq.js contains definitions of addHeader() and addFooter(), which are responsible for generating the HTML elements that are shared between all the pages.

    
    
    
    
    

    Any change to the functions addHeader(), addBannerPic(), addNavbar(), addMenuItem(), and addFooter() will affect all of the web pages in the website. For instance, it's easy to add a new menu item to the menu bar or a new icon to the footer list.

    See the header-footer example in action

    Analog and Digital Sound

    Signals

    When sound is transmitted or stored it may need to change form, hopefully without being destroyed.

    A signal is an undulating curve

    Sound moves fast: in air, at 340 m/sec = 750 miles per hour. Its two important characteristics are Frequency (aka pitch) and Amplitude (aka loudness). Frequency is measured in Hz or cycles per second. Humans can hear frequencies between 20 Hz and 20,000 Hz (20 KHz). Amplitude is measured in deciBels (we will see later that it is approximated with "bit-resolution").

    Consider music:

    1. Sound is simply pressure waves in air, caused by drums, guitar strings or vocal cords
    2. Converted to electrical signals by a microphone
    3. Converted to magnetism when it's put on a master tape and edited
    4. Converted to spots on a CD when the CD is manufactured
    5. Converted to laser light, then electricity when played by a CD player
    6. Converted back to sound by a speaker

    A similar kind of story can be told about visual images (sequences of static images) stored on videotape or DVD and played on your home VCR or DVD player.

    Degradation

    Any time signals are transmitted, there will be some degrading of quality:

    1. signals may fade with time and distance
    2. signals may get combined with interference from other sources (static)
    3. signals may be chopped up or lost

    When we continue to transmit and transform signals, the effect is compounded. Think of the children's game of "telephone." Or think about photocopies of photocopies of photocopies...

    Example

    This is the transmitted signal:

    the transmitted signal

    and this is the received signal (dashed) compared to the transmitted signal:

    the received signal, somewhat altered

    The horizontal axis here is time. The vertical axis is some physical property of the signal, such as electrical voltage, pressure of a sound wave, or intensity of light.

    The degradation may not be immediately obvious, but there is a general lessening of strength and there is some noise added near the second peak.

    There doesn't have to be much degradation for it to have a noticeable and unpleasant cumulative effect!

    Analog Signals

    The pictures we saw above are examples of analog signals:

    An analog signal varies some physical property, such as voltage, in proportion to the information that we are trying to transmit.

    Examples of analog technology:

    1. photocopiers
    2. old land-line telephones
    3. audio tapes
    4. old televisions (intensity and color information per scan line)
    5. VCRs (same as TV)

    Analog technology always suffers from degradation when copied.

    Digital Signals

    With a digital signal, we are using an analog signal to transmit numbers, which we convert into bits and then transmit the bits.

    A digital signal uses some physical property, such as voltage, to transmit a single bit of information.

    Suppose we want to transmit the number 6. In binary, that number is 110. We first decide that, say, "high" means a 1 and "low" means a 0. Thus, 6 might look like:

    a six is two high values and a low value

    The heavy black line is the signal, which rises to the maximum to indicate a 1 and falls to the minimum to indicate a 0.

    Degradation and Restoration of Digital Signals

    The signals used to transmit bits degrade, too, because any physical process degrades. However, and this is the really cool part, the degraded signal can be "cleaned up," because we know that each bit is either 0 or 1. Thus, the previous signal might be degraded to the following:

    an altered six is still two high values and a low value

    Despite the general erosion of the signal, we can still figure out which are the 0s and which are the 1s, and restore it to:

    the six, restored

    This restoration isn't possible with analog signals, because with analog there aren't just two possibilities. Compare a photocopy of a photocopy ... with a copy of a copy of a copy of a computer file. The computer files are (very probably) perfect copies of the original file.

    The actual implementation of digital transmission is somewhat more complex than this, but the general technique is the same: two signals that are easily distinguishable even when they are degraded.

    Summary of Digital Communication

    The main point here is that digital transmission and storage of information offers the possibility of perfect (undegraded) copies, because we are only trying to distinguish 1s from 0s, and because of mathematical error checking and error correcting.

    Converting Analog to Digital

    analog going in, digital
coming out If digital is so much better, can we use digital for music and pictures? Of course! To do that, we must convert analog to digital, which is done by sampling.

    Sampling measures the analog signal at different moments in time, recording the physical property of the signal (such as voltage) as a number. We then transmit the stream of numbers. Here's how we might sample the analog signal we saw earlier:

    dots drawn on the grid intersections nearest the curve

    Reading off the vertical scale on the left, we would transmit the numbers 0, 5, 3, 3, -4, ... (The number of bits we need to represent these numbers is the so-called bit-resoluton. In some sense it is the sound equivalent to images' bit-depth.)

    Converting Digital to Analog

    Of course, at the other end of the process, we have to convert back to analog, also called "reconstructing" the signal. This is essentially done by drawing a curve through the points. In the following picture, the reconstructed curve is dashed

    a reconstruction by drawing a curve through the dots

    In the example, you can see that the first part of the curve is fine, but there are some mistakes in the later parts.

    The solution to this has two parts:

    1. the vertical axis must be fine enough resolution, so that we don't have to round off by too much, and
    2. the horizontal axis must be fine enough, so that we sample often enough.

    In the example above, it's clear that we didn't sample often enough to get the detail in the intervals. If we double it, we get the following, which is much better.

    a better reconstruction by drawing a curve through a dots on a finer grid

    In general, finer resolution (bits on the vertical axis) and faster sampling, gets you better quality (reproduction of the original signal) but the size of the file increases accordingly.

    The Nyquist Sampling Theorem

    How often must we sample? The answer is actually known, and it's called the Nyquist Sampling Theorem (first articulated by Nyquist and later proven by Shannon). Roughly, the theorem says:

    Sample twice as often as the highest frequency you want to capture.

    For example, the highest sound frequency that most people can hear is about 20 KHz (20,000 cycles per second), with some sharp ears able to hear up to 22 KHz. (Test yourself with this Online tone generator or this hearing test.) So we can capture music by sampling at 44 KHz (44,000 times per second). That's how fast music is sampled for CD-quality music (actually, 44.1 KHz).

    Exercise on the Nyquist Theorem

    1. If the highest frequency you want to capture is middle C on the piano, at what frequency do you have to sample? 2*261.626 Hz
    2. If you want to record piano music (the highest key on a piano is C8, at what frequency do you have to sample? 2*4186 Hz
    3. If you want to record Whale sounds, at what frequency do you have to sample? 2*10,000, or 20KHz
    4. If you want to record sounds that bats can hear, at what frequency do you have to sample? 2*100,000 Hz, or 200 KHz

    File Size

    The size of an uncompressed audio file depends on the number of bits per second, called the bit rate and the length of the sound (in seconds).

    We've seen that there are two important contributions to the bit rate, namely:

    • sampling rate (horizontal axis), and
    • bit resolution (vertical axis)

    As the sampling rate is doubled, say from 11KHz to 22KHz to 44KHz, the file size doubles each time. Similarly, doubling the bit resolution, say from 8 bits to 16 bits doubles the file size.

    As we've seen, the sampling rate for CD-quality music is 44KHz. The bit-resolution of CD-quality music is 16: that is, 16-bit numbers are used on the vertical axis, giving us 216=65,536 distinct levels from lowest to highest. Using this, we can actually calculate the bit rate and the file size:

    bit rate (bits per second) = bit-resolution * sampling rate

    file size (in bits) = bit rate * recording time

    For example, how many bits is 1 second of monophonic CD music?

    16 bits per sample * 44000 samples per second * 1 second = 704,000
    Therefore, 704,000 / 8 bits per byte = 88,000 bytes ≈ 88 KB

    That's 88 KB for one second of music! (Note that there are 1000 bytes in 1KB, so 88000/1000 is 88KB.)

    Channels

    And that's not even stereo music! To get stereo, you have to add another 88KB for the second channel for a total bit-rate of 176KB/second.

    An hour of CD-quality stereo music would be:

    176 KB/sec * 3600 seconds/hour = 633,600 KB ≈ 634 MB

    634 MB is about the size of a CD. In fact, it is not accidental that a CD can hold about 1 hour of music; it was designed that way.

    Exercise on Bit Rate and File Size

    1. If you record an hour of piano music (the highest key on a piano is C8) in mono at 16 bits, what is the bit rate and file size? bit-rate is 16*2*4186, and file size is bit-rate*3600
    2. If you record an hour of bat-audible sounds in stereo at 32 bits, what is the bit-rate and file size? bit-rate is 32*2*2*100,000, and file size is bit-rate*3600

    Exercise with Form for Bit-Rate and File Size

    Consider the following form to compute bit-rate and file size. Fill in the missing function definitions.

    Choices

    What are the practical implications of various choices of sampling rate and bit-resolution?

    • If you're recording full-quality music, you'd want to use the 44 KHz and 16-bit choices that we've done some calculations with.
    • If you're recording speech in your native tongue (when your brain can fill in lots of missing information), you can cut many corners. Even a high-pitched woman's voice will not have the high frequencies of a piccolo, so you can probably reduce the numbers to 11KHz and 8-bit. Furthermore, you will only need one channel (monophonic sound) not two channels (stereo). Thus, you've already saved yourself a factor of 16 in bit-rate.
    • Speech in a foreign language is harder to understand, so it might make sense to use 22KHz and 16-bit resolution. Of course, you would still use one channel not two. This is still a factor a 4 decrease in the bit-rate.
    • Music before about 1956 wasn't recorded in stereo, so you would only need one channel for that.

    Compression

    Bandwidth over the internet cannot compete with the playback speed of a CD. Think of how long it would take for that to be downloaded over a slow modem.

    So, is it impossible to have sound and movies on your web pages? No, thanks to sound compression techniques. We have seen how GIF and JPG manage to compress images to a fraction of what they would otherwise require. In the case of sound and video, we have some very powerful compression file formats such as Quicktime, AVI, RealAudio and MP3. Read more about the history of MP3 (or history of MP3).

    The tradeoffs among different compression formats and different bit rates are explained well in this 2007 article on audio formats from the New York Times. (This article is available only on-campus or with a password.)

    A discussion of the technology behind these compression schemes is beyond the scope of this course. They are similar in spirit to the JPEG compression algorithm, in that they are lossy compression schemes. That is, they discard bits, but hopefully the bits that least degrade the quality of the music?

    Some compression algorithms take advantage of the similarity between two channels of stereo, so adding a second channel might only add 20-30%.

    What do you think?

    Discussion Topics

    1. Modems
    2. Does vinyl sound better than CD? (see this discussion of vinyl versus CD on answers.google.com
    3. CD versus MP3
    4. DVD audio representation that samples at 192 KHz with 24 bits per sample (see this Wikipedia description)
    5. Digital TV
    6. Digital cell phones

    Summary

    • Music, video, voice, pictures, data and so forth are all examples of signals to be transmitted and stored.
    • Signals inevitably degrade when transmitted or stored.
    • With analog signals, there's no way to tell whether the received signal is accurate or not, or how it has been degraded.
    • With digital signals, we can, at least in principle, restore the original signal and thereby attain perfect transmission and storage of information.
    • We can convert analog signals to digital signals by sampling.
    • We can convert digital signals back to analog signals by reconstructing the original signal. If the original sampling was good enough, the reconstruction can be essentially perfect.
    • Wellesley's LTS has a nice page on digital audio

    A condensed version of these notes can be found here.

    Further Information and Examples -- OPTIONAL

    Note that beyond here is information that we think you might find interesting and useful, but which you will not be responsible for. It's for the intellectually curious student.

    Error Detection

    Suppose we have a really bad burst of static, so a 1 turns into a 0 or vice versa. Then what? We can detect errors by transmitting some additional, redundant information. Usually, we transmit a "parity" bit: this is an extra bit that is 1 if the original binary data has an odd number of 1s. Therefore, the transmitted bytes always have an even number of 1s. This is called "even" parity. (There's also "odd" parity.)

    How does this help? If the receiver gets a byte with an odd number of 1s, there must have been an error, so we ask for a re-transmission. Thus, we can detect errors in transmission.

    You can see some examples of parity using the following form. The parity bit is the last (rightmost) one, with the red outline.

    Decimal

     

    Binary

     dataparity

    Exercise on Parity

    Assuming even parity, what is the parity bit for each of the following:

    1. 000010112 1, because there are 3 ones in the number
    2. 010010112 0, because there are 4 ones in the number
    3. 2316 1, because there are 3 ones total in the number (convert it from hex to binary)
    4. FF16 0, because there are 8 ones total in the number (convert it from hex to binary)
    5. DEADBEEF16 0, because the ones 33233334, for a total of 24, which is even

    Error Correction

    With some additional mathematical tricks, we can not only detect that a bit is wrong, but which bit is wrong, which means we can correct the value. Thus, we don't even have to ask for re-transmission, we can just fix the problem and go on.

    Try it with the following JavaScript form. Type in a number, and it will tell you the binary code to transmit. Then, take the bits and add any single-bit error you want. (In other words, change any 1 to 0 or any 0 to 1.) If you click on "receive," it will tell you which bit is wrong and correct it. If you think I'm cheating, you can type the bits into another browser!

    Note: for technical reasons, the parity bits are interspersed with the data bits. In our example, the parity bits are bits 1, 2, 4 and 8, numbering from the left starting at 1. (Notice that those bit position numbers are all powers of two.) So, that means the seven data bits are bits 3, 5, 6, 7, 9, 10, and 11.

    Transmit

    Binary Code

    Receive

    Exercise on Error Correction

    • Type in a number and click on the transmit button
    • Change one of the bits (either a data bit or a parity bit).
    • Click on the receive button.
    • Gasp in amazement that it figures out what bit you modified
    • Repeat

    What if more than one bit is wrong? What if a whole burst of errors comes along? There are mathematical tricks involving larger chunks of bits to check whether the transmission was correct. If not, re-transmission is often possible.

    How Hamming Codes work

    The error correcting code we saw above may seem a bit magical. And, indeed, the algorithm is pretty clever. But once you see it work, it becomes somewhat mechanical.

    Here's the basic idea of this error-correcting code. (This particular code is a Hamming code. The Hamming (7,4) code sends 7 bits, 4 of which are data. The (7,4) code is easy to visualize using Venn diagrams. The general idea is this:

    • If we have 11 bit positions total, number them from left to right as 1-11.
    • Write down the 11 numbers for the bit positions in binary. For example, position 5 (which is a data bit, since 5 is not a power of 2) is expressed as 0101.
    • The bits that are "true" in the binary number expressing the position define which parity bits check that position. For example, position 5 (0101) is checked by the parity bit at position 1 and the one at position 4.
    • The positions of the parity bits that are "wrong" add up to the position of the wrong bit. So if the parity bits at positions 1 and 4 are wrong, that means bit 5 is the one that is wrong.

    For more detail, see this general algorithm

    Solution to Exercise with Form for Bit-Rate and File Size

    Solution to the Exercise with Form for Bit-Rate and File Size is here.

    Copyright

    Intellectual Property Issues

    (Reading: With these notes, we strongly suggest you read Blown To Bits Chapter 6, Balanced Toppled: Who Owns the Bits.)

    Outline

    Intellectual Property

    The results of intellectual work are covered by three distinctly different legal areas:

    • Copyright
    • Trademarks
    • Patents

    (A rant by Richard Stallman on the very term intellectual property is worth reading.)

    A trademark is the recognizable mark that a company has made to market its products. It is not only the name of the product that is covered by the trademark (e.g., Coca Cola), but also the shape (e.g., the recognizable Coca Cola bottle shape, or the font of the Coca Cola name used on the product). This means that one cannot create, say, LTCola and have it bottled in a Coca Cola-shaped bottle or have its name written with a Coca Cola-looking type of font. All famous marks are registered and watched by webcrawlers. Domain names that confuse origin or “dilute the value of the mark” will be challenged by the owners (even in ridiculous cases such as the “Christmas Blend” of Starbucks.)

    The work of an inventor is covered by a patent. A patent is issued after careful review by the patent office, which must be persuaded that the work described in the patent is not a trivial extension of an existing work (“prior art”).

    In your project, it is not likely that you will produce or infringe upon a patent. You might violate a trademark if, for example, you decide to have the picture of a a Coca Cola bottle on your page or you use the same font, color, and style to write something. What you need to pay particular attention, though, is on the Copyright Law.

    Copyright is about the rights of the author, artist, or creator.

    What rights does an author have? Suppose you're the author of a novel. You can:

    1. Reproduce copies of the work. In other words, you can print up 100,000 copies of your novel to sell, but no one else can.
    2. Prepare derivative works. You can write a sequel to your novel, a different version (maybe with a different ending) and so forth, but no one else can.
    3. Distribute copies. You can sell or give away the copies that you made, but if you decide to keep them all in your attic, no one else can give them away for you.
    4. Publicly perform it. Suppose instead of a novel, you've written a play. You can decide who can and cannot perform your play.
    5. Publicly display it. Suppose instead of a novel, you've painted a painting: you can control whether it is displayed in a gallery or stays under your bed.

    Of course, as the owner of the copyright, you can decide to sell or lease the rights, piecemeal or in total, to other people. Musicians often sell their rights to the record company. Sometimes in the fine print at the end of a movie, you'll see “for the purposes of copyright, the owner of this film is Paramount Pictures, Inc.”

    Note that copyright applies to things, in the sense that your creative endeavor has to be fixed in some medium: paper, videotape or whatever. You can't copyright an idea; that idea has to be expressed somehow.

    Copyright law didn't always exist. Copyright actually began in England in 1557. It was a royal decree that allowed only designated printers to publish. That way the government controlled what was printed (censorship) and at the same time protected the market for the designated printers. With the end of censorship, the notion of copyright evolved into the Statute of Anne (1710), which is considered to be the forerunner of modern copyright. The full title of the law says,

    An act for the encouragement of learning, by vesting the copies of printed books in the authors or purchasers of such copies, during the times therein mentioned.

    Copyright was not granted primarily for the benefit of authors, but so that authors would have an incentive to create works, thereby benefitting society. Of course, now the record and movie industries have powerful lobbies in Washington, so copyright law is being extended to benefit these big corporations. They are also jealously protecting their copyrights.

    Copyrights don't last forever. For a long time, the law was that copyright protection ended 70 years after the author's death. It's actually more complicated than that, depending on whether the author is anonymous or whether a corporation now owns the copyright (see the resources section, below).

    The movie industry got the copyright law extended so that the movies that were released in the 1920s, where the copyright was about to expire, are still copyrighted. Now the copyright is held by the employer for 95 years since publication or 125(!) years from creation.

    Public Domain

    When a work is no longer copyrighted, it is in the public domain and therefore is owned by society in general. This is where society really benefits from the new works created by copyright law. Once something is in the public domain, the author no longer has any rights and anyone can do with it what they want. For example, someone wrote West Side Story without having to pay any royalties to Shakespeare's estate, because Romeo and Juliet is now in the public domain. Similarly, anyone can perform the works of J. S. Bach, because he's been dead for more than 70 years.

    Note, though, that a performance of a work is copyrighted. So, if the Wellesley Widows perform a 17th century art song, they own the copyright to their performance, even though the song is in the public domain.

    In fact, some authors will create things and explicitly place them in the public domain, giving up their rights so that others can immediately make derivative works, building on the contribution.

    Copyrighting Something

    What is copyrightable? An original work of intellectual authorship. This has a rather low threshold (many things can fall into this category). But facts, ideas, titles, short phrases, and public domain information are not copyrightable.

    How do you copyright something? Do you have to write the © symbol on the work and register it with some office somewhere? No, the 1971 Berne convention, an international convention of most countries in the world, declared that any work of yours is automatically copyrighted unless you explicitly place it in the public domain. (The U.S. joined the Berne convention in 1989.) If you made it; you control it. This holds whether or not a copyright notice is attached and whether or not the work is registered. Of course, adding those steps indicates that you intend to protect your rights, so it's not a bad idea.

    Rules for Fair Use

    The author doesn't hold complete power over of her work. There is an important legal concept of fair use, so that society can gain some benefits immediately. Examples:

    • A critic can quote passages from a novel or show clips from a movie to illustrate the ideas in the review.
    • A teacher can use sections from a book for educational reasons.

    How can you know whether something is “fair use”? There is no easy answer. The only real answer can be found in a court, but we can say what the court's decision will be based on [from http://www.wellesley.edu/Library/copyright.html ] the following 4 criteria:

    1. The purpose and character of the use. Non-profit and educational use is in your favor, but won't necessarily win the case for you. All the criteria are taken into account.
    2. The nature of the copyrighted work, with special consideration given to the distinction between creative work and informational work. For example, you're on safer ground copying a news story than a purely creative or literary work.
    3. The amount, substantiality, or portion of the work. Copying a few lines from a novel is a small part, while copying one chapter from a three-chapter book is pretty big. Copying as little as you can will work in your favor. On the other hand, keep in mind that not all parts are created equally. Taking just the right snippet from a pop song might be crucial, because that snippet is the key to the song.
    4. The effect of the use on the potential market of the copyrighted work. This factor is the key factor from which the others are derived. If your use significantly reduces the potential revenues an author gets from the work, the court may rule against you. People sometimes forget this when they say “but I'm not making any money!” In fact, no one really cares whether you're making any money. The author cares about whether your use is depriving her of money. If you use your CD burner to give away free copies of Britney Spears's latest oeuvre, you're depriving her of sales, even though you don't make a dime.

    An important related point is that copyright is different from plagiarism. Most of us know that we have to quote properly in our research papers and give credit where credit is due. If I quote from your research paper, I have to give you credit. However, if I've quoted so much of your work (chapters and chapters) that I get into trouble with copyright, giving you credit isn't going to help. After all, that bootleg CD of Britney Spears isn't passing itself off as someone else's work; that wouldn't be the point.

    Implications for your Web Site

    What does copyright law mean for you and your web site? It means that you should assume anything you find on the internet is copyrighted and that you may not use it without permission of the author. Certain things are intended to be copied, and the author may well explicitly grant permission for that. For example, snippets of code at a JavaScript download site are obviously intended to be used in your web page. You should do so with a clear conscience. Academic honesty requires that you give credit to the web site, but that has nothing to do with copyright.

    For the purposes of your homework or project in this class, not giving credit might constitute plagiarism. Ask your instructor if you are not sure.

    What is Copyrighted on the Web
    (adapted from a talk by Karen Hersey, Sr. Counsel for IP, MIT)
    Medium Example Holder
    Modern Text

    Screenplays, books, poetry, quotes, journals, newspaper articles

    Author or publisher

    Images

    Stills, video, artwork, logos

    Photographer, object owner, artist, architect, trademark company

    Sound

    Performance rights, mechanical rights, synchronization rights

    Lyricist, Performer, Studio, Composer

    Software

    Patents, university employees, trade secrets to 3rd party

    Programmer, University faculty, students, 3rd party

    People
    (pictured or described)

    Actors, Recognizable People, have rights of Publicity, of Privacy, against defamation

    individuals, agents, parents

    Similarly, when you are putting things on the site, you may need to think about copyright. Say there's a cartoon you'd like to put on it. It might be a cartoon that your client (a professor) always uses in lecture. Is this fair use? Look back at the criteria, and you see that (1) the class may be educational, but the primary purpose of the cartoon is probably just to be amusing; (2) the work is probably highly creative; (3) you've used the entire cartoon; and (4) the cartoonist sells this for money, and if it's free, globally, on the internet, there goes the market. A court would probably rule that this is not fair use. (On the other hand, cartoons are ephemeral, the cartoonist makes a new cartoon every day, so one cartoon might not dent the sales of the latest Dilbert compendium.) It also depends on the artist/cartoonist. Bill Watterson and his syndicate has zealously protected Calvin and Hobbes for many years. Scott Adams probably protects Dilbert just as fiercely, but might not.

    One thing to keep in mind is that the internet is global . Thus, the market effect of putting something on the web is a zillion times greater than just using it in a campus course. (Thirty students versus a billion on the web.) One approach to this is to restrict access to copyrighted material, say via a password or something.

    Digital Rights Management

    Copying digital information is extremely easy. This encourages people to freely share digital music, videos, books, software, etc., even though such sharing may violate copyright laws.

    Digital Rights Management (DRM) refers to technological and legal methods of protecting the copyright of digital information. On the technology side, digital information may be associated with "copy protection" or "content protection" systems that try to prevent the information from being copied. For example, some distributors of digital music use a combination of DRM information in music files and DRM software in the music players to limit the number of times the music file can be copied or played or the duration of time in which it can be played. Software available for trial download uses DRM to ensure that the software can't be used after the trial period expires. DVD video discs use a Content Scramble System (CSS) to encrypt the contents of the discs as an attempt to prevent the discs from being copied or being played by devices not licensed by the DVD Copy Control Association.

    Software-only approaches to DRM can be circumvented by skilled technologists, who often publish descriptions of how to circumvent the DRM or applications that circumvent the DRM. In response, the computer industry has developed hardware-assisted approaches to Trusted Computing, whose goal is to prevent uncertified programs from manipulating copyrighted digital information. A popular incarnation of this idea is the Trusted Platform Module (TPM), a chip that uses cryptography to verify that the operating system and applications manipulating the DRM-protected digital information have not been compromised. This chip is also known as the "Fritz chip" after former Senator Ernest "Fritz" Hollings, who championed its adoption. Many computers sold today are equipped with a Fritz chip.

    Because many forms of digital information must ultimately be converted to analog forms in order to be displayed, DRM systems suffer from an analog hole that fundamentally limits their efficacy. End users can ultimately copy these analog audio/picture/video forms, though such copies may suffer from reduced quality.

    Although DRM technology can often be circumvented, it is not legal to do so in the US. This is a consequence of the Digital Millenium Copyright Act (DMCA), a 1998 US law that includes an anti-circumvention provision that outlaws devices and methods for bypassing DRM. Even telling others how to circumvent DRM appears to violate this provision. Even providing a link to a CSS descrambler might be illegal, but CMU CS professor David Touretzky doesn't think so! The DMCA was championed by the music and film industries. Free speech advocates claim that the DMCA is at odds with the First Amendment, and critics call it Digital Millenium Competition Avoidance.

    Resources

    Cryptography

    Encryption

    Today, we'll talk about how machines can communicate in a secure way. A little while ago, we talked about analog and digital signals, and this lecture will remind you of that one, but we're talking about a higher level: not just how information gets from point A to Point B, but how it can get there without anyone in between knowing what is being said.

    Lots of us had fun with secret codes and such when we were kids. We'd get secret decoder rings in our cereal boxes and make up messages to send to each other. Could be useful if they were intercepted by the teacher! We hope that today's lecture evokes that sense of fun.

    A condensed version of these notes can be found here.

    The Cast of Characters

    When we discuss encryption, it's traditional to name the people involved, just so we can keep things straight. The cast of our little drama is:

    • Alice, who wants to say something privately to Bob
    • Bob, who wants to hear from Alice
    • Eve, the person who is trying to eavesdrop on their conversation.
    • Mallory, the person who is maliciously trying to interfere with their conversation

    The story is that Alice is sending Bob a message through some insecure medium (not whispering in his ear): think postcard or radio. Alice might be a field agent and Bob is her contact at HQ. Alice and Bob might not even know each other: perhaps Alice is trying to persuade Bob to defect, and Eve is trying to find traitors.

    Media

    The messages might be sent by radio, or phone, or email, or carrier pigeon. All media are potentially insecure. Radio waves can be picked up by other receivers, phone wires can be tapped, as can computer networks. Even carrier pigeons can be captured.

    Ciphers

    One approach is to put the message in code. Humans have invented lots of codes in history, and code-making and code-breaking have often been pivotal. Indeed, Alan Turing and his code-breakers in England may have done more to win WWII against Hitler than General Patton, because they were able to break the codes sent with the Enigma machine used by the Germans. Similarly, the Navajo Indians, who used their native language as an unbreakable code in the war in the Pacific, contributed greatly to the war effort without ever firing a shot.

    Terminology:

    plaintext
    (n) the message we want to send, in readable form
    ciphertext
    (n) the message in coded form, unreadable without special information
    encrypt
    (v) to turn plaintext into ciphertext
    decrypt
    (v) to turn ciphertext back into plaintext
    cryptanalysis
    (n) cracking a code; the attempt to decrypt without the required special information
    cryptography
    (n) The study of codes and code-breaking.

    Caesar Codes

    Caesar codes are named because Julius Caesar used them to communicate with his troops, so they're hardly new. They're also not particularly hard to break, but if you have to write your message on a postcard, it's better than nothing. The idea is letter substitution. A popular and easy way of doing it is rotating: Imagine the letters of our message are each printed on a wheel, and we simply turn the wheels so each letter is replaced by one that is n letters before or after it in the alphabet. For example, we replace each letter with the one preceding it in the alphabet (and “A” is replaced with “Z”).

    Plaintext:

    IBM

    Ciphertext:

    HAL

    (You may remember that the computer in Arthur C. Clarke's classic science fiction novel 2001: A Space Odyssey was the HAL 9000. Many people believe this was a thinly veiled reference to IBM, using a -1 rotation code.)

    Caesar actually used a rotation of 3, so A was written as D, B as E, and so forth. Thus, “ATTACK” would be sent as “DWWDFN”.

    Another popular Caesar code is called rot13 and has been used for many years on the Internet as a way to hide things from inadvertent reading, such as movie spoilers or dirty jokes. You have to decode it using rot13 to read the spoiler or the dirty joke. Rot13 is just a Caesar code incrementing each letter by 13. This is convenient because you can decode using the same software as encoding, since rotating twice by 13 brings a letter back to where it started.

    If you want to encrypt using a Caesar code by hand, you can use the following form. Choose an amount to rotate by, then write your message using the letter from the cipher alphabet instead of the one from the plain alphabet — in other words, the one below the one you really mean. For example, setting rotation to 1, you can see “B” below “A” and “C” below “B” and so forth. Setting it to 25, you can see “H” below “I” and “A” below “B” and “L” below “M”, giving “IBM” for “HAL”.

    rotation

    plain alphabet

    cipher alphabet

    Exercise 1

    Use the form above to translate some simple words into code. Translate the first two using Caesar's code (rotate by 3) and the last by rot13.

    plaintext

    ciphertext

    BY SEA

     

    BY LAND

     

    ATTACK

     

    You can check your answers and try out other Caesar codes using the following form. Note that this form converts the string to uppercase. Also, it only rotates the letters; it leaves the numbers, punctuation and other characters alone. It could be easily re-written to handle more stuff.

    rotation amount:

    plaintext:

    ciphertext:

    So, now you and a friend can exchange secret messages, say by email, just by encrypting them using this form. You just have to agree on a rotation amount (and keep it secret!).

    ASCII Codes implementing Caesar Ciphers

    Earlier, we ignored punctuation and anything other than a letter. Obviously, that makes for a bad code. What we really should do is treat all characters the same. How is this done? First, we have to say what a character is.

    As you know, everything in a computer is just numbers. How does it deal with characters? As you remember from an earlier lecture, early computer designers agreed on a set of characters and a standard number for each one. For example, A is represented with 65. One such system was ASCII: American Standard Code for Information Interchange. Here's part of the ASCII code:

    You read this table just like an addition table. Add together the row and column headers, and you find the numerical value (ASCII code) of the character at the intersection of that row and column.

    Note: The ASCII code is not about encryption; it's just a standard for numbering characters. The existence of such a numbering means that we can do rotation codes numerically, like this:

       encoded_char = (plaintext_char + rotation_amount) % 128;
    

    ASCII is now being supplanted by UNICODE, which is a vastly larger code, designed to handle all the world's languages.

    Code Breaking

    Breaking a code (that is, reading encrypted messages without having the secret information) is called cryptanalysis.

    Caesar ciphers are relatively easy to break, as is any cipher based just on substitution of letters. For example, the most common letter in the ciphertext is probably the encypted form of a very common letter, such as “e” or “t” or “a”. With more sophisticated statistics, and trial and error, both of which computers are good at, it's fairly easy to crack a substitution cipher.

    Vigenère Cipher

    One way to spoil the statistics of a Caesar cipher is to use multiple Caesar ciphers. In other words, suppose we rotate the first letter of the plaintext by 2, the second letter by 0, and the third letter by 19. Then we repeat, rotating by 2, 0, 19, until we're done with the plaintext. Such a technique is called a Vigenere Cipher, mis-attribute to Blaise de Vigenère from the court of Henry III of France in the sixteenth century. It was considered unbreakable for some 300 years!

    Another way to think of the Vigenère Cipher is as follows. Write down a keyword, such as “cat”. Then, use the index of each letter as the amount to rotate. For example, if the keyword is “cat”, then we will use a 2 rotation, a 0 rotation, and a 19 rotation (“t” is the 19th letter of the alphabet if you start from zero: A is the 0th letter). Write down the keyword above the plaintext and use it to select the correct rotation. It helps to have a table of all the rotations:

    Here's the idea. To encrypt the message:

    ATTACK AT DAWN

    using the keyword “CAT”, we write the keyword above the message repeatedly:

    keyword

    CATCAT CA TCAT

    plaintext

    ATTACK AT DAWN

    ciphertext

     

    Now, below, we compute each letter of the ciphertext by looking at the intersection of the row of the keyword and the column of the plaintext. (In fact, because of the way the table is set up, it doesn't matter whether the keyword character is the row or the column.) In our example:

    keyword

    CATCAT CA TCAT

    plaintext

    ATTACK AT DAWN

    ciphertext

    CTMCCD AM DTYN

    Notice:

    • The two T's in “ATTACK” were encrypted differently, unlike the simple substitution cipher. This is why we can't just do a simple frequency analysis to crack the code.
    • The letter “A” is encrypted four times, yielding only three different results, since there are only three letters in the keyword. If the plaintext were much longer, a sophisticated frequency analysis might be able to determine information about the keyword and plaintext. A longer keyword would give more variety and hence more security.

    Exercise 2

    Use the table above to encrypt “ATTACK” using the Vignere cipher and the keyword “CODE”. Notice how the A's and T's never have the same substitutions.

    Because a Vigenère cipher uses more than one substitution alphabet, it's one of a bunch of ciphers known as polyalphabetic.

    Exercise Using Vigenère Cipher

    Choose a partner (say from the row in front of or behind you, so you can't easily look onto her monitor, though it doesn't really matter). One of you will be the sender and the other the receiver.

    1. Jointly, choose a secret codeword that you'll use for encrypting and decrypting.
    2. The sender uses this vigenere form and the secret codeword to encrypt a message. The message can be anything. If you're feeling stumped, send the identity and location of one of the horcruxes, or a quotation from Shakespeare.
    3. The sender then copy/pastes the ciphertext into an email message and emails it to the receiver.
    4. The receiver uses the same vigenere form to decrypt a message, using the secret codeword.
    5. Verify that the message was transmitted correctly and secretly.

    Notice that the form above only encrypts lowercase letters; it removes anything else, including spaces. This is partly for pedagogical reasons (since the ciphertext is also all lowercase letters) and partly for simplicity, since the JavaScript code doesn't have to worry about dealing with non-printing characters in the output (ciphertext). However, we can simply represent each character as its ASCII code, as a two-digit hex number. That results in this vigenere form for all characters.

    Enigma

    The Germans in WWII used an encryption scheme based on a polyalphabetic cipher. They built machines to do the encryption and named them Enigma machines. They considered the encryption by the Enigma machine unbreakable, and relied on it to communicate with their U-boats in the North Atlantic. The Enigma machine looked like manual typewriters with keys and hammers, but internally the keys were attached to drums that did the substitutions by “re-wiring”: mapping the keys to different hammers. Actually, there were three (later four) rotors that did the substitutions and after each letter was typed, the rotors turned like a car odometer (the rightmost fastest, and so forth).

    The British managed to steal several of the machines and figure out how they worked. (One attempt to steal one was the story of the movie U-571, except that in the movie the Americans stole the machine, but in real life the British were the heros.) Unfortunately, they still needed the keyword (the settings of the rotors). A group of mathematicians led by Alan Turing (and including quite a few women) were able to analyze the transmissions and, eventually, crack the code. This was a major turning point in the war, and the Allies went to enormous effort and sacrifice to conceal the fact that they had cracked the code.

    Here are some links about the Enigma machine, in addition to the Wikipedia article on Enigma.

    Private Key Encryption

    Now that we understand something about encryption, let's go back to our initial scenario and see how it works. Alice wants to send a message to Bob, without Eve or anyone else being able to read the message. She encrypts it using the secret key, and sends it to Bob. Even if Eve intercepts the message, she won't be able to read it. Bob uses the secret key to decrypt the message and read what Alice says.

    Suppose that Alice is behind enemy lines and Bob is back at home base. She gets to a radio transmitter, gets out her secret code book, encrypts her message using today's key, and sends it to Bob. Bob has to get out the matching code book to decrypt the message. If Eve is able to capture the code book, disaster!

    If Eve captures the code book, Alice needs to send a new secret key to Bob. She needs to send it securely, so that Eve can't read it. Thus, we're back at square one: Alice needs to send a key securely to Bob, so that she can send a message securely to Bob. Consider the secret codes we used earlier, when we said you could send email messages in code, just by agreeing on a rotation amount, but if you had to send the rotation amount by email, you're stuck!

    For thousands of years, this was the essential paradox of encryption: you had to have a secure way of communicating in order to have a secure way of communicating. A real-life chicken-and-egg problem!

    The kernel of the paradox is that all of the encryption methods that we have discussed so far are kinds of private key systems: they required a shared private key.

    Public Key Encryption

    In 1976, Whitfield Diffie and Martin Hellman solved the problem of deriving a shared private key over an insecure channel, an invention that came to be known as Diffie-Hellman key exchange. While it contains some cool ideas that are still in use today, we won't purse it further in this course. (If you're interested, there is a good Wikipedia article on Diffie-Hellman key exchange.) Instead, we will discuss the RSA cryptographic system, which has some very interesting properties.

    The year after Diffie and Hellman came out with their cryptographic system, three MIT professors (Ron Rivest, Adi Shamir and Leonard Adleman) created the first published, practical implementation of public key cryptography. The main ideas of a public key cryptosystem are:

    • Instead of one key, you have two: one to encrypt and a different one to decrypt.
    • The encryption key can be public.
    • Knowing the encryption key doesn't help you figure out the decryption key.

    How does this help? Very simple: Bob knows that Alice wants to send him a message, so he creates a pair of keys. He advertises his public key all over the world (maybe he puts it on his web page). Alice sees it, and so does Eve. Alice downloads it and uses it to encrypt her message. She radios it to Bob, and Eve intercepts it, but Eve can't decrypt the message — only Bob can. No one but Bob can decrypt the message, because only Bob has the secret key.

    Imagine that we send information around in lockable trunks (rather than, say, paper envelopes).

    • With private key encryption, there's one key for each trunk. The same key is used to lock and unlock it. Therefore, Alice and Bob have to have the same key. If Alice wants to send a message securely to Bob, and he doesn't have the key, she needs to send him that first. That's a problem. Why?
    • With public key encryption , there are two keys for each trunk. If one key is used to lock the trunk, it can't be used to unlock the trunk; only the other key can unlock the trunk. They have to cancel each other out. If Alice wants to send a message securely to Bob, she first gets his public key, maybe off his web page or something. She then locks the trunk with the public key and sends it to Bob. He then unlocks it with the private key!

    A pictoral comparison of Private and Public Key Encryption
    Private Key Public Key
    Diagram of private key encryption Diagram of public key encryption

    Implementing Public Key Encryption

    The preceding description is relatively straightforward, but the implementation is not. Nevertheless, several different public key systems have been created. One system, called the RSA method, involves advanced number theory that can cause grown men to burst into tears (or maybe it's just me), but the idea is very cool. (If you're interested, please consult the Wikipedia article on the RSA method, but be warned that the article assumes a good deal of knowledge of number theory, though there are good examples and references.)

    • The pair of keys are mathematically related, and
    • You can reasonably efficiently generate them and use them to encrypt and decrypt messages, but
    • To try to determine one key from the other involves solving a problem that is mathematically hard.

    The last fact makes the RSA method difficult to crack. For their contribution, the members of the RSA team received the 2002 TURING AWARD, which is considered the Nobel-equivalent for Computer Science.

    The RSA Method

    There are many more substantive and accurate sources to learn about the RSA method, but here are a few steps that give a few more details to make it more concrete.

    To generate a key pair, do the following:

    1. Choose two large prime numbers, p and q.
    2. Compute n=pq. n is used as the modulus for both encryption and decryption.
    3. Compute e, which is used for encrypting. There are some technical conditions for e, but in practice it is often a prime with a simple bit pattern, such as 316, 1116 or 100116.
    4. Compute d, which is used for decrypting. It is the mathematical inverse of e when doing arithmetic mod n. In order to compute d, you need to know p and q.

    To encrypt, you compute

    c = me (mod n)

    To decrypt, you compute

    m = cd (mod n)

    The public key is e and n. (Yes, there are two numbers in the public key.) The private key or secret key is d.

    To crack this code, you have to factor n, or find some other way to compute d from e and n.

    The RSA Cipher in JavaScript

    There are many implementations of the RSA method, but a very nice one that shows the steps of generating a key pair and also allows for encrypting and decrypting is Herbert Hanewinkel's RSA Public Key Encryption Demo

    Breaking RSA

    We said that breaking RSA is hard, but what does that mean, really? You have to factoring n, a large number. The state of the art is little better than trying all the possible factors to see if they divide evenly into the number. Suppose the number is 256 bits long, which is roughly 76 decimal digits long. Let's call it 80 digits. How many numbers would you have to try? All the primes up to the square root of the 80 digit number, and the square root will have 40 digits. So, it's about

    10,000,000,000,000,000,000,000,000,000,000,000,000,000

    Yes, but computers are fast, right? Suppose we have a fast computer that can try a billion factors every second. A billion is a 1 followed by 9 zeroes, so to divide by a billion, we just knock off nine digits. Then we only have to wait for

    10,000,000,000,000,000,000,000,000,000,000

    seconds. Since there are about 32 million seconds in a year, this will only take

    312,000,000,000,000,000,000,000

    years.

    The centerpiece of the RSA method uses numbers that are the products of two very large prime numbers, forcing Eve to buy very fast computers and wait a very long time to crack the encryption.

    Public Key Encryption in practice

    When you access a secure web server, your browser and the server become Alice and Bob. They want to communicate securely, but they don't know each other and they didn't make prior arrangements to have a secret key. Instead, they use the idea of public key encryption. When the little padlock icon closes, your browser has established a cryptographically secure connection to the server, and so your credit card numbers and other private information is safe from the Eves on all the network connections between you and the server.

    Is your information safe? Not entirely. Maybe someone can hack into the server. Maybe someone at the destination isn't trustworthy. Maybe the server is a complete fraud, put up by Mallory. Maybe someone was looking over your shoulder when you typed. There is probably no such thing as perfect security. We all have to decide how much effort to put into security.

    Encryption isn't just for web traffic. It could also be used for email and for telephone messages, including cell phones. Right now, anyone with a radio scanner and a little know-how can listen to cell phone conversations. Similarly, tapping a phone is very easy. Encryption lets us use any of these insecure media to send a private message.

    Hybrid Cryptographic Systems

    Furthermore, note that public key encryption solves one important failing of private key encryption, namely the key distribution problem, but private key encryption is not obsolete. The reason is primarily speed. Public key algorithms are very slow, much slower than private key systems.

    Therefore, the way things usually work in practice (say, by HTTPS) is a hybrid approach:

    • The sender creates a random session key suitable for use by some private-key algorithm.
    • The sender encrypts the session key using the receiver's public key and securely sends the session key to the receiver.
    • The sender and receiver then use the session key and the private-key algorithm to communicate securely.

    Digital Signatures and Authentication

    Suppose Alice wants to send Bob the message:

    Call off the attack, it's a trap! Signed, Alice

    She encrypts her message with Bob's public key and radios it to him. Meanwhile, Mallory, who is malicious, sends Bob the message:

    Go on with the attack, it's all clear! Signed, Alice

    She also encrypts the message with Bob's public key and radios it to him. She's pretending to be Alice! What is Bob to think?

    There's a cool aspect to public key encryption that we haven't mentioned. We said that one key decrypts what the other encrypts. In fact, both keys can encrypt, and the two keys are opposites, which means that one can decrypt what the other encrypts.

    So, here's what Alice does: she encrypts her message with her own private key. Bob gets it and successfully decrypts it with Alice's public key. (She has a web site with her public key listed.) He then realizes that only Alice could have sent this message, since only her private key can create a message that her public key can decrypt.

    Thus, public key encryption can give us digital signatures . The purpose of a regular, real-life signature is that, presumably, only you can sign your name the way you do. By comparison to a known signature on file, your bank or any other interested party can verify that something has been signed by you.

    The “signing” of digital certificates, which we discuss in the lecture on certificates, actually uses digital signatures just like this. It just involves a different use of public key encryption: a trusted third party signs the public key, using its own private key! This is confusing, so think about it for a while...

    Similarly, if there was a public key on file for a person, they can use their private key to “sign” an electronic document, even an email.

    Message Digests

    In practice, because public key systems are slow and verbose, people do not digitally sign the orginal document. If you have a 50-page long legal contract, you don't want to use public key to sign it, because the result would be 50+ pages of gibberish and would take a long time to compute.

    Instead, they sign a digest of the document. What is a digest? In the field of cryptography, a digest of a document is something that

    • Is a lot smaller than the document. Typically, it's a fixed number of bits, such as 128. In other words, that 50-page legal contract gets boiled down to just 128 bits.
    • Depends deterministically on the document. The digest of a document is always the same, from time to time and place to place, no matter who computes it.
    • If anything about the document changes, the digest changes. In other words, if you change one word buried deep in that 50 page document, say the customer owes the bank $100 to the customer owes the bank $500, the digest changes.

    (I'm tempted to say that the digest depends on the document, the whole document, and nothing but the document.)

    Thus, for the purposes of digital signatures, it's just as good to sign a digest as the original document, and it saves a lot of time and space. Here's what happens:

    • The sender, Alice, generates a digest of the message. Call it MD.
    • Alice uses her private or secret key to encrypt MD. Call this E(MD). This signs the digest.
    • Alice sends Bob (1) the message, (2) MD and (3) E(MD).
    • Bob re-computes the digest and compares it to MD to check whether the document was tampered with. Bob also applies Alice's public key to E(MD) thereby decrypting it. He compares that to MD to check that the message and MD were really sent by Alice.

    Many message digest algorithms have been invented. As of this writing, cryptographic experts recommend using one of the algorithms in the SHA-2 family of algorithms for digital signatures. (The algorithms differ in the number of bits in the digest, such as 224, 256, 384, and 512.)

    You can play with a JavaScript implementation of these SHA-2 algorithms.

    Key Escrow

    We've been taking the side of Alice and Bob, helping them keep information away from Eve. What if Alice and Bob are bad guys and Eve is the government? What's the point of getting a court order to tap a phone line if the conversation is encrypted? What can Uncle Sam do?

    Throughout the 90s, the U.S. government did several things:

    • It categorized strong crypto systems as munitions, like napalm and cluster bombs, so that it was illegal to export them from the United States. That's why there were domestic versions of Netscape and international versions. The international version didn't have the high-powered crypto.
    • It established the Data Encryption Standard (DES) and required computer manufacturers to use it for any encryption.
    • The DES required that the government be given a copy of any key generated, so that law enforcement could decrypt any message that it deemed necessary to decrypt, like getting a court order to tap a phone.

    There was a lot of resistance. Computer manufacturers didn't want to have separate international and domestic versions of software. Privacy advocates and civil libertarians worried about the government's power to invade privacy. (The keys would be split in half with the halves held by different agencies, to prevent a single agency running amok and violating civil rights.) Practical people pointed out that the bad guys wouldn't use crypto systems that the U.S. government had the keys to; they'd use foreign-made crypto systems. Eventually, the government caved in, but in our current climate, the desire to clamp down on cryptography will rise again.

    Discussion Topics

    1. How safe do you feel shopping online using secure connections? What about insecure connections?
    2. What do you think of digital signatures?
    3. Should the U.S. government allow private citizens to use encryption?
    4. Should the U.S. government require private citizens to use key escrow?
    5. Should the U.S. government forbid the export of strong encryption systems?

    Lesson Summary

    • Encryption makes a message unreadable by those who lack the special key. On computers, this is always a symbolic/numerical operation, such as substituting letters or rotating the alphabet.
    • Ciphers (procedures for encryption) vary in how difficult they are to crack. Substitution ciphers and the like can be quite easy, depending on how much ciphertext there is.
    • There are two broad categories of ciphers: private key and public key.
    • Private key ciphers have the disadvantage that Alice and Bob have to have a secure way to tranfer the key. While this may be fine in many real-world applications, it doesn't work well across the internet.
    • Public key ciphers allow Alice to send Bob a message by encrypting it with Bob's public key, so that no one but Bob can read it.
    • Public key ciphers also allow Alice to sign her message by encrypting it with her own private key, so that when Bob is able to decrypt it using her public key, he knows it's from Alice.
    • Key escrow systems allow the government to decrypt messages. There is still a lot of debate about this. Privacy advocates, civil libertarians and computer industry executives are against it. Law enforcement officials and others are for it.

      What do you think?

    Further Information and Examples

    Note that beyond here is information that we think you might find interesting and useful, but which you will not be responsible for. It's for the intellectually curious student.

    Triple DES

    Many more sophisticated private-key encryption schemes have been invented since Vigenère and Enigma, and research continues on new algorithms. (Recall that private key or symmetric encryption is still in constant use, in addition to or combined with public key schemes.) One private key algorithm, not even a particularly new one, is called Triple DES, because it is based on the older DES — Data Encryption Standard. If you want to encrypt a message using a private key system, and you want to use something better than the Vigenère form that we provide above, Triple DES is a reasonable choice.

    Here is a link to a form that allows you do encrypt using Triple DES.

    How to use it:

    1. Go to the page above and generate a private key (the top box in the form).
    2. Use a public key encryption scheme to send that key securely to the person you want to correspond with.
    3. Either of you can then use the form and the key to encrypt messages to send to each other, and to decrypt messages you receive. Put the input (either the plaintext to encrypt or the ciphertext to decrypt) in the box labeled input and click the appropriate button below the box. The output appears below.

    Solutions to Exercises