HTML
This reading accompanies Chapter 2 of your book. That chapter does a nice job of introducing bits of HTML as needed. Read that first and feel free to work through their presentation. Here's an organized summary of what we learned, plus a bit more.
If you don't have Chapter 2, here's a link to a copy of a scan of the chapter. To respect the author's copyright, the link is only valid on-campus or with a password. Ask Scott if you don't have that password.
Languages¶
We learned that web pages are written using three languages
- HTML, which is the skelton and organs
- CSS, the skin and clothes. We'll look at that in the next chapter.
- JavaScript, which defines the behavior. We'll get to that later.
HTML template¶
Our basic page had the following template:
#!HTML
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Ottergram</title>
</head>
<body>
<header>
<h1>Ottergram</h1>
</header>
</body>
</html>
Tags¶
We learned the following tags. Look at W3Schools or MDN to learn more.
head
holds meta information about the documentmeta
tells the browser the character set. More about this much later in the course. We'll always useutf-8
title
is used for window titles, bookmarks, and is used by search engines. More important than you'd think.body
holds all the contentheader
holds headers and related stuff like logosh1
holds the text of a major headinglink
connects a separate file of CSS rules to an HTML file. The URL of the CSS file is thehref
attribute.ul
is a container for an unordered list (bullet list)li
is a container for a list itemimg
is replaced (a replaced element) with an image loaded from a separate file, specified using thesrc
attribute.a
demarks a clickable hyperlink
Meaningless Tags¶
All the tags above have some kind of meaning associated with them. They
are for some kind of content. However, HTML also comprises two
meaningless tags, span
and div
. A span
demarks some text or other
inline information. (Inline content is stuff like text that fills up a
line before flowing onto the next line.) A div
demarks a big block or
division of a document.
These tags are useful for styling and behavior (attaching JavaScript to them).
Chrome Developer¶
They described the Chrome Developer. This is how we look behind the matrix to see what's really happening.
Some other useful tags:¶
em
to emphasize some text. Typically is italic.strong
which is likeem
but more so. Typically is bold.h2
toh6
for different levels of headersp
for a paragraph. Can't nest or contain other block elements.br
for a line break. Usually avoid this because it can break layoutsol
for an ordered (numbered) list
Tags should be properly nested:
<foo> <bar> </bar> </foo>
not
<foo> <bar> </foo> </bar>
Here links¶
Once, it was very popular on the web to have links like this:
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:
- Here are some apple pie recipes.
- Click here for peach pie recipes.
- Yo, check out the prune pie recipes.
Accessibility is very important in this class, so keep that in mind.
The ALT Attribute¶
An IMG tag looks like this:
:::HTML
<img src="url/of/picture.jpeg" alt="picture of something">
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
Figures¶
Now that we know about the img
tag, it's useful to know about a semantic
tag that can be used with it. We can use figure
to surround an img
tag, paired with figcaption
for the caption text:
:::HTML
<figure>
<img src="../images/hermione-granger-256.jpeg" alt="Hermione Granger">
<figcaption>Hermione Granger as played by Emma Watson</figcaption>
</figure>
Here's what it would look like:
Note that images can be used without figure
; a figure
is often used as
in a book, where the text refers to a figure to provide additional
information. Also, the use of figcaption
doesn't remove the obligation
to provide alt
text. Still, this can be a useful tag to know about.
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.
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 >
.
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. 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 reference page.
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!
:::HTML
<p>
<a href="http://validator.w3.org/check?uri=referer">
<img
src="http://cs.wellesley.edu/~cs204/Icons/valid-html5v2.png"
alt="Valid HTML 5"
title="Valid HTML 5"
height="31" width="88">
</a>
</p>
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.
Tag Name | Short Description |
---|---|
<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). |
<main> |
Defines the main content of a page. |
<article> |
Defines independent, self-contained content (e.g., blog post, news story). |
<abbr> |
Indicates an abbreviation or acronym.
See an example in action in the paragraph below for the word W3C. |
<figure> |
Indicates an figure or other graphical content |
<figcaption> |
A caption inside a figure element |
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:
Review of URLs¶
In class, we learned about two kinds of URLs: relative and absolute:
- absolute URLs start with a slash (or
http
orhttps
) and specify the same destination regardless of starting location - relative URLs start with a name (or
..
) and specify a destination as a series of steps from the starting location
Relative URLs have the advantage that if the starting file and ending file are moved to a different place, but continue to share the same relationship (for example, they are in the same folder), then the relative URL will continue to work after they are moved, while an absolute URL will necessarily break.
Here are the rules for relative URLs:
- a bare name, like
fred.html
is a file or folder in the same folder as the starting point. - a slash means to go down into a folder. So
stuff/fred.html
means thatstuff
is a folder in the current folder (by rule 1) andfred.html
is insidestuff
- a
..
means to climb out of a folder and go to the parent folder. So../fred.html
means thatfred.html
is in the folder above the starting point.
These rules can be combined to yield long relative URLs like
../../africa/botswana.html
which is a file in the africa
folder that
is two folders above this one.
Ottergram¶
At the end of the chapter, the final page's HTML code is the following:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>ottergram</title>
<link rel="stylesheet" href="stylesheets/styles.css">
</head>
<body>
<header>
<h1>ottergram</h1>
</header>
<ul>
<li>
<a href="#">
<img src="img/otter1.jpg" alt="Barry the Otter">
<span>Barry</span>
</a>
</li>
<li>
<a href="#">
<img src="img/otter2.jpg" alt="Robin the Otter">
<span>Robin</span>
</a>
</li>
<li>
<a href="#">
<img src="img/otter3.jpg" alt="Maurice the Otter">
<span>Maurice</span>
</a>
</li>
<li>
<a href="#">
<img src="img/otter4.jpg" alt="Lesley the Otter">
<span>Lesley</span>
</a>
</li>
<li>
<a href="#">
<img src="img/otter5.jpg" alt="Barbara the Otter">
<span>Barbara</span>
</a>
</li>
</ul>
</body>
</html>
You can view that initial version of ottergram in your browser.
Let's take a moment to talk about the HTML.
- The bulk of the page is a list. Most web pages will not be like that, and indeed, neither will the finished Ottergram.
- Each list item is a hyperlink with the odd URL of
#
. That's a fragment identifier, and they use it for an odd reason that we'll talk about below. - Each hyperlink is wrapped around an
img
and aspan
. The span is essentially the caption of the image. Better semantic markup might have usedfigure
andfigcaption
.
Fragments¶
Above, we discussed URLs, but I left something out:
fragments. Notice the hyperlink at the beginning of this paragraph. It
goes to a particular place on this page. It's able to do so because
the destination has an id
attribute, and the URL specifies that id
after the #
character.
In general, a URL looks like https://machine.domain/path/to/file.html#fragment_id
The URLs in Ottergram consist solely of the #
, so there's no
fragment ID and the filename is missing as well. What that hyperlink
does is go to the same page. Try it!
Hyperlinks as Clickable Elements¶
A hyperlink to the same page we are on is not very useful. However, it is clickable. Later, in chapter 6, we're going to write some JavaScript code to hijack the click behavior and do something interesting and useful. For now, we just wanted to create a page with clickable elements. That's what these do.
The End¶
This is just the beginning of HTML. There's a lot more you could learn, but this will do for now. Title: CS 204 CSS
CSS
Chapter 3 on Styles does a nice job of introducing bits of CSS as needed. Read that first, at least through page 55. Here's an organized summary of what we learned, plus a bit more.
If you don't have Chapter 3, here's a link to a copy of a scan of the chapter. To respect the author's copyright, the link is only valid on-campus or with a password. Ask Scott if you don't have that password.
CSS concepts¶
- normalize.css removes some of the formatting differences between browsers, making it easier to build consistent websites
- A CDN is a content delivery network, useful for lots of common files, including jQuery
- CSS rules, which include
- selector(s)
- properties and values
CSS rules¶
:::CSS
header, footer {
margin: 0;
padding: 8px 4px;
background: cornflowerblue;
color: inherit;
}
CSS Properties¶
- background background colors
- border an optional box around the element
- color font colors
- display how an element is laid out on the page:
block
stacks vertically,inline
is like text. There are other values, likenone
to act as if the element doesn't exist - font-family sets the font for the element
- font-size sets the size of the font
- list-style can change or remove the bullets in a bullet list.
- margin spacing outside the element's border
- padding spacing between the box and the contents
- text-align can center text, right-align it and such
- text-decoration can add or remove underlines and such
- text-transform can capitalize, lowercase or uppercase text
- width is the width of the contents of the element, not including any padding, borders or margins. This can be very confusing.
Several of the above are shorthand properties. You can be more specific, like border-left-style
Box Model¶
The box model is most easily learned by playing with the dev tools, but the idea is simple:
- block elements work like big boxes that are (by default) stacked vertically on the page
- they have, outside to inside:
- margins. These just have widths. They have the background color of the parent block
- borders. These can have widths, styles, and colors
- padding. These just have widths, but they take on the background color of this block
- content. This has width and many other properties
You can use display:block
as a declaration to turn a non-block element
(like A, IMG or SPAN) into a block element.
Selectors¶
There are quite a few kinds of selectors available in CSS. Some are used often, some only rarely. Here are some that are simple and very common:
- tag: style every such tag (e.g. paragraphs
<p>
or list items<li>
) You have to specify one of the existing HTML tags, likep
- classes: style every element with that class. Make up a class name,
say
fred
and use.fred
as the selector. Specify the class with an attribute, like<p class="fred">
- id: style the (unique) element with that ID. Make up an ID, say
george
and use#george
as the selector. Specify the id with an attribute like<p id="george">
Our book authors advocate avoiding ID. I don't really agree with their reasoning, but their way is fine, too. If something is definitionally unique, I don't see a problem with giving it a unique ID. Furthermore, IDs are the only way to specify a location within a page using a URL. Let's turn to that now.
IDs¶
This section is not covered in the chapter, or indeed, in the book,
as far as I can tell. Still, it's worth re-explaining the href="#"
that they used in Chapter 2.
This section is really about URLs. We learned that URLs uniquely specify a single webpage in the world. URLs are even more powerful than that. They can even specify a location within a page. This is done by doing two steps:
First: Giving the location an ID. That's done in HTML with the ID attribute. Any element in HTML can be given an ID, like shown this:
<span id="george">this span is george</span>
This span is george
Second: The absolute URL to specify that location is like
http://domain.com/path/to/page.html#id-of-element
The #
is a
special character (called a hash mark, sharp sign, pound sign)
separating the URL for the page from the ID of the element (called a
fragment).
With relative URLs, you can omit things. So a within-page link to a
fragment would just be #id-of-fragment
.
Try these two examples, and look at the location box in your browser:
When a web designer wants a link to the current page, they will usually
use #
as the entire URL, letting everything default. Here's a link to
this page.
ID versus Class¶
If you're confused about the difference between ID and class, you're not alone. Many students have been confused about this.
Here's the key difference: an ID has to be unique, meaning there can be only one element with a particular ID. If we anthropomorphize the elements on our page, an ID is like a Banner ID: there should be only one person with a given ID (barring identity theft).
If we use an ID to identify a place on a page for a URL, we want to specify a single place to go, not multiple places. This reminds me of a short (1:20) clip from Monty Python's Life of Brian: you are all individuals
Classes and IDs are similar in the following ways:
- we make up a label
- we apply the label to 1 or more elements
- we refer to the label from the CSS rules
The difference, of course, is that an ID is a label that can be applied to at most one element, while a class is a label that can be applied to any number of elements.
Interactive Demonstration¶
I created an interactive selector display that will help show you what elements various selectors pick out. To use it, first, view source just to see the relevant stuff that is going to be picked from. It's not the whole page, just the part with the beige background. The HTML looks something like:
<h2>this is an h2 header</h2>
<p id="par1">This paragraph has ID <code>par1</code></p>
<h2>this is another h2 header</h2>
<p>this paragraph precedes the list of fruits and veggies</p>
<ol id="list1">
<li class="fruit">apple</li>
<li class="veg">broccoli</li>
<li class="fruit" data-tag="tough">coconut. this is tough</li>
<li class="fruit">date</li>
<li class="veg">endive</li>
<li class="veg" data-tag="yucky">fennel. this is yucky</li>
<li class="fruit">"g" fruits
<ul>
<li>gooseberry</li>
<li>grape</li>
<li>grapefruit</li>
<li>guava</li>
</ul>
</li>
<li class="veg">horseradish</li>
<li>tomato</li>
</ol>
<p>this paragraph follows the list of fruits and veggies</p>
Take a brief look at the tags, classes, ids, and the overall structure. Then click thorough and try the various selectors.
Summary¶
- CSS is how we apply style to our page.
- It consists of a set of rules
- Each rule comprises a set of properties and values, like
color: red
- The box model applies to all block elements, such as paragraphs
(
p
), lists (ol
andul
), list items (li
) anddiv
. - In the box model, an element has (from outside to inside):
- margin. This just has width
- border. this has a width, style and color
- padding. this just has width. Its background color is the same as for the content
- content.
- each rule also has a selector, which chooses which element(s) to apply the rule to.
- simple selectors include:
- tag, like
p
to apply to all paragraphs. Has to be one of the built-in HTML tags. .class_name
to apply to all elements withclass='class_name'
. We get to make up the class name.#id_name
to apply to the sole element withid='id_name'
. We get to make up the id name.
- tag, like
- The difference between classes and ids is that an id has to be unique.
Chapter 4 Supplement
This reading summarizes and expands on the concepts of responsive and flexible layouts that we learned in chapter 4.
Mobile First¶
We should first design our websites so that they work effectively on small devices, and only later take advantage of greater space. Some rules of thumb:
- don't lay things out horizontally; stack things vertically
- give images CSS declarations like
width:100%
so that they scale to smaller displays - don't use table elements and such that might be wider than the display
- specify widths in percentages when feasible
- don't specify widths of elements in pixels (or, at least, wide widths) which might result in the dreaded horizontal scrolling
inline-blocks¶
In the last chapter, we learned about inline elements, like span
, that
are found in running text and would move around as the browser gets wider
and narrower.
We also learned about block elements, which use the box model, can (typically) contain other block elements, and stack vertically on the page.
We now know about inline block elements, achieved with
display:inline-block
. Such elements act like inline elements in terms of
filling out the width of their container (moving other inline elements up
from the next line until there's no more space), but they act like block
elements in that they can contain other block elements.
Note that the default width of a block or inline-block element is 100%
,
which means that there is never any room left to bring another one up from
the next line. So, it only makes sense to use inline-block where you are
setting the width (or it's a replaced element, like an img
, and so the
width is derived from the contents). Like this:
:::CSS
selector {
display: inline-block;
width: 20%; /* five on a line */
...
}
New HTML¶
- main The main content of a page. Bigger than an article
- div A meaningless block container. Useful for structuring the page
Flexbox¶
With Flexbox, there is
- a container that is limited in size. Presumably takes the whole screen or a portion thereof. Get these with
display:flex
. Contrast that with a Wikipedia page that is as long as it needs to be - a set of flex-items to be displayed, all children of the container. This is automatic.
- a direction or main axis that the children will be oriented in (horizontally or vertically)
- a cross axis that is perpendicular to the main axis
- a specification for what happens with any leftover space in the flex container
Flex containers can be nested, so you have have rows with columns, columns within rows, even rows within rows and columns within columns.
Flex items can grow and shrink. We learned two uses of the flex
shorthand property:
flex: 0 1 auto
means don't grow me, shrink me if needed, and calculate my size from my contentsflex: 1 1 auto
means grow me as much as possible, shrink me if needed, and calculate my size from my contents
New CSS Properties¶
Pretty much all of these are related to the new flexbox layout
- align-items aligning (e.g. centering or stretching) flex-items. If the item doesn't fill the space allocated to it, where does it end up in that space. MDN align-items
- display:flex to specify an element as a flex container
- flex how a flex item shrinks or grows
- flex-direction row or column
- justify-content what happens with leftover space in a flex container?
- overflow set what happens when an element's contents is bigger than it is. Scroll? Hide? Show?
- order what order does this flexitem go in? source order? after others? before others? contents is bigger than it is. Scroll? Hide? Show?
- text-shadow can add a shadow to some text by reprinting the text in a different color and a small displacement
- white-space what happens with white space in an element: normal? nowrap?
Absolute and Relative Positioning¶
Normally, we let the browser figure out where an element should land on the page, based on its size, the size of the container, whether it's a block or inline element, and so forth. This is because the default value of the position
CSS property is static
. It has two other interesting values:
position:relative
which allows you to shift the element from its static positionposition:absolute
which allows you to place the element within a Cartesian coordinate system
Here's how that's done. First, the CSS:
:::CSS
.up_and_right {
position: relative;
top: -1em;
left: 2em;
color:red;
}
Here's the HTML:
:::HTML
Here's a sentence in which a single red
<span class="up_and_right">word</span>
has been moved from its usual place.
In general:
- The element is shifted vertically using either
top
orbottom
and giving a signed distance by which to move the top or bottom of the element. - It's shifted horizontally using either
left
orright
and another signed distance. - The starting location is where it would have
been if it had been
position:static
rather thanposition:relative
. - Note that other elements don't move as a result of the movement of this one. (There's a gap left in the sentence above, where the word was moved from.)
Position absolute is similar, except that the distances are measured not from the element's static position but in an absolute coordinate system, where the origin of the system is the first non-static ancestor and if no non-static ancestor is found, the browser window.
Therefore, another use of position:relative
is to set the coordinate
system for its descendants. I like to think of this as "my descendants
are positioned relative to me". Here's an example:
This is done by:
- putting
position:relative
on the ancestor (here the box with gray background) - putting
position:absolute; top:30px; left:50px
on the pink child - putting
position:absolute; top:-10px; left:-20px
on the green child - putting
position:absolute; bottom:20px; right:30px
on the blue child
Use this feature sparingly. Sites where everything is positioned in
absolute coordinates are incredibly inflexible. You want a site that is
responsive to the size of the browser. Nevertheless, sometimes
position:absolute
can be useful.
Note that with position:static
, elements can never overlap. In
particular, text can't overlap. But with position:absolute
and
position:relative
you can do that, if you want.
Flexbox versus Float¶
Flexbox is relatively new (circa 2014, though proposals go all the way back to 2009). Prior to widespread support for flexbox, web developers used float, which still has some useful features and is still worth knowing about.
Here's a simple example of float, where we get the text to wrap around an image:
Hermione Granger was indispensable in the Harry Potter series. Harry had the title role, and he was clearly critical to the story, but he did not have exceptional magical skill. His nemesis, Lord Voldemort, was an extraordinary wizard, matched only by Dumbledore. Harry, was good, but no more than good. Hermione, on the other hand, was "the brightest witch of her age" according to Remus Lupin. There was no spell she couldn't do, and her cleverness and foresight saved Harry countless times.
Float causes the floated elements to be
- Removed from the flow, so that later stuff moves up on the page, and
- shoved back into the page, causing block elements to overlap it and inline elements to wrap around it.
The example above shows the idea. Hermione's picture is floated (to the left in this case) and the paragraph text (inline elements) flows around it.
Centering Block Elements and Text¶
People love centering, particularly novice designers. Centering moves things away from the edges, which makes it feel more comfortable, without having to decide how much to move it. But there are two kinds of centering. There's centering block elements and centering inline elements like text. Let's start with centering text:
Centering Text¶
Centering text is pretty easy: just specify text-align:center
on its
parent element (or, in general, some ancestor, since the setting is
inherited.)
You should almost never center lines of text in a paragraph. 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:
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 Blocks¶
Here's an example of a block element (blue background) centered within its container (red border):
Note that, by default, block elements are width:100%
which means that
they are as wide as their container will let them be. So, by default,
centering is not possible, because there's no extra space to center
within. Therefore, to center a block element, you usually have to set its
width to something smaller than its normal width. The blue block above is
80% of its container. One exception is IMG elements, since they get their
width from the actual image, not from the container. However, pictures
are often quite wide, so you typically have to scale them down using a
width
setting anyhow.
The trick to centering a block element is to set its margin-left
and
margin-right
to auto
. Auto margins means to take whatever space is
leftover in the container and distribute it equally to the two margins.
The example above used a shorthand: margin:10px auto
which means the top
and bottom margins are 10px and the left and right are auto
.
Galleries with Floating Elements¶
We often want galleries of elements, where there should be as many on a
line as will fit, but fewer if necessary, without any horizontal
scrolling. One way to do that is by setting display:inline-block
and
set the width on the gallery elements, which allows you to put arbitrary
content in each element, while still having them fill the line like inline
elements.
Another way is to use float:left
as shown by W3schools
Gallery
Chapter 5 Supplement
This reading summarizes and expands on the concepts of adaptive layouts with media queries that we learned in chapter 5.
Summary¶
- standard term is responsive though I agree with their objection
- viewports:
- layout viewport: what the developer (and the browser) uses for
- layout (where elements go and how big they are: think "magazine layout")
- visual viewport: what the user sees
- often the visual viewport is narrower than the layout viewport, requiring
- zooming out
- scrolling
- set the layout viewport with this:
:::HTML
<meta name="viewport"
content="width=device-width, initial-scale=1">
- media queries using (in CSS) like this:
:::CSS
@media all and (min-width: 768px) {
selector {
flex-direction: row;
}
/* other CSS rules */
}
- setting print styles:
:::CSS
@media print {
body {
/* Note "pt" (points) not "px" (pixels).
72.27pt = 1 inch */
font-size: 12pt "Times New Roman";
}
/* other CSS rules */
}
Media Queries¶
A media query, like all CSS rules, overrides earlier rules. So, the question is, what is the default: the large device or the small device?
Given the primacy of mobile nowadays, it's better to design for small and later make use of larger devices.
Therefore use min-width
:
:::CSS
@media all and (min-width: NNNpx) {
/* rules for large devices */
}
rather than max-width
:
:::CSS
@media all and (max-width: NNNpx) {
/* rules for smaller devices */
}
Breakpoints¶
What widths make sense to use to call in a different layout? Common values are:
- 320px smartphones
- 786px tablets
- 1024px laptops and desktops
These are called breakpoints where you switch from one layout to another. See Media Queries for Common Device Breakpoints
Of course, those values aren't cast in stone. New devices and pixel densities are always coming out.
JavaScript
CS 111 is a prerequisite for CS 204, so our introduction to JavaScript will compare it to Python. If you skipped CS 111 or have forgotten Python, let me know.
Finally, there's some practical information on how to run JavaScript
Title: CS 204 How to Run JavaScript
How to Run JavaScript
There are two main ways you will be integrating JavaScript into your HTML code:
- Using the
script
tag - Using an external file
This is very similar to CSS, as you can use the <style>
tag or link
an external CSS file.
Below is how you would integrate JavaScript into HTML using the
<script>
tag. The JavaScript code is between the <script>
tags. Examine the code below, then switch to the results tab to see it
run in action.
Showing another way, below is how you would use an external JavaScript file. Examine the JavaScript and HTML files, then switch to the results tab to see it run in action. In CS 204, we will mostly be using external JavaScript files.
JS Console¶
It's nice to be able to try little bits of JS code (just as we might try little bits of Python code by running the Python interpreter). Fortunately, every browser has a JS console (interpreter) built-in so it's easy to test little snippets. I do this all the time.
Getting to the console in Chrome on a Mac:
- At the top bar, go to
view > developer > JavaScript Console
, or Command-Option-J
Getting to the console in Firefox on a Mac:
- At the top bar, go to
tools > web developer > Web Console
, or Command-Option-K
It might look like this:
If you type any Javascript expressions into the console, it will works as well:
Title: Closures and Namespaces
Closures and Namespaces
This reading is supplemental to Chapter 8 (through page 173), which uses Immediately Invoked Function Expressions (IIFEs) to establish namespaces. This reading also discusses closures, which are briefly described on page 133.
A closure is a special kind of function, and a namespace is a way that a programming language can support separation of code. Consequently, you'll learn more about these concepts in CS 251 (Programming Languages), but they are important, practical concepts that arise naturally in JavaScript code, so we'll learn about them now.
But, before we get to closures, let's review some ideas that you probably remember from prior CS classes, but I want to bring to the top of your mind.
Scope¶
In JavaScript, variables can be local or global. A global variable can be seen by any code anywhere; local variables can only be seen from a small part of the code. For example, consider the following code:
var glob = 13;
function fred(x) {
return x+glob;
}
function george(x) {
x = Math.random();
glob = Math.random();
return x+glob;
}
The global variable glob
is visible to both functions. (The function
names fred
and george
also go into the global namespace and so are
visible to each other. For example, they could invoke each other.)
The local variable x
is local to each function. I could
simultaneously
invoke fred and george with different values for x
and nothing would go wrong, because they are different names and therefore
different storage locations. Imagine each function is a family, and both
families have a child named x
(short for Xenophon
and
Xerxes
). Different kids, different storage locations, but the
identical names cause no confusion. For the functions, the x
variable
exists only during the function call and disappears when the function
completes.
Other Scopes¶
There are other scopes in addition to local and global. We actually used these in the Plotting assignment without realizing it. Here's an example; see if you can figure out what it does:
function curve13(max, incr) {
var xvals = range(max);
var f = function (x) { return x+incr };
var yvals = xvals.map(f);
newPlot(xvals, yvals)
}
Focus on the f
function. What is the scope of x
? It's local to f
,
of course. What is the scope of incr
? The incr
variable is local to
curve13
but it is non-local to f
. The incr
variable refers to the
environment that curve13
created.
A variable that is non-local like incr
means that f
is a
closure. We say that f
is a "closure over incr
".
If a closure is returned from a function, it can continue to refer to
its original environment. We did this in the Plotting assignment as well:
the functions returned from quadratic
and cubic
continued to refer to
their original environments, which is how they continued to know their
coefficient and roots.
What is a Closure?¶
Formally, a closure is a function plus an environment (you can read more about them in the Wikipedia article on Closures), so to begin getting a handle on them, we start with some more observations about functions.
Functional Programming¶
The following functions f1
and f2
depend only on their inputs (rather
than on some global state information), which makes them easier to
understand than the function g1
which depends on some global variable
glob
. (For example, suppose glob
is a string: then the value of g1
is a string, too.)
var f1 = function (x y) { return x + y; };
var f2 = function (x) { return x + 4; };
var g1 = function (x) { return x + glob; };
When we talk about ''functional programming'' in Computer Science, we are
thinking about functions like f1
and f2
, where calling the functions
with the same inputs always yields the same output. The same can't be said
of g1
. In general, when we say some code is functional, we mean that
it depends only on its arguments, not on external state (like glob
) or
even internal state (its prior history of executions). We'll return to
this later.
Function f1
is just the add
function; we might call f2
the add4
function. Since functions are first-class objects in JavaScript, we can
dynamically create them and return them from functions. So, the following
function can create functions like add4
:
var makeAdder = function (delta) {
return function (x) { return x+delta; }
};
var add4 = makeAdder(4);
alert(add4(3));
Now, what kind of function is add4
? It's functional, in the sense that
its value only depends on its arguments, not on any global state
(certainly none that can change). Yet the code looks nearly the same as
g1
. What's the difference? The difference is that the glob
that g1
refers to is global and can change dynamically, while delta
is a
lexical variable in the environment of the anonymous function returned
by makeAdder
. That function includes both the function plus that bit of
environment, so it is a closure.
If you think about our earlier discussion of scopes and environments, the
environment of the anonymous function returned by makeAdder
includes the
parameter delta
and the delta
continues to exist even though
makeAdder
has returned. It continues to exist because the anonymous
function needs it. We say that the anonymous function has closed over
the name delta
.
An Example: A Shopping Example¶
Let's see closures in action in a web page. Suppose we have a page that has an item for sale, say apples, and it has an associated button that increments a counter, updates a database, updates the web page and maybe other things. So, you write some code like this:
function updateAppleDatabase(n) {
console.log("Apple Database updated with "+n);
}
Here's the HTML code:
And here's the JavaScript code:
The event handler function we've written is not functional (it depends
on the global variable appleClicks
). Nevertheless, the code works fine.
Next, we decide to add additional buttons for bananas, coconuts, dates, eggplants, figs and the rest of the alphabet. Of course, we could copy/paste the code above for each of our grocery items, but copy/paste usually a bad idea. Duplicate code means that if we change our implementation, we have to update all the copies of the original implementation.
Event Handler Maker¶
But how do we write a generic
event handler? We could write a
function to make one. While we're at it, we'll make the
updateAppleDatabase
function more generic.
function groceryClickHandlerMaker(item,outputId) {
var counter = 0;
return function () {
counter++;
updateDatabase(item,counter);
$(outputId).html(counter);
};
}
How do we use the groceryClickHandlerMaker
? Here are two examples, where we
invoke the groceryClickHandlerMaker
function to return a closure that
we then attach as the click handler.
Here's the JavaScript code:
Closure Variables¶
Let's look again at the groceryClickHandlerMaker
:
function groceryClickHandlerMaker(item,outputId) {
var counter = 0;
return function () {
counter++;
updateDatabase(item,counter);
$(outputId).html(counter);
};
}
What variables does it close over? It closes over every variable that is not defined within the function. Here there are three:
item
outputId
counter
The first two closure variables won't change ever, so the JavaScript engine can really just substitute the values as static constants. The counter, however, is interesting, because it's updated by the closure invocation, which means that the closure isn't functional in the technical sense of its behavior only depending on its arguments. Its behavior depends on how many times its been executed before.
Namespaces¶
Some very cool properties of the counter
variable used by the click
handlers above are that
- there are several of these variables, one for each handler
- they all have the same name, but
- they are all completely unrelated, and
- they are all completely private
Think about that last property for a moment: each click handler has its own private state variable. (This should remind you of instance variables in object-oriented programming.) Indeed, each closure has its own private namespace.
What's a namespace? In general, a namespace is a mapping from names (symbols) to values. You can think of the names as variables, as we will here, since in JavaScript we can assign a function to a variable. Namespaces are important in programming because they help us avoid name collisions. For example, many years ago, I was doing some graphics programming and I has some variables that stored the hex codes for various colors:
var red = 0xff0000;
var white = 0xffffff;
var tan = 0xd2b48c;
var teal = 0x00ffff;
...
I also needed to compute the tangent of an angle:
var tan_theta = tan(theta);
I'm embarrassed to admit that it took me hours to understand why the
tangent function wasn't working. The problem was a name collision: I had
only one namespace, so tan
could only have one value.
In JavaScript, the tan
function is safely in the Math
object and so we
say Math.tan
to use it. The Math
object gives us a kind of namespace.
We could create one for Colors very easily in JavaScript using objects:
var Colors = {};
Colors.red = 0xff0000;
Colors.white = 0xffffff;
Colors.tan = 0xd2b48c;
Colors.teal = 0x00ffff;
We can put functions in the object as well, like the tan
function is in
Math
. Suppose we had a function lighten
and we didn't want to clutter
up the global namespace with it. We could put it in Colors
:
Colors.lighten = function (color) { ... };
This technique is very common in JavaScript programming. Another, even more common, is to use functions.
Functions as Namespaces¶
Let's take a very abstract example so that the details of the code don't
confuse the issue. Suppose we want to have a bunch of global variables
and functions with short, succinct names for brevity. The functions might
be mutually recursive, might refer to the globals, and so forth. After all
those definitions, the thing we actually want to do is compute f(1)
and
insert the result into page . Our code might look like this:
var a = 123;
var b = 456;
var f = function (n) { ... g(a*n); ... };
var g = function (x,y) { ... f(b*x)+f(b*y)...; }
$("#ans").html(f(1));
This code would work, but it would not be good software engineering, because of the potential for namespace conflicts. So, we can just make all these variables be local variables of a new, anonymous function that we will immediately execute.
(function () {
// code from above
})();
Notice that the function expression is wrapped in parentheses: that's necessary so that it won't be treated as just a top-level function definition. The parenthesized function expression is then followed by a pair of empty parentheses which causes the function to be invoked. This is called an Immediately Invoked Function Expression or IIFE. Wikipedia has more about Immediately Invoked Function Expressions.
Using an IIFE means that no names are added to the global namespace, so
the code has no footprint at all. (The footprint
of code is the set
of names that are added to the global JavaScript namespace.)
Modules, Objects and Methods
This reading is supplemental to Chapter 8 (page 173 to the end).
Many of you are familiar with Python from CS 111. Python has a nice module system in which we can import various helpful modules into our main program. Our code might look like this:
:::Python
import math, cs1graphics
def modifyPicture(pic,angle):
cs1graphics.adjustY( pic, math.tan(angle) )
Don't worry about the details of the code. I doubt that adjustY
exists;
I just made it up. The point is that we can use functions that are defined
in different modules by using the syntax module.name
where the part to
the left of the dot is the name of the module (math
or cs1graphics
)
and the part to the right is one of the names that lives in that module.
Moreover, the set of names in each module is separate. If, by coincidence,
both modules use the same name, there's no conflict. One could be
math.PI
and the other could be cs1graphics.PI
Separating sets of names like this is useful in CS, because it reduces the chance of accidental name collisions.
A set of names and values like this is called a namespace. There are lots of kinds of namespaces; a Python module is just one. We'll see a few more.
In fact, Python dictionaries are a kind of namespace, because again they comprise a set of names and values. We look things up and store things under various keys which can be strings or names
:::Python
math2 = dict()
math2['pi'] = 3.2
math2['e'] = 2.71828
colors = dict()
colors['red'] = 0xff0000
colors['tan'] = 0xd2b48c
Indeed, my understanding is that Python's modules are implemented using dictionaries.
JavaScript objects are namespaces¶
We can do the same thing as Python modules in JavaScript by using objects, which are just like Python dictionaries. They also conveniently give us separate sets of names. For example:
:::JavaScript
math2 = {pi: 3.2,
e: 2.71828,
tan: function (angle) { "complex code here"; },
sqrt: function (num) { "newton's method"; }
};
colors = {red: 0xFF000,
green: 0x00FF00,
black: 0,
white: 0xFFFFFF,
tan: 0xd2b48c};
math2.tan != colors.tan;
The above code creates two objects that work just like Python modules:
they give us module.name
sets of names and the names are distinct, so
if, by coincidence the same name is used in both modules, everything is
okay.
Inside and Outside¶
From outside a module, you have to access a value using the dot notation,
like math.PI
. From inside a module, you can usually use a shorthand
that omits the module name. That is, inside the math
module, your code
can just refer to PI
and it means the PI
in this module.
In fact, in Python a module doesn't necessarily know its name, and it can be imported as something else. In England, they probably do the following:
:::Python
import math as maths
print(maths.tan(2*maths.PI))
Can we do that in JavaScript? We can, but we will use the function namespace to do it.
What do we mean by a function namespace? A function has an "inside" and an "outside": inside the function, we can refer to local variables, and those are not useable from outside. We'll use a function's local variables for the inside of our module.
:::JavaScript
math2 = (function namespace() {
var PI = 3.2;
function area(radius) {
return PI*radius*radius;
}
var mod = {};
mod.PI = PI;
mod.area = area;
return mod;
})();
Title: Forms
Forms
This reading supplements Chapter 9, which introduces forms along with Bootstrap. This reading focusses just on the forms.
Forms are an import part of any website in which the user interacts, such as suppling information or making choices (e.g. menu options).
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 ask. 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. In this course, we
won't always be submitting the form to a web server, so we will
occasionally use form inputs without surrounding them with a form
tag,
but mostly we will use it. Your book does in Chapter 9.
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.
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 (also known as
controls). 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.
Control HTML | Rendered Control | More Info |
---|---|---|
text: <input type="text"> |
info | |
number: <input type="number" min="1" max="120"> |
info | |
range: <input type="range" min="100" max="200"> |
info | |
date: <input type="date"> |
info | |
time: <input type="time"> |
info | |
<button type="button">Click me</button> |
info | |
long text: <textarea rows="2" cols="10"> </textarea> |
info | |
menu: <select><option>Black <option>White </select> |
info |
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 aspects of forms.
The input
Tag¶
The input
tag is fairly straightforward, but you can
specify the type of input you are looking for by 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 phrasepassword
: 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 sometimes.
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>
<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, which we'll talk about later.
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 both the input and the text 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. The <label>
tag still wraps
the textual label, but it no longer wraps the control/input.
<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 it 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. Your book uses the for/id approach.
Using labels is important for accessibility. More on this below.
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:
name | value |
---|---|
customer | Hermione |
phone | 555-8888 |
addr | hgranger@hogwarts.ac.uk |
size | large |
due | 21:00 |
instructions | please 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 chosen by us, the authors of the form. It 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 every time we create form fields. - The
value
attribute is the information from the user. It can be typed in by the user, chosen from a menu, or some other way.
Placeholder¶
Another useful attribute for input
controls is
placeholder
, which can be used to provide a hint or
example of the kind of value that should go in a field. For example,
this HTML
<input type="text" placeholder="Hermione Granger">
will be rendered like this:
.
Radio Buttons¶
Radio buttons are used for a set of mutually exclusive options, like the buttons on a car radio, to choose the station.
Important: Radio and checkbox input items should all have the same name, so that they are considered as related. Without the same name, radio buttons will not be mutually exclusive.
HTML | Rendered HTML | More info |
---|---|---|
<label for="wbur">WBUR</label> <input type="radio" name="station" id="wbur"> <label for="wzly">WZLY</label> <input type="radio" name="station" id="wxly"> |
info |
Try choosing one button and then the other.
Testing Accessibility¶
Accessibility is a big complex subject, and professional websites have trained developers, automated tools, and human testers to ensure accessibility. All that is outside the scope of this course, but I will introduce three important tools and require you to use them.
All HTML must be valid, which means it satisfies the structural rules set out by the WWW consortium (W3C). Valid HTML is important because screen readers and such can do a better job understanding the structure of the page if it follows the rules. Most browsers are much more forgiving, so don't assume that if it looks good in a browser that it's good.
You can validate your HTML using this website from the W3C: https://validator.nu/. We've done this before in this course.
All CSS (see below) must be valid, for similar reasons as the HTML.
The W3C also provides a CSS validator that works the same way as the HTML validator: https://jigsaw.w3.org/css-validator. Again, we've used this before.
Check the page for common accessibility issues with the WAVE, the Web Accessibility Evaluation tool, https://wave.webaim.org/. It's important to note that getting no errors from the WAVE tool doesn't mean your site is accessible — only a person can decide that — but it's a useful tool nevertheless. Not passing the WAVE test is certainly undesirable.
Like the earlier validators, WAVE can retrieve a publicly hosted page given its URL and evaluate it. It doesn't have a mode where you can copy/paste your code, but there are two browser plugins that will evaluate the page in your browser. In less than 1 minute, I installed the Chrome plug-in, a page, and evaluated it.
Coffeerun From from Chapter 9¶
Here's the finished code from chapter 9
We'll explore it some, just to look at the form they created. Note:
- The controls that they created
- The names of those controls
- The values of the controls
- We'll try submitting the form and observer the name/value pairs in the URL
- The
coffee
input is an ordinarytext
input - The
emailAddress
input is anemail
input (fallback to text if the browser doesn't supportemail
) - The
size
input is a set of radio buttons - The
flavor
input is a dropdown menu - The
strength
input is arange
input type, which gives us a fancy slider widget - We'll look at the
submit
button as well. - We'll adjust the slider and see the numbers in the URL.
- We'll look at some of the CSS formatting that we get from Bootstrap.
Topics we didn't cover¶
- fieldset and legend
- checkboxes
- size of inputs
- validation
- others?? Title: Forms and JavaScript
Forms and JavaScript
This reading supplements Chapter 10, which introduces JS code to process data that is entered into forms. We'll look at the following topics:
bind
(this is from Chapter 8, but re-occurs in Chapter 10)- submit handlers
- preventing defaults
- jQuery and its pitfall
- serializing forms
- resetting forms
Binding this
¶
We saw bind
back in Chapter 8, but it rears its ugly head again in
Chapter 10.
If you'd like to explore bind
with more examples, check out the MDN
explanation of
bind
If you're not feeling okay about it, please talk to me or to our tutor.
Form Submission¶
Now let's talk about forms. HTML forms were invented so that a page could
collect information from the user and allow it to be packaged up and
submitted to a server for some kind of processing. Think about forms on
Amazon.com or Ebay.com or any other kind of web application. Think about
the customer feedback
questionnaires we are constantly being asked
to fill out. Even Facebook posts. All of those are forms being submitted
to servers.
We can write JavaScript code that gets triggered when a form is submitted. In this chapter, the authors write some sophisticated, abstract code for setting up some general-purpose code for handling form-submission. In this part of the reading, we'll look at more concrete examples, so that the abstract code will make a bit more sense.
Let's start with the following form
Go ahead and fill it out and submit it if you like.
Submit Handlers¶
The first thing we want to do is add a JS function that will be invoked when the form is submitted. Form submission is a kind of event, so this is a kind of event handler.
What should our function do? For now, let's just alert the user that they submitted the form. A little bit of jQuery will suffice.
:::JavaScript
$("#form2").submit(function () { alert("form submitted!"); });
The jQuery submit
method is just a shortcut for using on
and the name
of the event, which is what your book does:
:::JavaScript
$("#form2").on('submit', function () { alert("form submitted!"); });
Note that the URL changes when you submit this form, with your form data (key/value pairs) appearing in the URL.
Preventing Defaults¶
Usually, we want to send the data to a server when a form's submit button
is clicked (or the user presses enter
in a text field), but in this case
we don't. We want to prevent the default behavior, so we'll change our
event handler to get the event object and use the preventDefault()
method:
:::JavaScript
$("#form3").on('submit', function (evt) {
evt.preventDefault();
alert("form submitted!");
});
Note that the URL doesn't change with this event handler. Of course, that's because we've prevented the default behavior.
jQuery and its pitfall¶
What's wrong with the following combination of HTML and CSS and JavaScript?
:::HTML
<form id="form3"> ...</form>
:::CSS
#from3 { border: 1px solid green; }
:::JavaScript
$("#from3").on('submit', function () { alert("submitted"); });
Right; spelling. In CSS, you won't get an error message; it's just a rule that doesn't happen to apply to anything. Similarly, in jQuery, it'll look up everything that matches that selector, and add the given function as a submit handler. Alas, nothing matches that selector, but jQuery doesn't give you an error message. It treats it as an empty set: valid but useless.
Sometimes, jQuery's behavior is exactly what you want, but often, you'd like to know if you've done something wrong. So check the number of matched items:
:::JavaScript
var $form = $("#from3");
if ($form.length === 0) {
throw new Error("couldn't find form...");
}
$form.on('submit', function () { alert("submitted"); });
(In the code above, we've used a dollar sign in the name of the variable. That's a common but not universal convention for variables that contain jQuery results, since it helps you remember that you can use jQuery methods on the value of that varible. But it's also a little ugly. Your book chooses to use this convention; don't let it bother you.)
In fact, you might even create a higher-level function that will search, check and then add the event handler. Like this:
:::JavaScript
function addFormSubmissionHandler(selector, fn) {
var $form = $(selector);
if ($form.length === 0) {
throw new Error("couldn't find form...");
}
$form.on('submit', fn );
}
That's what they've done in this chapter. Actually, they also know that whatever submit handlers they write, they always want to prevent the default behavior of submitting the form, so they do this:
:::JavaScript
function addFormSubmissionHandler(selector, fn) {
var $form = $(selector);
if ($form.length === 0) {
throw new Error("couldn't find form...");
}
$form.on('submit', function(evt) {
evt.preventDefault();
fn();
});
}
One important thing to notice about the code above is how a function
(fn
) is passed in. That function does the rest of the work of the form
submission handler. So, you can think of the addFormSubmissionHandler
function as:
- find the form using a selector
- if the selector didn't work, complain
- set up a submission handler for that form
- the submission handler will do some routine stuff and then,
- invoke a function arg to do the specific stuff for this form
Serializing Forms¶
In general, forms have several inputs and all of them get packaged up and submitted to the server. To do that, the form inputs have to each be converted into strings and those strings have to be concatenated together. That process is called serializing. The key with serializing is that it has to be reversible: all of it has to be done in a way that the server can reverse the process and get back the original set of name/value pairs.
jQuery has a method that will serialize a form for you. It's called,
unsurprisingly, .serialize()
. You can also get the inputs as an array
of objects; that's called .serializeArray()
. Each object in the array
consists of a single name/value pair from the form. That is, a form asking
about pizza preferences:
:::HTML
<form id="pizza">
<input name="kind"> <!-- e.g. pepperoni or veggie -->
<select name="size">
<option>large (16 inch)</option>
<option>medium (14 inch)</option>
<option>personal (12 inch)</option>
</select>
</form>
Might serialize like this:
:::JavaScript
$("#pizza").serializeArray();
[{name: 'kind', value: 'veggie'},
{name: 'size', value: 'personal (12 inch)'}]
Check out jQuery .serializeArray to learn more.
In this chapter, they arrange for all form submission handlers to serialize the form into an array, and then collect all the form inputs into a single object. Like this:
:::JavaScript
var data = {};
$(this).serializeArray().forEach(function (item) {
data[item.name] = item.value;
});
The earlier pizza form would serialize into an object like this:
:::JavaScript
{kind: 'veggie',
size: 'personal (12 inch)'}
The form submission handler then invokes the callback function with the form data object as its input. So the overall plan is now:
- find the form using a selector
- if the selector didn't work, complain
- set up a submission handler for that form
- the submission handler will do some routine stuff namely
- prevent the default, and
- serialize the form into a single object
- invoke a function arg with the form data object to do the specific stuff for this form
Here's the code:
:::JavaScript
FormHandler.prototype.addSubmitHandler = function (fn) {
console.log('Setting submit handler for form');
this.$formElement.on('submit', function (event) {
event.preventDefault();
var data = {};
$(this).serializeArray().forEach(function (item) {
data[item.name] = item.value;
console.log(item.name + ' is ' + item.value);
});
console.log(data);
fn(data); // invoke the callback with the form data
});
};
Re-read the code above keeping the abstract plan in mind.
Bind¶
They've set up this very abstract code to attach a submission handler to a form with the routine stuff factored from the specific stuff. The code for the specific stuff will be passed in as a callback function. Now they'll use this to attach a submission handler to a form.
Unfortunately, the callback function that they want to use is, in fact, a
method. It's the createOrder
method of a Truck
object. So, they'd
like to do the following:
:::JavaScript
var myTruck = new Truck('ncc-1701', new dataStore());
var formHandler = new FormHandler(FORM_SELECTOR);
formHandler.addSubmitHandler( myTruck.createOrder ); // doesn't work
The last line doesn't work. It doesn't work because createOrder
is a
method, and it needs a value for this
. We could do the following:
:::JavaScript
var myTruck = new Truck('ncc-1701', new dataStore());
var formHandler = new FormHandler(FORM_SELECTOR);
formHandler.addSubmitHandler( function (form_data) {
myTruck.createOrder(form_data);
});
but it works just as well do to the following:
:::JavaScript
...
var myTruck = new Truck('ncc-1701', new dataStore());
var formHandler = new FormHandler(FORM_SELECTOR);
formHandler.addSubmitHandler( myTruck.createOrder.bind(myTruck) );
The latter is what our book uses. Use whichever technique you understand
better. Using bind
is also a little more concise, though that's not an
important reason.
Grid Systems, Skeleton and Bootstrap
When we have a display device larger than a phone, we often want to switch to a different layout, with different columns and such. For example, we might have a nav bar on the left and a twitter feed to the right in addition to a wide column of main content in the center. We might even have multiple columns of content. To make things neat and orderly, we often have a layout based on a grid. (Typically, you'll see the grid based on 960px, not because that amount matches any device size, but because 960 is divisible in lots of ways.)
For an idea of the theory, please read the Mozilla Developer Network article on grids Fair warning, though, it is long. Stop when you get to Line-based Placement. Our goal is to learn the basic concept and some of the techniques, but not every detail.
In this class, I'm using Skeleton which I like a lot because it's simple and well-documented. However, I acknowledge that many people like Bootstrap, and you're welcome to use that, too. The MDN article used to mention both Skeleton and Bootstrap; but it's been revised.
Form Validation
Chapter 12 on form validation is pretty clear, except that it doesn't explain much about regular expressions.
Regular expressions are a powerful and efficient way to match a pattern against a string. Most civilized programming languages have them available, either built-in or as an easily loaded module.
You should think of regular expressions as a whole new language with its own syntax and grammar. It's not a programming language, but it definitely changes the meaning of different characters. Unfortunately, there are often variations in the regular expression languages from Java to Python to JavaScript and so forth.
The MDN article on regular expressions in JavaScript is good and comprehensive, probably more comprehensive than we need. Read the book chapter first, so you understand the role that regular expressions will play, then read part of the MDN article to learn a bit more. Specifically, read from the beginning, up until it explains the meaning of the decimal point. That will explain all the stuff going on the the chapter.
What is 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.
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:
<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:
Try to submit an incomplete form!
Ajax
Before Ajax, the way that a browser communicated with a server (the "back-end") was typically to submit a form (or get a URL), whereupon the web page was replaced with the response. That replacement can sometimes interrupt a user's experience. Imagine if everytime you clicked "like" on a Facebook page, the entire page was replaced with a new one, even if it looked 99% like the old one.
Ajax is a powerful modern technique whereby a browser page can communicate with a server without having to be replaced by the response. Instead, it's in a kind of "side" conversation going on in parallel (asynchronously) with the browser paying attention to you.
Asynchronous Requests¶
When we invoke a function, we wait around for the response, like this, and then we can use the result as the argument to other functions:
:::JavaScript
var val = foo(x);
bar(val);
more_work();
That's fine in the context of normal programming, but it doesn't work for
lengthy operations. Suppose foo
took tens of milliseconds to return.
Not only does bar
have to wait (it would anyhow), but so does
more_work
, even if it doesn't depend on foo
. More importantly, if the
browser has something else to do (such as pay attention to the user), it
can't be sitting around waiting for foo
to complete.
Instead, we want to use an asynchronous style of programming, where
instead of foo
returning a value, we pass foo
a function that it
should invoke on the result. Meanwhile, neither more_work
nor the
browser will have to wait for foo
to complete. Here's the programming
style:
:::JavaScript
foo(x, bar);
more_work();
The more_work
function and whatever else the browser is doing can
execute immediately. Some tens of milliseconds later, once foo
is
done, foo
will arrange to invoke bar
.
That's how Ajax works, because the Ajax call starts a network connection to the server and waits for the response:
:::JavaScript
$.post('url', data, func);
The first argument is the URL of the server to send the data to. The second argument is the data, usually as a JavaScript object literal. Finally, the last argument is a callback function that will get invoked with the response from the server. Here's a bit more detail:
function gotit (response) {
console.log('Got '+response);
}
$.post('url', data, gotit);
In the coffeerun app, they send the data to an application they have running on Heroku.
The .get()
method works the same way. In fact, both are wrappers for a
general .ajax()
method that needs to know what HTTP request you want to
make:
:::JavaScript
$.ajax('url', {type: 'get', data: data, success: func});
$.ajax('url', {type: 'post', data: data, success: func});
$.ajax('url', {type: 'delete', data: data, success: func});
LocalStorage¶
Instead of saving things to a remote server, you can save them in the
browser, using localStorage
. Note that localStorage is persistent,
which means that it will last even if you quit the browser and restart
it, even days later. That's not the case with regular JavaScript
variables, which live just in that one browser tab and will disappear
if the browser tab is closed or re-loaded, let alone restarting the
browser.
Setting a value
To store something in the local storage of your browser, any of the following will work:
:::JavaScript
localStorage.fred = 'Fred Weasley';
localStorage['george'] = 'George Weasley';
localStorage.setItem('harry', 'Harry Potter');
To get the values back out, just use the expressions on the left hand
side, or the getItem
method:
:::JavaScript
console.log(localStorage.fred);
console.log(localStorage['george']);
console.log(localStorage.getItem('harry'));
There are also methods .removeItem
which removes a single key, and
clear
which removes all keys.
Title: Inheritance in JavaScript
Inheritance in JavaScript
Object-oriented programming (OOP) has many advantages:
- data abstraction: objects hide implementation and provide behavior
- polymorphism: objects can provide similar behavior for different types
In addition, OOP often provides for inheritance. That is, the behavior of a class can be extended or modified in subclasses.
We'll see how all these play out in JavaScript.
A good companion reading to this is the MDN article on Inheritance in JavaScript. The article has some good but different examples.
Data Abstraction¶
Suppose we are using JavaScript for a 2D computer graphics system. In our system, we're going to have rectangles.
How shall we represent them? We could do any of the following:
- upper left and lower right corners
- upper left corner, width and height
- any two corners
- center and width and height
- ...
What if we decide on a representation and change our minds later? Will that affect the users of our system?
What kind of behavior (methods) do we want to support? We might list
quite a lot of methods, including drawing it on the screen (which we will
not discuss unless you twist my arm). For now, we're only going to
provide the area
method.
Regardless of how we represent the rectangle internally, how shall we allow the user to construct a rectangle?
For the purposes of this example, suppose we allow the user to give any two corners in the constructor.
Furthermore (switching to the other side of the abstraction barrier), let's suppose that we decide to implement the representation as the upper left and lower right corners.
Here's a JavaScript implementation of rectangles. Please read the code; it's only about 20 lines.
Abstraction Barrier¶
The client of these rectangle objects only knows that they can report their area. They don't know or care what the internal representation is. This is called an abstraction barrier.
The implementor of these rectangle objects provides a constructor and that behavior (method).
Note that, the implementor might decide that, if clients ask for the area a lot, maybe it would make sense to pre-compute it, or switch to a representation that doesn't require so much computation. The behavior remains the same, but it's now faster and more efficient. We have the freedom to change our representation.
Polymorphism¶
Suppose that we also want to have circles. They should also support an
area
method. What will the internal representation be?
- Center and radius?
- Top and bottom points?
- Left and right points?
Here's an implementation of rectangles and circles. Please read the code. The new circle code is only two dozen lines.
Note at the end of that code that we have a list of objects, some of the
rectangles and some of the circles. We can compute the area of all of
them by using the area
method that they both support.
This is called polymorphism: a single interface to entities of different types.
One thing that's great about polymorphism is that we don't have to have a "master" function that knows how to compute the area of all kinds of shapes (and which then needs to be updated if we add a new kind of shape). Instead, the knowledge of how to compute the area of a shape is distributed among the shapes. Each knows how to compute its own area.
Inheritance¶
What if we have some behavior that is common to both rectangles and circles? Since we are supposing that this a 2D graphics system, maybe each has to keep track of its color (fill mode, stroke width and many other such properties).
We will define a new class called Shape
. It will take a color as its
argument. We'll also define methods to get and set the color and one to
help print a shape, overriding the toString()
method that every object
inherits from Object
, the ancestor of all JavaScript objects.
:::JavaScript
function Shape(color) {
this.color = color;
}
Shape.prototype.getColor = function () { return this.color; };
Shape.prototype.setColor = function (color) { this.color = color; };
Shape.prototype.toString = function() {
return "[A "+this.color+" "+this.constructor.name+"]";
};
var s1 = new Shape("red");
console.log("s1 is "+s1.toString());
The constructor
property
As you surely noticed, an object can know what function constructed
it. For s1
it's the Shape
function. Functions have properties like
name
, which we used here in our toString()
method.
Using the constructor name is not common, but it clarifies some of the issues we will discuss next.
Defining Subclasses
We'll redefine our classes for rectangles and circles to use
inheritance. In honor of this change, we'll call them Rectangle
and
Circle
.
Both of our Rectangle and Circle classes will inherit from
Shape
. (Shape
will be described as the parent class or sometimes the
superclass. Rectangle
and Circle
will be described as the child
class or the subclass.)
Setting up inheritance requires several steps:
- To properly initialize a new object, we must invoke the parent's
constructor from the child's constructor. True, we could assign the
color
instance variable ourselves, but what if the parent changes the initialization code, say to check the color? Then we'd have to copy those changes to every child: very bad. - We have to specify that the child's prototype is an instance of
Shape
. Since each object inherits instance variables and methods from its prototype chain, we have to make sure that chain is correct. - Setting the child's prototype has the unwanted side-effect of changing
the
constructor
property, which we use in the name, so we set it back to the correct value.
Here's a high-level view of creating a subclass:
:::JavaScript
function Rectangle(color,c1,c2) {
// initialize using superclass
Shape.call(this,color);
...
}
Rectangle.prototype = Object.create(Shape.prototype);
Rectangle.prototype.constructor = Rectangle;
Here we see a good use of the call
method that functions have. We invoke
the Shape
function but we supply a value to use for this
(it happens
to be the same as the current this
) and any additional arguments it
needs.
The following file has a complete implementation of these ideas, with
rectangles and circles. It also adds Triangles, but it "forgets" to set
the prototype and prototype constructor. The result is that triangles
don't inherit from Shape
, which you can see in the console.log output.
Here's the file: shapes.html
Please read the code; it's not terribly long, and much of it is familiar to you from the earlier examples, so you can focus on the differences.
Notice that one of the cool things about inheritance is code reuse: all
the children (grandchildren and further descendants) of Shape
get its
methods.
The instanceof
Operator¶
There is a special JavaScript operator that will go through the prototype chain for an object to determine whether it inherits from a particular "class". Remember that JavaScript doesn't really have classes; we simulate that with constructor functions, so the constructor functions stand in for classes:
:::JavaScript
// All true
console.log("r1 instanceof Rectangle: "+(r1 instanceof Rectangle));
console.log("r1 instanceof Shape: "+(r1 instanceof Shape));
console.log("r1 instanceof Object: "+(r1 instanceof Object));
// False
console.log("r1 instanceof Circle: "+(r1 instanceof Circle));
New Syntax¶
In JavaScript/ECMAScript 2015, a new syntax was introduced for defining
classes. At the same time, they introduced a new syntax for inheritance,
namely the extends
keyword to the new class
syntax. For a quick
introduction, see the following:
- read the first example in this section on subclassing with extends
- the extends keyword
- Class inheritance
One important thing to note is that you must invoke the constructor for
the parent class using super()
; that invocation is not automatic. You
can also use super
in method definitions, which is very cool.
Example
The following file re-implements the shapes from above, using the new syntax.
Here's the file: shapes-new.html
With the new syntax, it's impossible to get the prototype chain wrong, so it's a clear winner.
Summary¶
Many object-oriented languages, such as Java and Python, have classes and objected, with classes being the templates and factories for objects. JavaScript doesn't have this "classical" (as Douglas Crockford, author of JavaScript: The Good Parts, describes it) inheritance system, but instead uses prototype chains. Nevertheless, we can implement this classical OOP inheritance in JavaScript, and many JavaScript libraries do so. For example, Threejs, a library for doing 3D computer graphics in JavaScript.
Galleries and Drop-downs
Our topic for the next class is learning how to do two very common tasks on websites: image galleries (slideshows) and drop-down menus.
There are many solutions for these problems, including fancy transitions between slides and much more. We're going to keep it fairly basic, though.
Rather than write up how to do this, I'm going to defer to two descriptions that are on W3Schools. Let me know whether you find the links below reasonably clear. We will talk about them in class and implement some examples.
Slideshows¶
A slideshow displays one of a set of images, rotating through them. It has arrows to advance the slideshow or move it backwards, little buttons to indicate where we are in the set and lots of other eye candy.
Automatic Slideshows¶
To have a slideshow automatically advance, it's sufficient to have a
function that will manually advance the slideshow, and then have the
browser invoke that function every few seconds. That's easily done with
the built-in JavaScript setInterval
function.
Learn more about setInterval
from MDN: setInterval
Clickable Dropdowns¶
We want to be mobile-friendly and old-fashioned drop-down menus typically drop-down when the mouse is hovered over them. But we can't "hover" on a touch-screen device. Instead, we will click to open/close a drop-down menu. Here's one way:
jQuery UI
jQuery itself is a JavaScript library for manipulating the DOM in a convenient way. We've used it many times this semester.
However, there are lots of common user interface (UI) widgets and effects that people commonly want to do that jQuery doesn't do. Fortunately, many of these UI widgets and effects are packaged up in something called jQuery UI.
In this reading, I'll ask you to look at a selection of these. There is nothing particularly special about the ones I've chosen except that I have used most of them in the past and found them helpful and relatively easy to use.
jQuery UI Overall¶
First, take a few minutes to look over the home page and look at the options:
Then, take the time to read the about page: about jQueryUI
Next, I'll ask you to look at several specific items. Each item has a main page with a demo. In fact, it usually has several demos; make sure you study at least the default demo. The demo will have a way to look at the source code of the demo. Please look at the source code.
You'll notice that the source code usually loads quite a few files and other code, such as
- jquery-ui.css
- some additional custom CSS
- some example-specific CSS in a
style
tag - jquery itself
- jquery UI
- some example-specific JavaScript, that puts these libraries into action.
So, when you're reading the code, don't neglect to notice all these parts.
You'll see that these jQuery UI features have "API documentation" that shows how they can be customized in a bewildering number of ways. We typically won't be using these customizations; we'll try to stick to the most common cases. You're welcome to look at the API documentation, but I am not asking you to do that on this first reading. Let's get the high-level view down first. Still, it's good to know that if a jQuery UI feature is close to what you want but not quite right, it's probably customizable in the way that you want.
In class, we'll get some more experience with using these.
- autocomplete Developers should always use this for "state name" when asking for an address.
- datepicker So easy and useful. We'll use this in the final project as well
- tabs A nice way to organize a page without having lots of scrolling or switching to other pages. jQuery Mobile is based on this idea.
- sortable We might use this in the final project
Four features should be enough to get us started, but if there is something else that you see that you think is cool, let me know and we'll see if we can learn about it.
Title: Google Maps
Google Maps
Google Maps is a useful feature to add to many websites and it's (almost) free! Both Google and the W3Schools have nice tutorials and a number of fun examples. We won't read all of them, but a few will be helpful.
API Key¶
I said Google Maps was almost free. What that means is that Google generously allows you to make queries to their map servers per month for free (it's many thousands), but after that, they will bill you (and the charge is pretty low, $7 per thousand queries, I believe).
Unfortunately, all of that means that in order to use Google Maps, they need to be able to bill you, even if you're just playing around and won't be doing industrial-scale numbers of queries.
This "we need to be able to bill you if we need to" policy, while understandable, is a serious impediment for us. If you have a personal Google account, you can give them a credit card for billing purposes then create an API key and use that.
Unfortunately, the Google accounts that we have thanks to Wellesley College don't allow us to add a credit card. So, I've given my credit card to Google for my personal Google account, and created an API key for that. I can share that with you for educational purposes; just don't cost me any money. :-)
So, when you read these tutorials and they refer to the API key, understand that that is a unique identifier that tells the Maps server who is making the query, so that they can count how many queries you make and, if it gets beyond the free level, can bill you.
Google's Tutorial¶
First, read this one (longish) web page that is Google's tutorial on adding a Google Map with a Marker
Tutorial¶
Then, please read through the first two pages of the W3Schools tutorials (linked below). You can just start at the first one and click the big green "next" button on each page.
- Maps Intro
This is the set up to show a nice, static map, at a place of your choosing
(specifying the
center
given a latitude and longitude. Note that latitude measures north/south location and ranges from -90 (south pole) to +90 (north pole). Longitude measures east/west location and ranges from -180 (middle of the Pacific) to +180 (same as -180) with 0 degrees longitude being Greenwich, England. - Maps Basic
This is more information on the basic map, explaining about the map container (a
div
) and the initialization function. It also shows a demo of four different map types (ROADMAP, SATELLITE, HYBRID, and TERRAIN)
Title: Accessibility
Accessibility
A website is accessible if it can be used effectively by people who have disabilities, such as blindness, deafness, or paraplegia. We've mentioned accessibility many times in this course, and we've made it an important part of the way we build web sites. This reading will cover a lot of what we haven't yet covered, though we won't be able to cover everything we would like to.
Motivation¶
Overall, the web has been good for accessibility. Because the text is already in computer form, it can be easily processed by a screen reader for the blind (as opposed to print, which would first require optical character recognition). Nevertheless, many modern websites can be frustratingly difficult for people with disabilities.
We can assume that the designers who made the inaccessible websites didn't set out to do so. Most of us see the need and responsibility for building designers to allow for wheelchair ramps and curb cutouts to allow access to public buildings, along with braille signs in elevators and many other accommodations. Furthermore, the Americans with Disabilities Act or ADA requires that many websites be accessible in the same way that public buildings must be accessible. See the website Web Accessibility in Mind for much more information. Much of what is covered in this reading is drawn from that resource. Their materials are copyright © 1999-2016 WebAIM (Web Accessibility in Mind).
The POUR Principles¶
Having decided to build an accessible website, we have to figure out what that means. First, consider different kinds of disabilities:
- Visual: people can be blind, have low-vision, be color-blind, and more
- Auditory: people can be deaf or hard of hearing
- Motor: people can be unable to use a mouse, be slow or lack fine motor control
- Cognitive: people can have learning disabilities or poor ability to focus
To make a website accessible, we want to keep four guidelines in mind:
- Perceiveable
- The information should be accessible by the visitor's working senses, so, for example, information should not be presented solely by sound (a video with narration but no captioning).
- Operable
- The website shouldn't require the use of a mouse in order to access the information
- Understandable
- The content is clear, at least to the target audience.
- Robust
- The website should be accessible to a wide range of assistive technologies
These make the acronym POUR.
Checklist Dozen¶
These are wonderful principles, but our task in this reading is to see how to achieve them. Let's start with a list of the dozen most important principles. I've copied this list from the WebAIM website, and I've included links to their elaboration on each principle. You're encouraged to go to their site to learn more.
- Provide appropriate alternative text
- Alternative text provides a textual alternative to non-text content in web pages. It is especially helpful for people who are blind and rely on a screen reader to have the content of the website read to them.
- Provide appropriate document structure
- Headings, lists, and other structural elements provide meaning and structure to web pages. They can also facilitate keyboard navigation within the page.
- Provide headers for data tables
- Tables are used online for layout and to organize data. Tables that are used to organize tabular data should have appropriate table headers (the
<th
> element). Data cells should be associated with their appropriate headers, making it easier for screen reader users to navigate and understand the data table. - Ensure users can complete and submit all forms
- Ensure that every form element (text field, checkbox, dropdown list, etc.) has a label and make sure that label is associated to the correct form element using the
<label>
element. Also make sure the user can submit the form and recover from any errors, such as the failure to fill in all required fields. - Ensure links make sense out of context
- Every link should make sense if the link text is read by itself. Screen reader users may choose to read only the links on a web page. Certain phrases like "click here" and "more" must be avoided.
- Caption and/or provide transcripts for media
- Videos and live audio must have captions and a transcript. With archived audio, a transcription may be sufficient.
- Ensure accessibility of non-HTML content, including PDF files, Microsoft Word documents, PowerPoint presentations and Adobe Flash content.
- In addition to all of the other principles listed here, PDF documents and other non-HTML content must be as accessible as possible. If you cannot make it accessible, consider using HTML instead or, at the very least, provide an accessible alternative. PDF documents should also include a series of tags to make it more accessible. A tagged PDF file looks the same, but it is almost always more accessible to a person using a screen reader.
- Allow users to skip repetitive elements on the page
- You should provide a method that allows users to skip navigation or other elements that repeat on every page. This is usually accomplished by providing a "Skip to Main Content," or "Skip Navigation" link at the top of the page which jumps to the main content of the page.
- Do not rely on color alone to convey meaning
- The use of color can enhance comprehension, but do not use color alone to convey information. That information may not be available to a person who is colorblind and will be unavailable to screen reader users.
- Make sure content is clearly written and easy to read
- There are many ways to make your content easier to understand. Write clearly, use clear fonts, and use headings and lists appropriately.
- Make JavaScript accessible
- Ensure that JavaScript event handlers are device independent (e.g., they do not require the use of a mouse) and make sure that your page does not rely on JavaScript to function.
- Design to standards
- HTML compliant and accessible pages are more robust and provide better search engine optimization. Cascading Style Sheets (CSS) allow you to separate content from presentation. This provides more flexibility and accessibility of your content.
This list does not present all accessibility issues, but by addressing these basic principles, you will ensure greater accessibility of your web content to everyone. You can learn more about accessibility by browsing our articles and resources.
Images¶
There are generally two kinds of pictures on a website: informative and decorative. If a picture is informative, you must provide some way for a blind user to get equivalent information in a textual form. The usual way to do this is to provide an ALT attribute on the image:
<img src="../images/harry-potter-thumb.jpeg" alt="Daniel Radcliffe as Harry Potter">
Note that this ALT is often incorrectly called an "alt tag" but of course it's an attribute not a tag. The general concept of providing a textual alternative is called "alt text," so that's probably the easiest and best way to describe this. Also, the alt text doesn't say "picture of ..." because that will be clear from the screen reader.
However, sighted people won't (typically) read this alt text. Maybe the text preceding this image says that Daniel Radcliffe plays Harry Potter, but a better way to do this would be to use a FIGURE and a CAPTION:
<figure> <img src="../images/harry-potter-thumb.jpeg" alt=""> <figcaption>Daniel Radcliffe as Harry Potter</figcaption> </figure>
In this case, the screen reader software can use the caption as the ALT text, so we explicitly leave the ALT attribute empty, so that the blind visitor isn't having the same text read twice.
This figure with a caption is now better for both blind and sighted visitors, an example of where accessibility can improve the experience for everyone.
What about other uses of images, say with slideshows and galleries? In most cases, a similar approach will work: if the sighted visitor is expected to get some information from the picture, you should provide that same information in textual form. A gallery of pictures showing the executive board of your club, should have each person described with a caption. If the pictures are somewhat generic, it's reasonable to give a common caption ("picture from our annual soccer game") that will apply to all the pictures in the slideshow.
If a picture is purely decorative (a picture of a soccer ball on the page describing the annual soccer game), the ALT text can be explicitly set to the empty string. Alternatively, you can make the image be a background image using CSS:
#soccerball { width: 240px; height: 240px; background-image: url(/images/240px-Soccer_ball.svg.png); } <div id="soccerball"></div>
The advantage of a background image is that, using media queries, you can easily omit these decorative images when the screen size is small.
Videos and Audios¶
Video and audio elements pose the same issues as still images. Blind visitors won't be able to see your video, so it should have a textual transcript. Deaf visitors won't be able to hear the narration or speakers, so the video should have captioning. This is not always easy or inexpensive. However, there is a benefit that search engines will be able to do a better job with indexing this content if the textual equivalent exists.
Hyperlinks¶
We already know that hyperlinks shouldn't have "here" or "more" as the click text. Screen readers often read links out of context, so the link text should stand on its own. However, there's a lot more to know about hyperlinks. Here are just a few items:
- People expect that links are underlined. Unless the context makes the link obvious (a navigation bar), don't use CSS to remove the default underline
- An image that is a hyperlink will use the ALT text as the description of the hyperlink.
- Don't say "link to X" or "go to Y"; the screen reader will indicate that the element is a hyperlink
If you want to learn even more, I suggest Making Accessible Links: 15 Golden Rules for Developers.
Labels for Form Controls¶
Each form control (input element, such as a text input or a menu) needs to have a label. It can be tempting to omit the labels when you have placeholders and such, but labels are necessary.
Avoid Color¶
Not everyone sees colors correctly. Color blindness is more common in men than in women, but it does happen in both sexes. Don't use color as the sole means of conveying information. It's fine, for example, to mark the required form inputs with red, but you should also add a bit of text or an asterisk or something. It can be a red asterisk.
Accessible JavaScript¶
- don't use mouseover, mouseout and hover, since those are mouse-only
- use :focus for links that are in focus
Accessible jQuery¶
Many jQuery methods, such as .hide()
and .slideUp()
use the CSS
setting display:none
to achieve the hiding. That method means the
resulting content is inaccessible to a screen reader. If you don't
want that, a better idea is to add an after-event handler to the
jQuery code to display the content but offscreen (or using one of the
other techniques for hiding content).
Learning More¶
- Accessibility Useability For All
- Understand the Social Needs for Accessibility
- Create Accessible Websites with the Principles of Universal Design
Conclusion¶
Assistive software and hardware are always evolving, as are the CSS techniques that attempt to help them while not hindering other visitors. The main thing is to consider accessibility when you are considering coding some fancy new interface: will it work if the user only has a keyboard? will it work if the user is blind? Will it work if the user has limited motor control? Sometimes, this will mean foregoing that fancy feature, but the goal of making our website for all instead of the lucky few is worth the price.