Edx html5 1 - Code
Edx html5 1 - Code
The HTML5 course team is thrilled to guide you in your learning experience. We
are committed to teach you how to code Web pages, and how to do it the
correct way. With this W3Cx HTML5 Part 1 course, you will be able to test their
new skills through numerous interactive examples and multiple exercises. You
will be encouraged to create Web pages and apps and share them in the
discussion forums.
Learn the new simplified HTML5 tags, and how to use microdata
Play with the audio and video tags
Draw and animate fun Web graphics
Discover the newest HTML5 forms
Understand why accessibility is important
Test the basic APIs, such as Web storage and geolocation
Practice coding techniques thanks to multiple interactive examples
Outline of the HTML5 Part 1 course
About W3C and the Web (OPTIONAL)
About W3C
Why accessibility is important
Why internationalization is important
W3C tools
HTML 1.0
Below is a screenshot of Tim Berners-Lee's Browser Editor as developed in
1991-1992.
This was a true browser editor for the first version of HTML and ran on a NeXT
workstation. Implemented in Objective-C, this very first browser in Web
history made it easy to create, view and edit web documents. Hypertext
Markup Language (First Version of HTML) was formally published in June 1993.
HTML versions
HTML is an evolving language. For Web sites and pages created since 1991,
however, it is easy to find out which HTML version they use. A Document Type
Declaration, or DOCTYPE, is a piece of HTML code that states which version of
HTML is being used. This declaration must appear at the very top of every Web
page.
For example: <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"> tells
that the document uses the HTML4.01 version.
HTML Versions
1991
HTML
1993
HTML+
1995
HTML2.
0
1997
HTML3.
2
1999
HTML4.
01
2000
XHTML
1.0
October
HTML5 2014
For those of you who are curious, the W3C published a document laying down
the HTML5 Differences from HTML4 (the document was published in December
2014, shortly after the release of HTML5). Read also the history
section available in the HTML5.1 specification document.
What is HTML5?
On 28 October 2014, the W3C officially published HTML5 as a Web standard
(or recommendation of HTML5). HTML5 is the fifth major revision of the format
used to build Web pages and applications.
to refer to a set of technologies that together form the future Open
Web Platform. These technologies include HTML5
specification, CSS3, SVG, MathML, Geolocation, XmlHttpRequest, Context
2D, Web Fonts (WOFF) and others. The boundary of this set of technologies is
informal and changes over time.
to refer to the HTML5 specification, which is, of course, also part of the
Open Web Platform.
Although it would be great if people used one term to refer to the specification
and another term to refer to the set of specifications, in practice people use the
term both ways.
When HTML5 became a Web standard, Tim Berners-Lee, Web inventor and
W3C Director said:
"Today we think nothing of watching video and audio natively in the browser,
and nothing of running a browser on a phone. We expect to be able to share
photos, shop, read the news, and look up information anywhere, on any device.
Though they remain invisible to most users, HTML5 and the Open Web Platform
are driving these growing user expectations."
The HTML5 logo
Here is the HTML5 logo! It has been unveiled on 18 January 2011, so way
before HTML5 became a Web standard. This logo represents HTML5, the
cornerstone for modern Web applications.
Please check out both the HTML5 logo home page and the FAQ page for more
information on how to use the logo, etc. You will notably find out that this logo
does not imply validity or conformance, and that you are welcome to be
creative and make it fit into your own designs.
Greater simplicity
Changes have been made to particular elements in
HTML5 making it simpler to use. In this section, we will
look at some examples highlighting these
improvements, including:
the new doctype definition;
the fact that the "type" attribute of elements such
as <link> or <script> are now optional;
the syntax constraints that have been relaxed;
the new structural elements that have been added, etc.
DTDs are not used by current Web browsers to validate the structure of an
HTML page, as they "read" the code without using the DTD to decipher it,
using only "rules" contained in their own "HTML engine", but it is still preferable
to indicate the doctype as modern browsers have several rendering engines
that are chosen depending on the doctype.
Old HTML1 Web pages will not be rendered the same way as new HTML5
pages, since in the 90's some of them were written by hand and may contain
errors, embedded HTML elements, etc.
With HTML4, doctype definitions looked like this: <!DOCTYPE HTML PUBLIC
"-//W3C//DTD HTML 4.01 Transitional//EN"
"[Link] which was even more
complicated as one had to choose between three different possibilities
(doctypes could be transitional, strict, or frameset). Most of the time, the
doctype definition was copied and pasted from one document to another and
was nearly impossible to memorize.
With HTML5, there is only one way to indicate the doctype, and it's so simple
there is no reason to forget it:
1. <!doctype html>
The "type" attribute is not needed in HTML5, and even old browsers will use
text/css as the default type for stylesheets today. So, either way, you can omit
the "type" attribute altogether and use:
instead of:
1. <link href="[Link]" rel="stylesheet" type="text/css"/>
We will not go into detail about the <link> element, but the fact that
the type attribute is becoming optional shows the current direction taken by
HTML5: towards greater simplicity.
1. <script src="[Link]"></script>
Here again, the type attribute has been omitted. Just as a reminder, the old
way to do the same thing:
Attribute values only need to be quoted if they contain spaces or some non-
alphanumeric characters, instead of
writing <link rel="stylesheet" href="[Link]">, we could have
used <link rel=stylesheet href=[Link]> instead. However, for
compatibility with older browsers, it might be wiser to still use quotes...
New structural elements
History
As Web site layouts evolve, HTML5 structural elements such as lists,
paragraphs, tables, etc. show their limits. Today, many Web sites offer
navigation menus, tabbed panels, headers, footers, and so on. The way these
"parts"' are implemented relies heavily on <div> and <span> elements with
different id and class attributes, lots of CSS and lots of JavaScript code to apply
custom styles and behaviors.
id and class names differ from one developer to another, from one country to
another, etc.
Even with the same ids and class names, the css rules may be different
JavaScript libraries have become increasingly heavy over the years
Web pages have become increasingly heavy over the years!
These elements can not be handled by the Web browser natively...
Even if differences exist between ids, classes and css/js implementations, they
also share common behaviors, layouts, and "ways of doing things" that could
be guessed at first glance by a human.
So various studies have been conducted in order to identify the most popular
ids, class names, widgets, etc. used on the Web:
According to [Link]
html5/, "During the creation of HTML5, Ian Hickson used Google's tools to mine
data from over a billion Web pages, surveying what ids and class names are
most commonly used on the real world Web. You can see one of the surveys
published at Google Code: Web Authoring Statistics: Classes. Opera did a
similar study of 3.5 million URLs, calling it MAMA ("Metadata Analysis and
Mining Application"). MAMA, as structural Web-paged search engine, had a
smaller URL set, but looked at a larger and wider variety of Web page statistics.
The articles published by Opera are no longer online but have been archived on
github, and still can be accessed using [Link], see MAMA common
attributes, MAMA's id list, and MAMA's class list. For more options, go to
the MAMA home page."
Finally, the 20 most popular ids and class names found in Hickson's and
Opera's surveys gave birth to these new elements (click on the element's name
to go to the W3C specification about this element):
External resources:
importance-of-sections/
[Link]
[Link]
How to mix all the new structural elements together?
are available on the [Link] Web site and can be modified freely: you can
save your own version using the "Bins/create milestone" menu, share your
version with others in the forums, etc. Don't hesitate to play with the
the HTML page using a <header> element that contains the "Simple
HTML code:
1. <!DOCTYPE html>
2. <html>
3. <head>
4. <title>Simple HTML5 blog</title>
5. </head>
6. <body>
7. <header>
8. <h1>Simple <span>HTML5</span> blog</h1>
9. </header>
10. ...
1. header {
2. color: #007e99;
3. font-size: 2.5em;
4. padding: 20px 50px
5. }
6. header span {
7. color: #722
8. }
Use a <nav> for the navigation menu just below the header
The navigation menu just below the header is a <nav> element. For the
purpose of this example we haven't provided any value for the hyperlinks...
HTML code:
1. <!DOCTYPE html>
2. <html>
3. <head>
4. <title>Simple HTML5 blog</title>
5. </head>
6. <body>
7. <header>
8. <h1>Simple <span>HTML5</span> blog</h1>
9. </header>
10.<nav>
11. <ul>
12. <li><span>Blog</span></li>
13. <li><a href="">About</a></li>
14. <li><a href="">Contact</a></li>
15. </ul>
16.</nav>
And here is the CSS we used in this example for the <nav> element:
1. nav {
2. font-size: 1.5em;
3. margin: 5px 0;
4. padding: 20px 50px
5. }
6. nav li {
7. display: inline;
8. margin: 0 15px
9. }
10. nav li:first-child {
11. margin-left: 0
12. }
13. * html nav ul {
14. margin-left: -15px
15. }
16. nav span, nav a {
17. padding: 3px 15px 4px
18. }
19. nav span {
20. background: #722;
21. color: #fff
22. }
A <section> for each month and an <article> for each post in the blog
of <article> elements...
HTML code:
1. <section>
2. <article>
3. ...
4. </article>
5. <article>
6. ...
7. </article>
8. <article>
9. ...
10. </article>
11. </section>
1. section {
2. float: left;
3. padding: 35px 0;
4. position: relative;
5. width: 70%
6. }
7. section article {
8. margin: 0 50px 40px;
9. padding: 25px 0 0;
10. position: relative
11. }
12. section header {
13. font-size: 1em;
14. padding: 0;
15. }
16. section h2 {
17. font-size: 2.3em;
18. }
Note that the H2, article, article header, etc. will be styled using these
rules.
Next, in each article in the section we have a header (to display the article
1. <section>
2. <article>
3. <header>
4. <h2><a href="">Information about this example</a></h2>
5. This example is a modified version of <a
6. href="[Link]
7. [Link]
8. </header>
9. <p>Try to move the mouse on different elements. The structure will be
10. highlighted and you will be able
11. to see the different inclusions of elements one in each other. If you
12. move the cursor to this sentence, it will be highlighted in dark
grey,
13. showing the presence of an <article> element, surrounded by a
14. <section> element (light grey), etc. So we have some articles in
15. a single section element. The page title at the top is
a <header>
16. element, while the tag cloud on the right is a <aside> element.
The
17. main menu on top (with Blog, About, Contact) is
a <nav> element.</p>
18. <figure>
19.
<img src="[Link]
20. alt="Example of HTML5 structural tags" />
21. <figcaption>
22. Fig. 1 : an example of how new structural elements could
23. be used. This page put a <nav> on top, and does not have
24. headers and footer for each article, like in this
figure,
25. but it could... By the way this is a
26. <figcaption> inside a <figure> element...
27. </figcaption>
28. </figure>
29. </article>
30. ...
31. </section>
Also note the way we included a figure using the new "HTML5" method,
Here is the CSS for the <figcaption> element we have used in the
example (we did not apply any style to the <figure> element):
HTML code:
1. <figure>
2. <img src="[Link]
3. alt="Example of HTML5 structural tags" />
4. <figcaption>
5. Fig. 1 : an example of how .....
6. </figcaption>
7. </figure>
CSS code:
1. figcaption {
2. font-style:italic;
3. font-size: 0.8em;
4. width: 100%
5. }
Use an <aside> element to display a tag cloud on the... side of the main
content
After the long <section> element that contains all the blog articles
displayed in the page, we added the HTML code for the tag cloud that is
displayed on the right of the page, "aside"! This is done using - you already
We are not going to show the complete CSS here as it uses some tricks to
display the list as a "real tag cloud" that uses JavaScript for handling
events, etc. Those who are curious can look at the code of the online
example: [Link]
We used a float:right CSS rule to put the tag cloud on the right... In a
make a nice layout with the new structural elements, using simple CSS
rules.
Finally, we added a <footer> element (lines 12-14 below) after the tag
1. <html>
2. ...
3. <body>
4. ...
5. <section>
6. ...
7. </section>
8. <aside>
9. ...
10. </aside>
11. <footer>
12. <p>© 2009 Some blog</p>
13. </footer>
14. </body>
15. </html>
1. footer {
2. clear: both;
3. color: #777;
4. padding: 10px 50px
5. }
Example of a blog post defined as a long <article>, that is in turn cut into
smaller <section> elements:
1. <article id="id1">
2. <section id="id1part1">
3. <h2>Introduction</h2>
4. </section>
5. <section id="id1part2">
6. <h2>My travel to India</h2>
7. </section>
8. <section id="id1part3">
9. <h2>Return to France</h2>
10. </section>
11. </article>
The blog example from the previous part of the course, on the other hand, uses
a single <section> that contains several <article> elements.
Indeed, we can also have a <section> that regroups all blog posts per month,
each one being an <article>element.
too!
CAN you PUT A <NAV> IN AN <ARTICLE>?
Yes you can, in case you would like to propose some navigation links with each
blog post, for example:
1. <article>
2. <header>
3. <h1>Blog post title</h1>
4. <p>Author: Michel</p>
5. </header>
6. <nav>
7. <ul>
8. <li><a href="...">Next post</a></li>
9. <li><a href="...">Previous post</a></li>
10. <li><a href="...">Contact author</a></li>
11. </ul>
12. </nav>
13. <p>Content...</p>
14. <footer>
15. <p>Posted by Michel, the <time datetime="2012-02-02">February
2,
16. 2012</time> </p>
17. </footer>
18. </article>
In that case, the <nav> element proposes navigation links to the next or
previous blog post, as well as a link to contact the author of the blog post.
Also note that we used in that example a <footer> element in the blog post.
You can use <div> elements in all cases where the proposed structural
elements do not fit your needs: for defining some content that should be
styled, for example.
This chart from the HTML5 Doctor Web site may help you decide whether or
not to use a <div>:
Headings and structural elements
We will now present some best practices for starting to use <section>,
<article>, <nav>, <aside>, in particular concerning the use of headings
(H1, H2, H3, H4, H5 and H6).
This is a H1 heading
This is a H2 heading
This is a H3 heading
This is a H4 heading
This is a H5 heading
This is a H6 heading
These headings define a hierarchy, as shown by the default sizes given by the
browser. This hierarchy can also be used to define an outline of the document.
To illustrate this, we have used a browser extension. Here is the result for the
previous example:
In the above outline, note that we have only used H1...H6 elements, without
any new HTML5 structural elements such as <section> or <article>.
Here is a list of browser extensions you can try, for visualizing the outline of a
document: Google HTML5 outliner, or the HTML5 Outliner Opera
Extension or this Firefox extension.
The HTML5 specification says that "each sectioning element potentially has a
heading and has also an outline associated".
<h1>...<h6> are called headings, and define the header of a section (whether
explicitly marked up using sectioning content elements, or implied by the
heading content itself). This means that:
1. <body>
2. <h1>Title of my document</h1>
3. ...
4. </body>
... defines the header of a section implicitly, while:
1. <body>
2. ...
3. <section>
4. <h1>Title of my section</h1>
5. ...
6. </section>
7. </body>
... defines the heading of the explicit section (its parent element <section>).
1. <body>
2. <section>
3. <h1>This H1 is the heading of an explicit section</h1>
4. ...
5. <h2>This H2 is a subheading, part of the same section
6. (lower rank)</h2>
7. ....
8. <h1>This H1 starts an implicit new section in the explicit
9. section (equal or higher rank)</h1>
10. ...
11. <h2>This is a H2 heading in the new section that has
12. just started</h2>
13. ...
14. </section>
15. </body>
The corresponding outline is:
1. <section>
2. <h1>Blog post of April 2015</h1>
3. ...
4. </section>
1. <section>
2. <header>
3. <h1>Blog post of April 2015</h1>
4. <p>Posted by Michel Buffa...</p>
5. </header>
6. ...
7. </section>
1. <section>
2. <header>
3. <p class="article title">Blog post of April 2015</p>
4. <p>Posted by Michel Buffa...</p>
5. </header>
6. ...
7. </section>
The last example is bad for accessibility reasons. A screen reader that vocalizes
the page will just say "Entering section", while in the previous two good
examples it would say "entering section with heading Blog Posts of April 2015".
You can also check if your headings and sectioning elements are ok by using a
browser extension that displays the outline of the document (just search for
"html5 outliner" in your browser's extension search engine).
1. <body>
2. <h1>Example Blog</h1>
3. <section>
4. <header>
5. <h2>Blog post of April 2015</h2>
6. <p>Posted by Michel Buffa...</p>
7. </header>
8. <p>Content of the blog post...</p>
9. </section>
10. </body>
To sum up:
You can use heading elements <h1>...<h6> in a <header> but be careful if you
use more than one, as the rules explained in the previous part of the
course will apply and may generate implicit "sections" in the header.
1. <section>
2. <header>
3. <h1>Some text in a h1 in a header of a section</h1>
4. <h2>This a h2 in the header...</h2>
5. </header>
6. </section>
Here is the resulting table of contents, notice the two subsections that appear,
one for the H1, one for the H2:
If you do not want the subtitles to be included in the table of contents, just use
standard markup, for example <p> elements, as shown in the next example. Of
course, CSS rules can be applied to change colors, sizes, etc.
1. <header>
2. <h1>HTML 5.1 Nightly</h1>
3. <p>A vocabulary and associated APIs for HTML and XHTML</p>
4. <p>Editor's Draft 9 May 2013</p>
5. </header>
Best practice 2: try not to rely on implicit sectioning,
use <section>, <article>, etc. instead of
just <h1>...<h6>
The example below defines several implicit "sections" by using <Hx> directly (at
lines 7 and 9):
1. <body>
2. <h4>Apples</h4>
3. <p>Apples are fruit.</p>
4. <section>
5. <h2>Taste</h2>
6. <p>They taste lovely.</p>
7. <h6>Sweet</h6>
8. <p>Red apples are sweeter than green ones.</p>
9. <h1>Color</h1>
10. <p>Apples come in various colors.</p>
11. </section>
12. </body>
Better version (best practice): this example can also be written like
this:
1. <body>
2. <h1>Apples</h1>
3. <p>Apples are fruit.</p>
4. <section>
5. <h2>Taste</h2>
6. <p>They taste lovely.</p>
7. <section>
8. <h3>Sweet</h3>
9. <p>Red apples are sweeter than green ones.</p>
10. </section>
11. </section>
12.<section>
13. <h2>Color</h2>
14. <p>Apples come in various colors.</p>
15. </section>
16. </body>
Both of the examples above are semantically identical and produce the same
outline:
1. <body>
2. <h1>Apples</h1>
3. <p>Apples are fruit.</p>
4. <section>
5. <h1>Taste</h1>
6. <p>They taste lovely.</p>
7. <section>
8. <h1>Sweet</h1>
9. <p>Red apples are sweeter than green ones.</p>
10. </section>
11. </section>
12. <section>
13. <h1>Color</h1>
14. <p>Apples come in various colors.</p>
15. </section>
16. </body>
This final example would need explicit CSS style rules to be rendered well in
legacy browsers. Legacy browsers without CSS support would render all the
headings as top-level headings (same default size).
As stated in the article HTML5 Document Outline and on the W3C HTML Wiki,
these days it is not recommended that you follow the third example, as many
browsers do not implement the outline algorithm that "sort of renumbers" H1s
when located inside sectioning content.
1. <body>
2. <h1>This is an example of embedded table of content</h1>
3. <section>
4. <header>
5. <h1>First section of the document (this is a h1)</h1>
6. This is a subheading...
7. </header>
8. <h2>First subsection of the first section (a h2)</h2>
9. <p>Blah Blah...</p>
10. </section>
11. <section>
12. <h1>Second section of the document (a h1)</h1>
13. <h2>First subsection (a h2)</h2>
14. </section>
15. <aside>
16. <h3>Table of contents</h3>
17. <a href="javascript:(function(){...})();"
18. title="TableDeMatiere">
19. Click here to display the table of contents!
20. </a>
21. </aside>
22. </body>
They are also useful for checking the presence of headings in each sectioning
content. If some headings are missing, the table of contents will display some
"untitled entries". Remember that having a heading after each sectioning
content is a good practice in terms of accessibility.
A document has been written by the HTML5 working group, which details the
different use-cases for this
element: [Link]
usecases#Introduction
The <main> element has been supported by major browsers since 2013.
And finally here are some examples (from the HTML5 specification) that mix
the <main> element with the other sectioning elements already seen in the
course:
Here is another example (also from the specification). Here the <main> element
contains a <nav> element consisting of links to subsections of the main
content:
1. <!DOCTYPE html>
2. <html>
3. <head>
4. <title>Graduation Ceremony Summer 2022</title>
5. </head>
6. <body>
7. <header>The Lawson Academy:
8. <nav>
9. <h2>Click these links to navigate...</h2>
10. <ul>
11. <li><a href="[Link]">Courses</a></li>
12. <li><a href="[Link]">Fees</a></li>
13. <li><a>Graduation</a></li>
14. </ul>
15. </nav>
16. </header>
17.<main>
18. <h1>Graduation</h1>
19. <nav>
20. <h2>Please choose:</h2>
21. <ul>
22. <li><a href="#ceremony">Ceremony</a></li>
23. <li><a href="#graduates">Graduates</a></li>
24. <li><a href="#awards">Awards</a></li>
25. </ul>
26. </nav>
27. <h2 id="ceremony">Ceremony</h2>
28. <p>Opening Procession</p>
29. <p>Speech by Valedictorian</p>
30. <p>Speech by Class President</p>
31. <p>Presentation of Diplomas</p>
32. <p>Closing Speech by Headmaster</p>
33. <h2 id="graduates">Graduates</h2>
34. <ul>
35. <li>Eileen Williams</li>
36. <li>Andy Maseyk</li>
37. <li>Blanca Sainz Garcia</li>
38. <li>Clara Faulkner</li>
39. <li>Gez Lemon</li>
40. <li>Eloisa Faulkner</li>
41. </ul>
42. <h2 id="awards">Awards</h2>
43. <ul>
44. <li>Clara Faulkner</li>
45. <li>Eloisa Faulkner</li>
46. <li>Blanca Sainz Garcia</li>
47. </ul>
48.</main>
49. <footer>Copyright 2012 [Link]</footer>
50. </body>
51. </html>
Best practice
For accessibility matters, a best practice is to split your page content into
"regions" defined by the five 5 elements
(aside, footer, header, main and nav) learned this week.
External resources:
[Link]
[Link]
[Link]
Also note that in this example, we used H1s after each sectioning element, and
we still get a hierarchy, some H1s are inside an <article> that is in
a <section> (this corresponds to the third example given in the "heading and
sectioning elements" part of the course):
1. <section>
2. <header>
3. <h1>Blog posts for April 2012</h1>
4. </header>
5. <article>
6. <header>
7. <h1><a href="">Information about this example</a></h1>
8. This example is a modified version
of <a href="[Link]
blog/[Link]">[Link]
9. blog/[Link]</a>
10. </header>
11. ...
12. </article>
13. </section>
With this technique, parts of the document can be moved more easily, or
integrated inside an RSS stream, without the need to renumber the headings.
Beware that this technique will require you to use some CSS styling, and may
confuse some screen readers that do not yet take into account this way of
computing the heading hierarchy. A simple fix is to use an H1 right after
the <body> and use only H2...H6 inside <section>, <article>,
<nav> and <aside>.
Let's add this piece of code (we removed the JS details from this extract):
1. <aside>
2. <h1>
3. <a href="javascript:(function(){...});"
4. title="TableOfContents">
5. Click here to display the table of contents!
6. </a>
7. </h1>
8. </aside>
We also added a <main> element to identify the main content of the page
composed of the big section with all blog posts:
1. <main>
2. <section>
3. <header>
4. <h2>Blog posts for April 2012</h2>
5. </header>
6. ...
7. </main>
So, while this is just a warning, we do prefer to use H1s only as top level
elements, and replace the H1s we had after <section>, <article>,
<nav> and <aside> elements respectively by a H2s and H3s.
1. <nav>
2. <header>
3. <h2>Navigation menu</h2>
4. </header>
5. ...
6. </nav>
The examples below are given "as is" to give you some hints. There are lots of
other possibilities on using CSS to position elements.
Here we use the CSS rule float:left for the <section> and the CSS
rule float:right for the <aside>. When an element floats, it goes out of the
normal flow of the HTML element. Then by default it floats to the edge of its
parent; and its size depends on the elements it contains. So, in order to fill the
whole horizontal space, we prefer here to "force the width" by setting the
CSS width property with a percentage. So we took width: 63% for
the <section> on the left and width:30% for the <aside> on the right.
You can look at the complete CSS code in the interactive example below (click
on the CSS or HTML text in the menu bar below, or click "edit on codepen" to
change the code and see the results):
Example from the live coding video, a slight adaptation of
the technique described above:
Also available online at JSBin.
Example 2: three sections centered, of equal size,
also using the float and widthCSS properties
Here we show how to make a 3 column layout using the CSS float property.
HTML code:
1. <header>
2. <code><header></code>
3. </header>
4.
5. <section>
6. <code><section> <br> float: left;</code>
7. </section>
8.
9. <section>
10. <code><section> <br> float: left;</code>
11. </section>
12.
13. <section>
14. <code><section> <br> float: left;</code>
15. </section>
16.
17. <footer>
18. <code><footer></code>
19. </footer>
Instead of having one element with a float:left and one element with
a float:right property, we instead use float:left for all three of them, and
we give a width:30% CSS property value to each <section>. We also set a
small margin so that the colums have a gap between them.
Other tutorial links have been posted in the forums of the first version of this
course: Lynda Tutorial (check with your local library for a free membership!),
a screencast from [Link], a Podcast and an article on using FlexBox in
real world deployments.
Example 4: another example written by a student
(ROyRey), that uses the flex property
This example also uses all the structuring elements we saw: main, article,
section, etc. It uses only the simplest parts of the FlexBox CSS module, so it
should be easy to understand, even for CSS beginners:
In the screenshot below, taken from the W3C specification page, the text next
to the horizontal arrow is a <summary> element, and the text displayed when
we click on the summary part, is the <details> element. This is a sort of
"accordion" with foldable content.
The <details> element generates a simple widget to show/hide element
contents, optionally by clicking on its child <summary> element.
1. <!DOCTYPE html>
2. <html>
3. <body>
4. <details>
5. <summary>
6. How to beat the boss...spoiler alert !
7. </summary>
8. <p> Just aim to the red spots near his eyes</p>
9. <p>Keep shooting at these spots until the eyes open, then hit quickly both
eyes with your laser beam.</p>
10. </details>
11. </body>
12. </html>
Step 2: click on top level summary icon, the first "hidden" part appears...
Step3: click on embedded summary icon inside the part that has been
previously unfolded:
Source code of this example, see the summary/details inside another one:
1. <details>
2. <summary>
3. How to beat the boss...spoiler alert !
4. </summary>
5. <p> Just aim to the red spots near his eyes</p>
6. <p>Keep shooting at these spots until the eyes open, then hit quickly both
eyes with your laser beam.</p>
7. <details>
8. <summary>
9. Bonus and spoiler No 2: get a new weapon by cutting the tail of the
boss.
10. </summary>
11. <p>Before finishing him, try to cut his trail, you will get a new
weapon</p>
12. <p>Just try to stay behind him as long as you can, hitting his tail
with your melee weapon, after a few hits the trail will fall and you will get a
new bonus weapon, then finish the boss.</p>
13. </details>
14. </details>
Example1: [Link]
The color and background of the icon on the left are specified by the following
CSS rule, which uses the pseudo class ::-webkit-details-marker
1. summary::-webkit-details-marker {
2. color:#FF0000;
3. background:#FFFFFF;
4. }
1. details[open] summary::-webkit-details-marker {
2. color:#0000FF;
3. background:#00FFFF;
4. }
It is also possible to change the icon itself using the CSS pseudo class :after
Example 2: [Link]
1. summary:after {
2. content: "+";
3. color: #FF00FF;
4. float: left;
5. font-size: 1.5em;
6. font-weight: bold;
7. margin: -5px 5px 0 0;
8. padding: 0;
9. text-align: center;
10. width: 20px;
11. }
1. details[open] summary:after {
2. content: "-";
3. color: #FFFFFF
4. }
Current support
Support as of October 2015:
Here is a version at JsBin of the last example, that includes a polyfill that
makes it work on nearly all browsers: IE, Microsoft Edge, which still do not
support summary/details as of May 2016. This version has been written
by jotlash, a student from the MOOC, after reading the next lesson about
polyfills.
Do you know where the “polyfill” term is coming from? It was coined by
Remy Sharp, a British Web programmer who had been using a brand of
resin to fill holes in masonry.
The link points to the JavaScript code you must include in your Web page. But
in the comments of the polyfill page, you will find an online example at
[Link]:
You can follow the link to see a running example, or directly copy and paste the
code from the main page, then include it in your Web page using
the <script> element:
Either use <script src="[Link]"> (in this case put the polyfill in a
file [Link]>) or if you want to try it on [Link], just copy it into the
jsBin script tab, or include it directly between <script>...</script>. This is
what we did:
1. <!DOCTYPE html>
2. <html>
3. <head>
4. <meta charset="UTF-8">
5. <title>Contact manager</title>
6. <script>
7. (function(e,t){function r(e){var t=null;... // POLYFILL CODE HERE!
8. ...
9. </script>
10. </head>
11. ...
The machine readable part adds semantics that can be used by search engines
for indexing, by browsers or by browser extensions, or by JavaScript code.
Useful scenarios include generating alerts for birthdays, automatically adding
dates or events that contain <time> elements in a calendar, etc.
External resources:
Example:
Date/time values
Supports different specifications of time such as "a year", "a month in a year",
"a week in a year", "a time", etc...
<time datetime="1905-
November 1905
11">
<time datetime="11-
November 13th (any year)
13">
<time datetime="1905-
Week 21 from year 1905
W21">
<time datetime="1905-
November 13th year 1905, time = 9:00
11-13 09:00">
<time
9:00 in the morning, GMT
datetime="09:00Z">
<time datetime="09:00-
9:00 in the morning, GMT minus 5 hours
05">
<time
9:00 in the morning, GMT plus 5 hours 45 minutes, (for
datetime="09:00+05:45"
example, Nepal is 5:45 ahead of GMT)
>
Duration values
Duration values use the prefix “P” for “period” as in <time
datetime="P4D"> (period = four days)...
So you start the attribute string value with a "P",
followed by a duration value that ends with
another letter indicating the unit used: "D" for
"days", “H” for hours, “M” for minutes and “S”
for seconds.
Using a “T” after the “P” marker allows you to indicate a more accurate
duration time: <time datetime="PT4H 6M 12.55S"> is a duration of 4 hours, 6
minutes and 12.55 seconds.
You still can’t represent dates before the Christian era, as years can’t be
negative. Neither can you indicate date ranges. To mark up From “21/02/2012
to 25/02/2012″, use two separate <time> elements."
Examples:
1. <h2>Recipe:</h2>
2. <ul>
3. <li> Preparation time: <time datetime="PT30M">30 minutes</time> </li>
4. <li> Cooking time: <time datetime="PT10M">10 minutes</time> </li>
5. </ul>
The HTML <mark> tag is used for indicating text as marked or highlighted for
reference purposes, due to its relevance in another context.
Example1: [Link]
Source code:
1. <!DOCTYPE html>
2. <html>
3. <head>
4. <meta charset=utf-8 />
5. <title>JS Bin</title>
6. </head>
7. <body>
8. <p>Project is due in <mark>.zip format</mark> next monday.</p>
9. </body>
10. </html>
Example 2:
Source code:
1. <body>
2. <pre>
3. <code><mark>var</mark> i = 3;</code>
4. </pre>
5. <p>The var keyword is used to declare a variable in JavaScript.</p>
6. </body>
For example:
1. mark {
2. background-color: green;
3. color: yellow;
4. }
1. <a href="[Link]">
1. please right click this link to download
2. the [Link] picture</a>
...will ask the remote HTTP server to send back the [Link] file. The browser
will receive in the response HTTP header from the server (and by default the
browser will display the image in a new tab):
1. ...
2. Content-type: image/jpg
3. ...
However, if the link points to some PHP code, Java servlet code, or any kind of
script/application on the server side, this remote server code can send in its
HTTP response a Content-type that may force the browser to download the
image instead of rendering it.
It may also propose a name for the file to be downloaded that may be different
from the one that appears in the URL of the href attribute. This can be done by
generating, in addition to the Content-type line in the response HTTP header,
a Content-Disposition line that looks like this:
Here are some extracts from a Java Servlet that generate a zip file and forces
the browser to propose downloading it using a specified name:
Here is the result of this link (just click on it): download a picture of Michel
Buffa. NOTE from May 2016: this stopped working with the new version of edX
as now the different assets (images, videos) are hosted on a different domain
than [Link]. See the warning further in this page, about cross domain
restrictions.
This will indeed force the download of an image with a filename different from
its original filename on the server side. Here is a screen capture of the Web
browser while downloading the picture. We can see in the status bar the name
of the link (the image is "[Link]") and the downloaded file is
"[Link]":
WARNING: since 2015, and for security reasons, the image should be
located on the same domain as the HTML page that contains the
link (using a relative URL works well, for example, but linking a page on
another domain will not work - it will keep its original name).
Interesting applications: serverless download
We won't detail this demo here, but take a look if you are curious to see
what can be done with this new download attribute. As the FileWriter and
FileSystem APIs are still supported only by Google Chrome (other browsers
need polyfills), you will need Google Chrome to try it.
We have also put the simplified source code of this demo on [Link] for you
to play with: [Link] the original demo by [Link]
is at [Link]
The HTML5 TRANSLATE ATTRIBUTE
Introduction
HTML5 gives us a new translate attribute. This attribute is used to limit the
impact of translation tools such as Google Translate by prohibiting the
translation of certain content. In many cases some parts of a document should
not be translated.
HTML pages that contain source code: you would certainly not like to see the
Java or PHP or whatever programming language parts of your page translated
into another spoken language!
Video game Web sites that propose cheat codes; the codes do not have to be
translated,
Street names, author names in an "about" page must not be translated,
etc.
Both Google translate and Microsoft online translation services already offer
the ability to prevent translation of content by adding markup to your content,
although they do it in (multiple) different ways. Hopefully, the new attribute will
help significantly by providing a standard approach.
The attribute's keywords are the empty string, yes, and no. The empty string
and the yes keyword map to the yesstate. The no keyword maps to the no
state. In addition, there is a third state, the inherit state, which is the missing
value default (and the invalid value default)."
In the above example, a <span> element defines an author (of a blog, for
example) who is named Michel Ham. However, his family name is the same as
pork and would be translated to "Michel Jambon" in French, or Michel Jamón in
Spanish...
...where all of the end of the sentence has been translated except the author's
name.
Inheritance between elements
When you define an element as not being translatable, its children inherit this
behavior and are themselves not translatable. The reverse is also true.
1. <p translate="no">This is a text in a paragraph element, that should not be
translated: the p element has a translate="no" attribute.<span> This part that
is in a span element embedded within the paragraph. It does not have a
translate attribute but inherits the translation-mode of the p and will not be
translated too</span>. This is the end of the paragraph...</ p>
Microdata
Introduction
There are 3 ways to provide machine-readable content embedded in a classical
Web document: HTML+RDFa, microformats and microdata. In this section, we
will focus on microdata.
Adding microdata to Web pages helps search engines to better understand the
pages' content, their topics, etc. The main purpose of microdata is Search
Engine Optimization.
We can also add another embedded data item in the middle, such as the
person's address:
1. ...
2. </dl>
3. <!-- SURFACE ADDRESS GOES HERE -->
4. <dd itemprop="address" itemscope
5. itemtype="[Link]
6. <span itemprop="streetAddress">10 promenade des anglais</span><br>
7. <span itemprop="addressLocality">Nice</span>,
8. <span itemprop="addressRegion">Alpes maritimes, France</span>
9. <span itemprop="postalCode">06410</span><br>
10. <span itemprop="addressCountry" itemscope
11. itemtype="[Link]
12. <span itemprop="name">France</span>
13. </span>
14. </dd>
15. <h1>My different online public accounts</h1>
16. ...
In the following sections, we will look more closely
at the itemprop, itemscope and itemtype attributes.
Note: For advanced users, Microdata is very similar to microformats, which use
HTML classes, or to RDFa, which doesn’t validate in HTML4 or HTML5. Because
RDFa was considered to be too hard for authors to write (Google has conducted
research that finds that authors make 30% more mistakes with RDFa than with
other formats), microdata is HTML5's answer to the need to embed semantics
into html documents.
External resources
W3C's HTML Microdata Working Group Note
Very good Microdata paper from code{4}lib journal
Microdata and the microdata DOM API, article from [Link]
Interesting blog post about Microdata by one sencha developer
Chapter from Mark Pilgrim's book about microdata, very detailed introduction
about semantic metadata in general, contains full examples with explanations
about how to describe a Person, etc.
The reference about popular HTML5 microdata
vocabularies: [Link] (do not forget to visit the full list of
vocabularies), see also the [Link] blog for news and announcements
Testing tools
Google Rich Snippets and
Structured Data test tool
One of the most popular resources for testing
microdata (as well as microformats and RDFa) is the
Google page about rich snippets and structured data.
This page contains a link to a structured data testing
tool that you can use to see how Google recognizes
the semantic data you embed in your HTML code.
Testing a real interactive example with an "about page" for
Michel Buffa
Let's have a look now at a (small) example of an about page. It renders as a
very simple paragraph that explains who Michel Buffa is... But we embedded
Microdata, so it's interesting to see how a search engine sees it, and how it
may produce "augmented search results".
Source code:
1. <!DOCTYPE html>
2. <html>
3. <head>
4. <meta charset=utf-8 />
5. <title>Michel Buffa</title>
6. </head>
7. <body>
8. <div itemscope itemtype="[Link]
9. My name is <span itemprop="name">Michel Buffa</span>,
10. And I'm
a <span itemprop="jobTitle">professor/researcher</span> at
11. <a href="[Link] itemprop="affiliation">I3S
12. Laboratory</a> in the south of France, near the city of Nice. My
13. email
14. is : <span itemprop="email">micbuffa@[Link]</span>.
15. I live in the city of
16. <span itemprop="address" itemscope
17. itemtype="[Link]
18. <span itemprop="addressLocality">Biot</span>, in a region
named
19. <span itemprop="addressRegion">Alpes Maritimes</span>
20. </span>
21. </div>
22. </body>
23. </html>
Here is what Google sees of the page. We just entered its URL
([Link] in the the Google page about rich snippets and
structured data:
Note that the address is a fully featured embedded object in the Person's
description.
Live Microdata
The Live Microdata Web site is a bit similar to the previous one except that it
shows the extracted metadata as JSON objects:
And the JSON view of the microdata:
Implementing microdata in your page /
the itemscope, itemtype and itempro
p attributes
Basic steps
Adding microdata to an HTML page is a really simple task and requires only
three attributes: itemscope, itemtype and itemprop.
1 - Define a container element by adding
an itemscope attribute
First, you need to add an itemscope attribute to an HTML element. This will
define the "global object" for which we will define properties. This element can
be of different types that we will describe later, but for now let us keep looking
at the same example we used in previous sections:
1. <section itemscope itemtype="[Link]
2. ...
3. </section>
We will look at the itemtype attribute later. Now that we have defined a global
wrapper object/element (a Person in this case), we can add properties inside
this element to define the first name, last name, etc.
Microdata works with properties defined as name/value pairs. The names are
defined in the corresponding vocabulary. For example, the vocabulary for
representing a Person, available at [Link] defines a set of
property names, as illustrated by the following screenshot:
As you can see in this small extract from the vocabulary (also called a
"schema"), a Person can have a name (some text), an Address (the type is
defined by another vocabulary named PostalAddress), an affiliation (defined by
another vocabulary named Organization) and so on.
We notice that one property, such as the address of a Person, may use another
vocabulary. Yes, a vocabulary may link to another vocabulary! There is also
inheritance between vocabularies! The above screenshot shows that the
Person vocabulary inherits from a Thing vocabulary, and the five first
properties of the table come from this vocabulary that describes things.
If you are a developer and if you are familiar with object oriented
programming, think of properties as class attributes and think of vocabularies
as classes.
Now that you have defined a container element, you may add properties to the
HTML inside:
The line:
...defines a property called "name" that has a value of "Michel Buffa" (the text
value between the opening and closing tags of the <dd> element)
Give an element inside a microdata container its own itemscope attribute with
the recommended itemtypeattribute for indicating the name of the vocabulary
used by the nested microdata.
1. ...
2. </dl>
3. <!-- SURFACE ADDRESS GOES HERE -->
4. <dd itemprop="address" itemscope
5. itemtype="[Link]
6. <span itemprop="streetAddress">10 promenade des anglais</span><br>
7. <span itemprop="addressLocality">Nice</span>,
8. <span itemprop="addressRegion">Alpes maritimes, France</span>
9. <span itemprop="postalCode">06410</span><br>
10. <span itemprop="addressCountry" itemscope
11. itemtype="[Link]
12. <span itemprop="name">France</span>
13. </span>
14. </dd>
15. <h1>My different online public accounts</h1>
16. ...
The properties at lines 8-12 refer to the address nested microdata (they are
defined in the Address vocabulary, not the Person vocabulary), and "France"
(line 14) is a property that refers to the Country vocabulary.
It is possible to use the same property name several times in one microdata
object, but with different values:
1. ...
2. <h1>My different online public accounts</h1>
3. <ul>
4. <li><a href="[Link] itemprop="url">Twitter
5. profile</a></li>
6. <li><a href="[Link] itemprop="url">Michel
7. Buffa's blog</a></li>
8. </ul>
This will define the fact that Michel Buffa has two online accounts, and the two
properties have the name url, each with its own value.
It is possible to set more than one property at once, with the same
value
Here are some microdata that represent a song. In this example, at line 5 we
set two different properties: genre and keywords with the same value (see
the MusicRecording schema definition at [Link]
And so on...
Now let's see what elements are compatible with the itemprop attribute and
where the values of the properties are located, depending on each element
type.
<time> element The data is the time in the element's datetime attribute. This lets
you, for example, just say "last week" in your text content but
still indicate exact date and time.
For example, the value of a property defined in an <img> element will be the
value of the src attribute:
1. <img itemprop="image" src="[Link]" alt="A great
professor">
Or for an <a> element, the value will be the value of the href attribute:
Microdata Tools
There are many tools available (most are free) that you can use for generating,
visualizing and debugging microdata. We list some of them in this page, but
feel free to share the tools you find / like in the forums.
Microdata generators
There are many free tools you can use to automatically generate microdata for
describing persons, restaurants, movies, products, organizations, etc. such as:
[Link]
[Link]
[Link]
Search for "microdata generators" using your favorite search engine, and you
will find lots!
First example
Visit the online page: [Link]
Structure:
Microdata:
Second example
Visit the online page: [Link]
Week 2
The <video> element
Introduction
The <video> element of HTML5 is one of the two "Flash killers" (the other being
the <canvas> element). It was designed to replace horrible things like
embedded Flash objects that we used to encounter not so long ago.
Indeed, until two years ago, this was the only way to embed a YouTube video
(fortunately, YouTube has changed that now). Furthermore, embedding a Flash
player made it impossible to watch videos on some mobile platforms
(especially Apple devices).
SINCE HTML5:
The new way of doing things is a lot better... (please open this live example at
JS Bin).
You will learn more about the different attributes of the <video> element later
on in the course...
As you can see, with the exception of Opera mini and older versions of Internet
Explorer, nearly all browsers support the <video> element. Popular streaming
Web sites like YouTube and Dailymotion also support this element and
automatically switch from the Flash player to the HTML5 version, based on your
browser (whether or not it is mobile, supports Flash, etc.).
Here is the HTML code you need to copy and paste in order to embed a video
(in this case, a tutorial that tells you how to embed a YouTube video):
The YouTube video embedded in this page by the above code: it's HTML5 but
it's not a <video> element directly inserted in the HTML of this page, it's
an <iframe>:
CODEC SUPPORT
This is one of the main issues that the industry has had to solve during the last
few years: codec support was not the same from one browser to another, for
commercial/cost reasons. For example, Firefox only supported the ogg/oggm
format from 2010 to 2013. It did not natively support mp3/mp4 encoding for
audio/video, while Internet Explorer only supported the H.264 encoding. Since
2012, things have changed as browsers have been updated. In order to check
codec support, the best way is to try it yourself: just visit Video Format Support
from Microsoft IE (test works for all browsers).
You might also check external resources, such as this page from the Mozilla
Developer Network, but beware, it is very difficult to maintain such lists.
External resources
One excellent reference is in the online documentation of the Opera browser.
At the bottom of the page, you will find important references and links to many
relevant examples.
Check out this article about the state of HTML5 video as well, a must-read for
all of you!
Another very good reference is from Apple's developer site.
About DRM, and some HTML5 video features to come in HTML 5.1: "HTML5
Video in the Open Web Platform" is a talk by Philippe le Hegaret from W3C
(video + slides) (in April 2013).
The attributes, event set and JavaScript API of the <audio> element are just a
"reduced" version of the ones from the <video> element, and here we will only
address the differences and peculiarities.
As you can see, the code is very similar to the basic <video> element usage.
1. <html lang="en">
2. <body>
3. <audio controls="controls">
4. <source src="[Link]
5. type="audio/ogg" />
6. <source src="[Link]
7. type="audio/mp3" />
8. Your browser does not support the audio element.
9. Download the audio/video in
10.
<a href=”[Link]
a>
11.
or <ahref=”[Link]
a>
12. format.
13. </audio>
14. </body>
15. </html>
Lines 8 - 12: we suggest downloading the audio files if the browser does not
support the <audio> element. This is also good practice!
Attributes of
the <video> and <audio> elements
Here are the attributes you can use with the <video> element. Most of them
are self explanatory...
Name Description
src
width If unspecified, the default width and height of the video will be used. If
and you specify one dimension but not the other, the browser will adjust the
size of the unspecified dimension to preserve the aspect ratio of the
height video.
If this boolean attribute is present, the browser displays its own controls
for video playback and volume.
controls
This attribute allows you to specify an image that the browser will use
while video is being downloaded, or until the user starts playing the
poster video.
If this attribute is not specified, the first frame of the video will be used
instead.
Name Description
This attribute asks the browser to start playing the video automatically as soon as the page
autoplay is ready.
The preload attribute is used when autoplay is not used. It tells the
preload browser what to do before a user plays a video. This attribute is a hint -
the browser may ignore it. While autoplay and preload are mutually
exclusive, if both are present, then preload is ignored.
Possible values:
auto (default value): the browser will decide. This will depend on the
implementation, and on the kind of connection: wifi, 3G, data roaming
etc.
Another boolean attribute that indicates to play the video in loop mode (and it starts again
loop when finished).
Best practice: do not use autoplay and add preload="none" if you target
mobile devices or if you have multiple audio/video on the same page. For
example, this page contains many audio elements and it does not make sense
to have them preload or autoplay.
About the poster attribute
If the poster attribute is missing, usually the first non-blank frame of the video
will be used as the image that is shown when the video is not playing.
while this is the expected behavior, Internet Explorer doesn’t actually do this, it
displays the first frame of the video as soon as it can regardless of the poster
value (see Ian Devlin's article about this).
Best practice: think twice before using the autoplay attribute, even for
desktop applications.
As with the <video> element, the same best practice in regard to preload and
autoplay attributes should be followed.
Styling media players with CSS3
The <video> and <audio> elements are just like other HTML elements, so CSS3
can be used for styling, including CSS3 transitions, animations and transforms.
This was not possible with Flash technology.
1. <figure id="figaudio1">
2. <img id="imghorse" width="200"
3.
src="[Link]
4. alt = "a horse"/>
5. <figcaption id="figcptionaudio1"> Press Play to hear the horse!
6. <audio controls="controls">
7. <source src="[Link]
8. type="audio/ogg" />
9. <source src="[Link]
10. type="audio/mp3" />
11. Your browser does not support the audio element.
12. Download the audio/video in
13.
<a href=”[Link]
a>
14.
or <ahref=”[Link]
a>
15. format.
16. </audio>
17. </figcaption>
18. </figure>
1. #figaudio1 {
2. width : 420px;;
3. text-align:center;
4. padding : 6px;
5. background : white;
6. margin : 0 11px 0px 0;
7. border :solid 1px #888888;
8. border-radius : 8px ;
9. }
10.
11. #figcptionaudio1 {
12. font-size : .8em;
13. padding : 6px 8px;
14. background : #dddddd;
15. display :block;
16. text-align :center;
17. font-family : georgia, serif;
18. font-style : italic;
19. border-radius : 7px ;
20. }
21.
22. #figaudio1 > img {
23. background : #eeeeee;
24. padding : 5px;
25. border : solid 1px #444444;
26. }
27.
28. /* For audio and img transitions/animation */
29. audio, #figaudio1 > img {
30. transition:all 0.5s;
31. }
32.
33. #figaudio1 > img:hover {
34. box-shadow: 15px 15px 20px rgba(0,0, 0, 0.4);
35. transform: scale(1.05);
36. }
37.
38. audio:hover, audio:focus, audio:active {
39. box-shadow: 15px 15px 20px rgba(0,0, 0, 0.4);
40. transform: scale(1.05);
41. }
Changing the size of a video on the fly using CSS3
transforms
Resizing and rotating a video as the mouse pointer comes
over it
See this example online (where you can modify the code on the fly) or just play
the following video, and move the mouse pointer in and out of the video while
it's playing.
This example uses the pseudo CSS class :hover in order to track
the mouseover event. On mouseover, it uses a CSS3 transition property that
interpolates the changes in the scale and orientation of the video element
(done using a transform CSS property).
1. #w3devCampusVideo {
2. width: 300px;
3. transition: all 0.5s ease-in-out;
4. }
5.
6. #w3devCampusVideo:hover {
7. width:400px;
8. transform:rotate(-5deg);
9. }
FullScreen video that resizes and maintains ratios. Uses
simple JavaScript to modify CSS properties
This is a trendy way of displaying videos (the PayPal Web site, as of June 2015,
used a small size video that looped and started playing as soon as the page
was loaded. One of the JsBin examples below uses this video. Note that as of
October 2015 PayPal removed the video and replaced it by a still image).
Below you will find two examples that show how to do this trick. The first is for
a "regular" video, using the <video> and <source> elements. This technique
can also be used on any YouTube embedded videos (see Example 2 below).
The interesting part is that we use a 100% standard (and really small and
simple) JavaScript code here to handle the window resize events and we just
set regular CSS properties width and height of the video element, to resize
the video.
Online at JS Bin
Here is the HTML code. It's really simple, just notice the <body
onload="init();"> which calls the JavaScript init() function right after the
page is loaded.
1. <!DOCTYPE html>
2. <html lang="en">
3. <head>
4. <meta charset="utf-8">
5. <title>Full width video like PayPal site</title>
6. </head>
7. <body onload="init();">
8. <video id="myVideo" autoplay>
9. <source
10. src=[Link]
11. type=video/webm>
12. <source
13. src=[Link]
14. type=video/ogg>
15. <source
16. src=[Link]
17. type=video/mp4>
18. </video>
19. </body>
Here is the CSS (remove margins, remove padding, hide parts that could
overflow from the <body>):
1. body {
2. margin:0;
3. padding:0;
4. overflow:hidden;
5. }
The CSS and JavaScript codes for this example are exactly the same as in
Example 1.
Full screen video, pure CSS approaches (external resources)
Here is a JSBin with the video from the PayPal Web site, played full
screen using only very simple CSS.
In this example, the video does not rescale; it's just cropped if the browser
window is resized. Enlarge your browser and you'll see a man with a phone on
the right. Resize your browser and you'll see only part of the video.
Example on JsBin
CSS code:
1. body {
2. margin:0;
3. padding:0;
4. overflow:hidden;
5. }
6.
7. video {
8. width:100%;
9. height:auto;
10. }
This time the video is zoomed in so that it's much bigger than the browser's
window. When we resize the browser, the part of the video that is visible
adapts itself. It's not "real resize" of the video.
Try the example and read the explanation in an article by Dudley Storey. Also
available as a simplified JsBin example.
HTML code:
1. <!DOCTYPE html>
2. <html>
3. <head>
4. <meta charset="utf-8">
5. <title>Full screen video, example from [Link] by </title>
6. </head>
7. <body>
8. <header>
9. <video autoplay="" loop=""
10.
poster="[Link]
11. id="bgvid">
12. <source src="[Link]
13. type="video/webm">
14. <source src="[Link]
15. type="video/mp4">
16. </video>
17. </header>
18. <section>
19. <h1>[Link]
20. Background-Video</h1>
21. </section>
22. </body>
23. </html>
CSS code:
1. html, body{
2. color:white;
3. height: 100%;
4. }
5. header{
6. height: 100%;
7. background-image: url('[Link]
url('#');
8. background-repeat: repeat, no-repeat;
9. background-size: auto, cover;
10. background-position: center center, top left;
11. font-family: sans-serif;
12. color: #051a00;
13. }
14.
15. header video {
16. position:fixed;
17. top:50%;
18. left:50%;
19. min-width:100%;
20. min-height:100%;
21. width:auto;
22. height:auto;
23. z-index:-100;
24. transform:translateX(-50%) translateY(-50%);
25. }
[Link] video is in the header, and the header has a plotted transparent
background that is repeated in X and Y (see line 8 and 9).
[Link] video is positioned so that it's origin (top left corner) is away from the
visible surface (line 25), while it is set to take 100% of the surface (lines 20 and
21).
Full screen video that resizes and keeps its ratio, using the viewport
units (beware, not supported by old browsers)
Example on JsBin
This time we obtain the same result as with the first example that used
JavaScript and a resize event. The video resizes correctly and keeps its ratio.
CSS code:
1. body {
2. margin: 0;
3. }
4.
5.
6. video {
7. position: absolute;
8. width: 100vw;
9. height: 100vh;
10. object-fit: cover;
11. object-position: center center;
12. }
Conclusion: we can get full size video without JavaScript by using viewport
units, unless we need to support some old browsers
(See [Link] for current support).
Setting the video to 100% width and height results in different behavior:
This will create a complete video player for the file "video.mp4", with control
buttons, and will add it to the <body> element of the page.
Conclusion: you can very easily change the look and feel of the standard
video player: use custom CSS and design your own control widgets. We can
find many examples of such video players that offer extended functionalities on
the Web. We will present some of them later in the course, but before that,
let's see a little more of what we can do using the JavaScript API of
the <video> element.
JavaScript API
of the <audio> and <video> elements
Methods, ProperTIES, AND EventS
The JavaScript API gives you powerful tools to manipulate the <video> element,
as the video object provides many properties, methods and events.
The complete list of events can be found at the W3C specification page, and
numerous examples of each event can be found on many Web sites such as
this one.
The complete list of properties can be found at the W3C HTML5 Video Events
and API page. This page is interesting for Web developers because it shows an
interactive view of the different values and events changing over time while
the video is playing within the page.
Click the picture to see it running online (or try the direct link), then
play with the different buttons and look at the table of events and
properties that will change in real time. The displayed names
show the properties, events, and methods from the API.
Here is a table that shows the most interesting
methods, properties, and eventsprovided by
the <video> element API
We provide this as a quick reminder - keep in mind that the complete list is
much longer!
videoHeight timeupdate
error empty
muted waiting
seeking loadedmetadata
volume
height
width
seekable (readonly)
played (readonly)
Let's see now, through a set of examples, how to use the most important of
these properties, methods, and events...
Lines 7, 9 and 11: we add a click listener to each button, in order to call a
JavaScript function when the button is clicked.
Line 14: using the DOM API we get the JavaScript object that corresponds to
the video element we inserted in the HTML document. This line is outside a
function, it will be executed when the page loads.
Lines 17 and 20: we call methods from the API for playing/pausing the video.
Line 24: we modify the currentTime property in order to rewind the video.
Note that [Link]() also rewinds the video, shows the poster image again,
but also pauses the video. By using currentTime=0 the playback does not
stop.
To try this example: use the progress cursor to go near the end of the first
video that is being played and see how it continues with the next video.
1. <!doctype html>
2. <html lang="en">
3. <head>
4. <title>Sequential Movies</title>
5. <script>
6. var myVideo;
7. var currentVideo = 0;
8. var sources = [
9. "[Link]
10. "[Link]
P1120973_512kb.mp4"
11. ];
12. // Set the src of the video to the next URL in the playlist
13. // If at the end we start again from beginning (the modulo
14. // [Link] does that)
15. function loadNextVideo() {
16. [Link] = sources[currentVideo % [Link]]
17. [Link]();
18. currentVideo++;
19. }
20. // callback that loads and plays the next video
21. function loadAndplayNextVideo() {
22. [Link]("playing " + sources[currentVideo % [Link]])
23. loadNextVideo();
24. [Link]();
25. }
26. // Called when the page is loaded
27. function init(){
28. // get the video element using the DOM api
29. myVideo = [Link]("#myVideo");
30. // Define a callback function called each time a video ends
31. [Link]('ended', loadAndplayNextVideo, false);
32. // Load the first video when the page is loaded.
33. loadNextVideo();
34. }
35. </script>
36. </head>
37. <body onload="init()">
38. <video id="myVideo" controls></video>
39. </body>
40. </html>
Some examples are given "as is", such as the custom video player that
uses SVG (at the end of the page); if you are interested, you may view the
code.
Don't forget to click the JavaScript and CSS tabs at JS Bin in order to display the
JavaScript code that creates the buttons on the right of the video, and the CSS3
that processes the different clicks and applies CSS3 transforms.
This example shows a lot:
CSS filter support (green squares with a small yellow part in the top right
corner) means that a prefix is needed, like -webkit-filter, or -moz-
filter or -o-filter):
Below, you will find images obtained with different filter values:
Use <video class="blur"> for example, to obtain a blurry video.
This complete example changes the CSS class associated to the video
element, on the fly in a mouseclick listener callback.
1. .blur {
2. filter: blur(3px);
3. }
4. .brightness {
5. filter: brightness(5);
6. }
7. .contrast {
8. filter: contrast(8);
9. }
10. .hue-rotate {
11. filter: hue-rotate(90deg);
12. }
13. .hue-rotate2 {
14. filter: hue-rotate(180deg);
15. }
16. .hue-rotate3 {
17. filter: hue-rotate(270deg);
18. }
19. .saturate {
20. filter: saturate(10);
21. }
22. .grayscale {
23. filter: grayscale(1);
24. }
25. .sepia {
26. filter: sepia(1);
27. }
28. .invert {
29. filter: invert(1)
30. }
This extract from the source code explains how to set a mouseclick listener
and how to change the value of a CSS class attribute on the fly:
[Link] is a very practical tool. It's a simple library you can include in
your HTML page that will add prefixes on the fly when needed. It uses the
[Link] tables and also relies on the W3C specifications, so we
recommend it!
Typical use: just add some lines of code to the <head> element of your HTML
page.
1. <head>
2. <script src="[Link]
[Link]"></script>
3. <style type="unprocessed" id="AutoprefixerIn">%css%</style>
4. <style id="AutoprefixerOut"></style>
5. <script>
6. AutoprefixerSettings = ""; // Specify here the browsers you
7. // want to target or leave empty
8. [Link]("AutoprefixerOut").innerHTML =
9. autoprefixer(AutoprefixerSettings || null)
10. .process([Link]("AutoprefixerIn")
11. .innerHTML)
12. .css;
13. </script>
14. </head>
Example 3: how to track all possible events and
manipulate many properties
This example also shows how to handle failures. See the code and play with
this example online.
Note that on mobile phones, the video does not start until the user presses the
play control or clicks on the video picture. Using the "canplaythrough" event is
a trick to call a function that starts the video player as soon as the page is
loaded on desktop. This event is not supported by mobile devices, so if you
try this example on a mobile, the video will not start automatically.
As the Apple Developer Web site explains it: "The buffered property is
a TimeRanges object: an array of start and stop times, not a single value.
Consider what happens if the person watching the media uses the time
scrubber to jump forward to a point in the movie that hasn’t loaded yet—the
movie stops loading and jumps forward to the new point in time, then starts
buffering again from there. So the buffered property can contain an array of
discontinuous ranges. The example simply seeks the end of the array and
reads the last value, so it actually shows the percentage into the movie
duration for which there is data. "
1. <!doctype html>
2. <html lang="en">
3. <head>
4. <title>JavaScript Progress Monitor</title>
5. <script>
6. function getPercentProg() {
7. var myVideo = [Link]('video')[0];
8. var endBuf = [Link](0);
9. var soFar = parseInt(((endBuf / [Link]) * 100));
10. [Link]("loadStatus").innerHTML = soFar + '%';
11. }
12. // Will be called as soon as the page is ready on desktop computer,
13. // Only when a user clicks on play control or image on mobile
14. function myAutoPlay() {
15. var myVideo = [Link]('video')[0];
16. [Link]();
17. }
18. function addMyListeners(){
19. var myVideo = [Link]('video')[0];
20. [Link]('progress', getPercentProg, false);
21. // Calls autoplay only if the device is adapted
22. [Link]('canplaythrough', myAutoPlay, false);
23. }
24. </script>
25. </head>
26. <body onload="addMyListeners()">
27. <h1>Check progression of buffering before playing a movie. Useful
withy
28. slow connexion (3G, etc.)</h1>
29. <div>
30. <video controls>
31.
<source src=[Link]
32. type=video/webm>
33.
<source src=[Link]
34. type=video/ogg>
35.
<source src=[Link]
36. type=video/mp4>
37. </video>
38. <p id="loadStatus">Buffering...</p>
39. </div>
40. </body>
41. </html>
We recommend looking at the source code; you will learn many things related
to the Week 1 course.
Screenshot:
This is the discussion forum dedicated to "streaming multimedia content". You
are welcome to post comments and share your creations here, and of course
ask questions.
Suggested topics
Where do you host your video files (we are speaking about files that can be
used with the <video> element directly, not on YouTube, DailyMotion, etc.)?
Have you already tried some of the enhanced audio or video players? Would
you please share opinions or make a review of these players?
What tool do you use for encoding your audio and video files?
Optional projects
This might be useful: free videos
at [Link]
Here are a few ideas to play with the material learned in this section. Your
classmates and the team who prepared the course will be happy to look at
them and give feedback. Please post URLs of your work in this discussion
forum. These projects are optional, meaning that they won't be graded.
Project 1 (very easy): find the "enhanced HTML5 video players" described in
the course and try to use one of them to play a video. Do some customization
as well, such as adding a logo, choosing a theme, etc.
Project 2 (easy): try to write a video or an audio player with a few custom
buttons for play/stop/etc. When your custom player is done, please add a way
to play several videos one after another (what we call a playlist), etc.
Examples that can help you, created by students of earlier versions of this
MOOC:
The WebVTT format used for describing a track file is also presented in this
chapter.
Some definitions
closed captions describe all relevant audio present in the video (fire, rain,
birds, gun fights, etc.).
subtitles are only for spoken words.
The accessibility features of TV programs often propose both options for people
with hearing deficiencies.
1. <Files [Link]>
2. ForceType text/vtt;charset=utf-8
3. </Files>
It might be worth mentioning that most browsers work fine with WebVTT even
if the MIME Type is not set, but Internet Explorer doesn’t: in fact it will
ignore WebVTT entirely unless the MIME Type is set correctly!
Here is an example of a video element that includes a <track> element in
the .vtt (WebVTT) format (line 7), original version
at [Link] and we also cooked a version that is
easier to study on jsbin: [Link]
Notice that the <track> element at line 9 has an attribute named kind that
indicates the type of the track that is included. Possible values
are: subtitles, captions, descriptions, chapters or metadata.
The <track> element also has an attribute default that indicates that we
want this track to be displayed by default when reading the video.
1. <video src="[Link]">
2. <track kind=subtitles src=[Link]
3. srclang=en
4. label="English">
5. <track kind=captions src=[Link]
6. srclang=en
7. label="English for the Hard of Hearing">
8. <track kind=subtitles src=[Link]
9. srclang=fr
10. lang=fr
11. label="Français">
12. <track kind=subtitles src=[Link]
13. srclang=de
14. lang=de
15. label="Deutsch">
16. </video>
label: the label value will be displayed in the GUI control that is included in
the default HTML5 video player,
srclang: gives the language for the text track data. The value must be a
valid BCP 47 language tag. This attribute must be present if the element's kind
attribute is in the subtitles state.
1. WEBVTT
2. [Link].000 --> [Link].042
3. (drumbeat)
4. [Link].167 --> [Link].025
5. (plaintive violin solo playing)
6. [Link].000 --> [Link].183
7. (wind whistling)
8. [Link].167 --> [Link].025
9. (orchestra music swells)
10. [Link].033 --> [Link].192
11. (weapons clash)
12. [Link].000 --> [Link].175
13. (gasps)
14. [Link].183 --> [Link].158
15. (grunts)
16. [Link].167 --> [Link].058
17. (groaning)
18. [Link].192 --> [Link].150
19. (blade rings)
20. [Link].158 --> [Link].008
21. (bellowing)
22. [Link].017 --> [Link].067
23. (grunting)
24. [Link].075 --> [Link].133
25. (panting)
26. [Link].108 --> [Link].125
27. (cries out in agony)
28. [Link].050 --> [Link].058
29. (panting)
30. [Link].092 --> [Link].142
31. (panting)
32. [Link].017 --> [Link].125
33. (orchestra plays ominous low notes)
34. [Link].058 --> [Link].133
35. (plaintive violin solo returns)
36. [Link].158 --> [Link].058
37. This blade has a dark past.
38. [Link].092 --> [Link].108
39. It has shed much innocent blood.
40. [Link].083 --> [Link].000
41. You're a fool for traveling alone
42. so completely unprepared.
43. [Link].100 --> [Link].033
44. You're lucky your blood's still flowing.
45. [Link].183 --> [Link].075
46. Thank you.
This format is rather simple, but we still recommend reading this excellent
article from Mozilla Developer Network that explains in detail all the different
options.
Each "element" in this file has a starting and ending time, plus a value (the text
that will be displayed), followed by a blank line (blank lines are separators
between elements).
Each element is called "a cue", and may optionally have an ID that will be
useful when using the track element JavaScript API, in particular
the getCueById() method of TextTrack objects. How to use these will be
taught in the "advanced HTML5" course, soon on W3Cx
1. 9
2. [Link].000 --> [Link].000
3. to hear from <u>you</u>
4. 10
5. [Link].500 --> [Link].000
6. We want to hear what inspires you as a developer
IDs may also be defined as strings, and values can use HTML as well:
1. Opening
2. [Link].000 --> [Link].000
3. Welcome to our <i>nice film</i>
The displayed text can span multiple lines, but blank lines are not allowed, as
they would be interpreted as a separator:
1. [Link].083 --> [Link].000
2. <p>You're a fool for traveling alone</p>
3. <p>so completely unprepared.</p>
External Resource:
An unofficial webVTT format validator
For this, use any sort of open source, free or commercial video encoding
software, such as Handbrake (free, open source) or Super (free). There are also
online video encoding services, and you can even upload your video to
YouTube, let it encode your video in several resolutions and codecs, and use a
browser extension such as VideoDownloadHelper (for Firefox) to download the
video in your chosen formats.
So, let's suppose you have a video like the one below (we included it on
YouTube for practical reasons). This video has subtitles (you can activate them
in the YouTube player), but the goal of this lesson is to explain how we made
them without using the YouTube embedded tools, which do not allow export
the subtitle file to be exported in the webVTT format.
And you've also got it in mp4/H264 and in webm formats. Here is how you can
embed it in your page using the video element:
Go to the above Web site, click on the "subtitle a video" link, then follow the
different tutorials/instructions. It will ask for a YouTube URL, so it's better to
first upload your video to YouTube (even in private mode). Once you have
entered the URL of your video, you will have an online subtitles/caption editor.
Enter your subtitles and sync them until you are happy with the results.
Once your subtitles/captions are ok, you will be able to upload them to
YouTube, or -this is what we wanted first- download them as WebVTT format:
Try your subtitled/captioned video
This video example shows each use case. We also "cooked" an easier version
to study on JS Bin (look at the HTML in JS Bin).
1. WEBVTT
2. [Link].000 --> [Link].000
3. These captions test some features of the WebVTT formats
4. [Link].000 --> [Link].000 line:5%
5. This cue is positioned at the top of the video
6. [Link].000 --> [Link].000 position:5% align:start
7. This cue is positioned at the left side of the video.
8. [Link].000 --> [Link].000 position:95% align:end
9. And this one ate the right side.
10.[Link].000 --> [Link].000 size:33%
11. This cue is only a third of the width of the video, hence the multiple line
breaks.
12. [Link].000 --> [Link].000
[Link] cue contains <b>bold</b> text.
14. [Link].000 --> [Link].000
[Link] cue contains <i>italic</i> text.
16. [Link].000 --> [Link].000
[Link] cue contains <u>underlined</u> text.
18. [Link].000 --> [Link].000
[Link] cue contains <b><i><u>bold, italic, underlined</u></i></b> text.
20. [Link].000 --> [Link].000
21.<[Link]>This cue contains the class "myclass".
[Link] that support ::cue CSS should make it red.</c>
23. [Link].000 --> [Link].000
24. The following cue contains two voices.
25. Tarzan should be blue and Jane green.
26. [Link].000 --> [Link].000
27. <v Tarzan>Me Tarzan...
28. <v Jane>That would make me Jane!
29. bigtext
30. [Link].000 --> [Link].000
31. This cue has a unique id.
32. Using CSS, its font size should be 150%.
33. [Link].000 --> [Link].000
34. The <[Link].333>text <[Link].666>in <[Link].000>this <00:0
1:07.333>cue <[Link].666>should <[Link].000>grow
35. <[Link].333>one <[Link].666>word <[Link].000>at <[Link]
.333>a <[Link].666>time
36. [Link].000 --> [Link].000
37. That's it! For now...
It is possible to locate the cues in the video viewport using absolute or relative
values. The attributes that position the text are located on the same line as the
cue definition, like at line 9 of the previous WebVTT example file:
The ::cue pseudo element selector is used to match "cues" in the webVTT file.
You add parenthesis and a secondary CSS selector to match cues that have a
particular id, or a particular CSS class, etc. Look at the CSS above and at the
extract from the webVTT file, play the video, you will understand how
this works...
Support differs from one browser to another, see this compatibility table for
more info. Notice that most of the enhanced players presented further on in
the course will provide full support.
Using the <v> tag, you will distinguish different voices that should be displayed
in different colors (depending on the HTML5 video player implementation). See
the CSS presented in the previous section to see how to specify the colors for
the different voices.
External resource:
Article from Mozilla Developer Network that details all the options you can use
in WebVTT cues.
Here is an example of WebVTT files with defined chapters. Each "CUE" at line 3,
7, 11 etc. can bear any name. We used "Chapter 1, Chapter 2, Ending, etc..."
but you are free to name them as you choose.
What makes them special is that the track has an attribute kind="chapters".
In 2015, the <video>elements rendered in standard browsers ignore chapters,
but enhanced HTML5 players such as SublimeVideo Player or JW Player take
them into account.
It's also easy to process them, and for example, to generate a custom
navigation menu, using the <track>JavaScript API (which is covered in
the HTML5 part 2 course available on W3Cx).
How to do this will be taught in the "advanced HTML5" course, soon on W3Cx.
Examples of use
Add a navigation menu to start playing the video at given
chapters
This example shows a video with an enhanced progress bar that displays the
different chapters as small "clickable" squares. Furthermore, using the
JavaScript API of the <track> element, this Web site builds a navigation menu
(on the right of the video):
Some JavaScript code listens to the ontimeupdate event while the video is
playing. We use the currentTimeproperty of the video to know exactly where
we are in the video. Finally, we also rely on an external library to render in an
HTML5 canvas the bars corresponding to the current video explanations. We
render in real time guitar pro tablatures using the [Link] library.
Suggested topics
What tools do you use for adding subtitles to videos?
Did you have problems with encoding foreign languages?
What subtitle format do you use? WebVTT or .srt or something else?
Optional projects
Here are a few project ideas. Your classmates and the team who prepared the
course will all be glad to try them and give some feedback. Please post URLs in
this discussion forum. These projects are optional, meaning that they won't be
graded.
Project 1 (very easy): add some subtitles of your own on one of your videos.
Share your step by step experience. This will be a valuable resource for your
classmates.
Very simple example on JsBin with a video and subtitles hosted in the "public"
directory of a dropbox account. Note the use of the crossorigin attribute of
the <video> element. The subtitles were created by hand
with [Link]
Project 2 (easy): try to style some of the subtitles, set their position, etc.
Try it on JSBin: Samurai Pizza Cat with subtitled lyrics grabbed from the
Wikiquote Web site, and synchronized using [Link]
A Queen song subtitled by Ann McCartney - the JSBin contains all the
explanations at the bottom of the page. Try it on JSBin.
We call them "HTML5 enhanced video players" because on top of being based
on the <video> element, they come with custom features, custom look'n'feel,
chapters, etc., based on a JavaScript API that makes such
customizations possible.
An explanation of what enhanced video players can do, by the creators of the
popular JW Player.
Accessible players
For those of you interested in this particular topic, here is a very good resource
that compares most of the players presented in this section, in terms of
accessibility. This resource has links to players designed especially for people
with disabilities: accessible media player resources and demos.
Total control!
No need for external dependencies
Lightweight: no need to download lots of JavaScript and CSS code (also, Flash
fallbacks in some cases)
Popular players such as the Sublime video player (now bought by Dailymotion,
and no more officially supported, but still downloadable) and JW Player have
many explanations and examples on their Web sites, and are either free of
charge or come with free versions. The PayPal team open sourced an
"accessible video player" used on the PayPal Web site.
Example screenshots
Scrub Bar thumbnails (JW Player)
Read this article about 10 enhanced HTML5 audio players, for example.
EXAMPLES
Chameleon audio player (commercial):
SoundManager2, a free HTML5 audio player with flash fallback and a javaScript
API that makes it suitable to any kind of project.
Using the webcam video stream
Introduction to the getUserMedia API
The getUserMedia API is useful for controlling a webcam video stream. This
chapter presents the most interesting parts, related to
the <video> and <audio> elements.
While this API is one component of the WebRTC specification and therefore not
considered a "real" part of the HTML5 specification, we still consider it relevant
to the "multimedia" part of this course. The getUserMedia API, when dealing
with video streams, is always used in conjunction with the <video> element.
In fact, this example still does not work "as is". Prefixes need to be added to
the API function calls, due to limitations of current browser support.
It's similar to the first example above except that we use the prefixed versions
of getUserMedia(...). This example works on Opera/Chrome/Firefox on
Desktop and Mobile.
1. <html>
2. <head>
3. <meta charset="utf-8">
4. <title>JS Bin</title>
5. <script>
6. [Link] = ( [Link] ||
7. [Link] ||
8. [Link] ||
9. [Link]);
10.
11. if ([Link]) {
12. [Link] (
13. // constraints
14. {
15. video: true,
16. audio: false
17. },
18.
19. // successCallback
20. function(localMediaStream) {
21. var video = [Link]('video');
22. [Link] = [Link](localMediaStream);
23. },
24.
25. // errorCallback
26. function(err) {
27. [Link]("The following error occured: " + err);
28. }
29. );
30. } else {
31. [Link]("getUserMedia not supported");
32. }
33. </script>
34. </head>
35. <body >
36.
<video width=200 height=200 id="video" controls autoplay></video>
37. </body>
38. </html>
More on getUserMedia
Let's see some more examples of what we can do with the getUserMedia API:
start/stop the webcam, take a screenshot from the current video stream from
the webcam, and apply CSS effects in real time. And at the end, we give links
to some cool examples available on the Web.
1. <html>
2. <head>
3. <meta charset="utf-8">
4. <title>JS Bin</title>
5. <script>
6. [Link] = ( [Link] ||
7. [Link] ||
8. [Link] ||
9. [Link]);
[Link] webcamStream;
11.
12. function startWebcam() {
13. if ([Link]) {
14. [Link] (
15. // constraints
16. {
17. video: true,
18. audio: false
19. },
20.
21. // successCallback
22. function(localMediaStream) {
23. var video = [Link]('video');
24. [Link] = [Link](localMediaStream);
25. // We use the first webcam by default
26. webcamStream = [Link]()[0];
27. },
28.
29. // errorCallback
30. function(err) {
31. [Link]("The following error occurred: " + err);
32. }
33. );
34. } else {
35. [Link]("getUserMedia not supported");
36. }
37. }
[Link] stopWebcam() {
39. [Link]();
40.}
41. </script>
42. </head>
43. <body >
44.
<video width=200 height=200 id="video" controls autoplay></video>
45. <button onclick="startWebcam();">Start Webcam</button>
Explanation:
Lines 6-9: set the [Link] method with the name that
works on the current browser. As some browsers only have experimental
implementations, this method needs to be prefixed by -webkitor -moz etc.
Then in the rest of the code, we can just
use [Link] without worrying about prefixes. If the browser
does not support this API at all, it will receive undefined.
Line 13: we test if [Link] is not defined (aka supported
by the current browser).
Lines 14-32: we call [Link]. We defined here (line 21 and
28) the callback functions directly between the parenthesis of the method call.
This is possible with JavaScript, and might confuse beginners:
Lines 15-19 define the first parameter of the call: a JavaScript object that
defines the "constraints", here we only want to capture the video.
Lines 22-27 define the function called in case of success, instead of having
just the function name here like in previous examples, we directly put the code
of the function. Lines 23-25 are executed when the webcam stream could be
opened. Line 25 we store the stream of the first available video stream (there
can be more than one webcam) in a global variable so that we can use from
another function (for stopping/starting the webcam...)
Lines 29-32 define a function called in case of error (the webcam cannot be
accessed).
Line 33: closing parenthesis of the [Link](...) method
call.
Lines 38-40: a function for stopping the webcam. We use the global
variable webcamStream here, that has been initialized when we started using
the webcam, line 25.
Apart from videoconferencing, microphone input will be used for music Web
apps, from the WebAudio API. This API focuses on real time sound processing
and music synthesis. This API will be covered in the advanced W3Cx HTML5
course.
Do try some nice WebRTC applications like [Link] audio and video
conferencing tool. Also check out the WebAudio demonstrations written by
Chris Wilson, in particular the one called "Input effects".
drawing and animating things in the new <canvas> element, for offline
So yes, during this course, in particular during Week 3 and 4, you will have
more, many resources are available on the Web; this document is simply
here to give you a head start. Remember that one great thing about these
MOOCs courses is that everybody can help each other. Some students are
very good in JavaScript and are usually very happy to help others when
External resources
by Stoyan Stefanov
Video tutorials at Treehouse are very slick, this includes a basic JavaScript
course.
Codecademy is also very good - very nice JavaScript introduction for
from scratch.
We will not look at the JavaScript syntax here, but more at "JavaScript in
First of all, you need to find a way to debug your code and see errors. If
your work does not produce any results, you must know why!
For that you will use the dev. tools of your browser. Press F12 in
1
2
3 <!DOCTYPE html>
4 <html>
5 <head>
6 <meta charset=utf-8 />
7 <title>Web Audio API</title>
8 <script>
9 [Link]("Some JavaScript code has been executed");
1 </script>
0 </head>
1 <body>
1 <h1>JavaScript debugging using the dev tool console</h1>
1 </body>
2 </html>
1
3
loaded: the JavaScript code is executed before the browser could see the
rest of the page (as the <script></script> is located before
the <body>).
The H1 element, for example, does not exist in the Document Object Model,
and has not yet been displayed when the JavaScript code is executed. If we
all [Link]() messages), and re-execute the page (just type a space
at the end of a line, this will re-render the page and display the message in
the console), we see the message in the console tab, as well as in the dev.
It is also possible to use the "real dev. tool console", and for this I
Bin editor. Press the black arrow on the top right of the output window -
this will render the page as a standalone Web page, then press F12. You
should see:
Ok, now, let's make an error:
to look at some basic tutorials on how to use the dev. tools of your
browsers, since they differ from one another in the way they work
StackOverflow.
The canvas has been designed for pixel-based graphics, while SVG
(Scalable Vector Graphics, another W3C standard) is for vector-based
graphics.
Indeed, the canvas JavaScript drawing API supports different kind of shapes:
lines, rectangles, ellipses, arcs, curves, text, images. Some drawing styles need
to be specified that will affect the way shapes are drawn (color, drawing width,
shadows, etc.). An alpha channel for drawing in transparent mode is also
supported, as well as many advanced drawing modes and global filters (blur,
etc.).
The canvas is also used to do animations at 60 frames per second (useful for
games), to display videos with special effects, to display a webcam stream, and
so on.
Examples
Example 1
Foot Chinko, one of the most popular free HTML5 games (released in 2015):
Example 2
Data visualization with the HTML5 <canvas>:
Example 3
Love HTML5, a nice demo that shows 60 frames/s animation in a
canvas, (written in 2009)!
Performance is generally good today, since most Web browsers support
hardware acceleration or will add support soon. Back in 2009, this demo ran at
only a few images per second on some low-end computers (smartphones that
could run HTML5 demos, such as this one, did not exist at that time ) due to
the lack of hardware acceleration support in the browser's implementations of
the canvas API.
Note: 3D drawing using the WebGL API is also possible in a <canvas>, but will
not be covered in this course. For the most curious among you, please have a
look at the two popular libraries for doing 3D drawing/animation in
a <canvas>: BabylonJS and ThreeJS.
Current support by browsers (as of 2015)
PDF version
The image links to a PDF - just click on it.
The canvas coordinate system
X axis is horizontal, directed to the right
Y axis is vertical, directed downwards
The coordinate system used for drawing in canvases is similar to the one used
by many drawing APIs like Java2D: the (0 , 0) is in the top left corner while the
X axis is going to the right and the Y axis to the bottom, as shown in the
following picture (author Mark Pilgrim):
Small errata about what I said in the above video: "So let's get the canvas
DOM API"..
The part is bold is not correct: querySelector, technically, comes
from Selectors API. Just in case some people would like to go to the
specs...
Here are the different steps, in a little more detail, of the example
4. is disabled.
5. </canvas>
"transparent".
Make it visible using CSS: A good practice when you are learning
to use canvases is to use some CSS to visualize the shape of the canvas.
The three lines of CSS will create a border around the canvas
CSS code:
1. <style>
2. #myCanvas {
3. border:1px solid black;
4. }
5. </style>
We can have more than one <canvas> in a single page, and canvases will
height) for example, that draws a filled rectangle, and properties for
1. var ctx=[Link]('2d');
1. [Link]='red';
1. [Link](0,0,80,100);
Complete example that draws a filled rectangle in red
Result:
Source code:
1. <!DOCTYPE html>
2. <html lang="en">
3. <head>
4. <style>
5. #myCanvas {
6. border: 1px solid black;
7. }
8. </style>
9. <script>
10. var canvas, ctx;
11.
12. function init() {
13. // This function is called after the page is loaded
14. // 1 - Get the canvas
15. canvas = [Link]('myCanvas');
16. // 2 - Get the context
17. ctx=[Link]('2d');
18. // 3 - we can draw
19. drawSomething();
20. }
21. function drawSomething() {
22. // draw a red rectangle
23. [Link]='#FF0000';
24. [Link](0,0,80,100);
25. }
26. </script>
27. </head>
28. <body onload="init();">
29. <canvas id="myCanvas" width="200" height="200">
30. Your browser does not support the canvas tag.
31. </canvas>
32. </body>
33. </html>
Explanation
Notice that we wrote an "init" function (line 12) that is called only when the
page has been entirely loaded (we say "when the DOM is ready"). There are
elements of the page before the page has been loaded entirely and before
when the JavaScript code is executed, the DOM has already been
constructed.
Before drawing or doing anything interesting with the canvas, we must first
get its drawing "context". The drawing context defines the drawing
Good practice is to get the canvas, the context, the width and height of the
After the context is set, we can draw, but first let's set the current
The example shows the use of the fillStyle property at line 27 - useful
for specifying the way shapes will be filled. In our case this line indicates
The context property named fillStyle is used here. This property can
The example says that all filled shapes will use the color "#FF0000",
which corresponds to a pure red color using the CSS RGB hexadecimal
1. [Link](0,0,80,100);
The way the rectangle will be filled depends on the current value of several
the fillStyle property. So, in our case, the rectangle will be red.
Summary of the different steps
content:
...fallback content...
</canvas>
API:
var canvas=[Link]('myCanvas');
var ctx=[Link]('2d');
[Link]='#FF0000';
[Link](0,0,80,100);
Drawing principles
More about the "context" object
Before we go on, we should take some time to clarify the way we draw on
HTML5 canvases. We already mentioned that we use a graphic context for all
the main operations. Whenever a shape, a text, or an image is drawn, the
current values of the different properties of the graphic context are taken into
account. Some are relevant only for certain kinds of shapes or drawing modes,
but you must be aware that it is always the current values of these drawing
properties that are used.
Later on we'll see that there are ways to save and restore this whole set of
values, but for now, let's examine in greater detail some of the properties and
methods we've already encountered, and introduce new ones.
The default value is the color black. Any kind of drawing in "fill mode" will use
the value of this property to determine how to render the "filled part" of the
drawing: any filled rectangle will be filled black by default, any filled circle will
be filled in black, and so on.
As long as we don't modify the value of this property, all drawing commands
for filled shapes will use the current value.
Note that we will study in detail how to use colors, gradients and patterns later,
but for now we introduce some properties and values so that you can
understand the principles of canvas drawing.
Extract from the source code (the part that draws the rectangle):
1. function drawSomething() {
2. // draw a red rectangle, line width=3 pixels
3. [Link]=3;
4. [Link]='red';
5. [Link](10,10,80,100);
6. }
Here, we used "stroke" instead of "fill" in the property and method names
(lines 4 and 5): strokeStyle instead of fillStyle, strokeRect(...) instead
of fillRect(...).
We also introduced a new property of the context, that applies only when
drawing in "stroke" mode, the lineWidth property (line 3), that is used for
setting the width of the shape outline. The value is in pixels.
1. function drawSomething() {
2. // set the global context values
3. [Link]=5;
4. [Link]='red';
5. [Link]='blue'
6. // font for all text drawing
7. [Link] = 'italic 20pt Calibri';
8. // Draw the two filled red rectangles
9. [Link](10, 30, 70, 150);
10. [Link](110, 30, 70, 150);
11. // Draw the two blue wireframe rectangles
12. [Link](10, 30, 70, 150);
13. [Link](110, 30, 70, 150);
14. // Draw a message above the rectangles
15. [Link]("hello", 70, 22);
16. }
This example shows the "global" nature of the context properties. Once you set
the filled color to red, any shapes you draw in filled mode will be red. This is
true for all the context properties. We set some of these properties in lines 3-7,
and all following calls to context methods for drawing rectangles or text will
depend on them. The two filled rectangles at lines 10-11 will be red, the two
wireframe rectangles drawn at lines 14-15 will be blue, etc.
Line 18 shows how to draw a text message at an X position of 70 and a Y
position of 22. The font is set at line 7 using the font property of the context.
The syntax is the same we use in CSS for using "system fonts".
If you would like to draw the filled text message in green, for example, you
should set the [Link] to "green" after you draw the
rectangles and before you draw the text (i.e just before line 18).
Let's start with some simple examples before looking at how we use 2D
transforms.
Let's draw three rectangles!
If we draw three rectangles of size 100x200 in a 400x400 canvas, one at (0, 0)
and another at (150, 0), and a third at (300, 0), here is the result and the
corresponding code:
JavaScript code extract (see the online example at JS Bin for the
complete running code)
1. function drawSomething() {
2. [Link]='lightgreen';
3.
4. [Link](0,0,100,200);
5. [Link](150,0,100,200);
6. [Link](300,0,100,200);
7. }
If you look at the code of the modified function, you will see that each call
to fillRect(...) uses the x and y parameters instead of hard coded values.
In this way, if we call it with parameters (0, 100), then all rectangles will be
drawn 100 pixels to the bottom (offset in y). Here is the result:
Ok, Now let's draw a small monster's head with
rectangles
Now we can start having some fun... let's draw a monster's head using only
rectangles (online version):
An extract of the JavaScript source code is:
1. function drawMonster(x, y) {
2. // head
3. [Link]='lightgreen';
4. [Link](x,y,200,200);
5. // eyes
6. [Link]='red';
7. [Link](x+35,y+30,20,20);
8. [Link](x+140,y+30,20,20);
9. // interior of eye
10. [Link]='yellow';
11. [Link](x+43,y+37,10,10);
12. [Link](x+143,y+37,10,10);
13. // Nose
14. [Link]='black';
15. [Link](x+90,y+70,20,80);
16. // Mouth
17. [Link]='purple';
18. [Link](x+60,y+165,80,20);
19. }
As you can see, the code uses the same technique, becomes less and less
readable. The Xs and Ys at the beginning of each call makes understanding the
code harder, etc.
Let's take a piece of code that draws something corresponding to the original
coordinate system, located at the top left corner of the canvas:
1. function drawMonster(x, y) {
2. // head
3. [Link]='lightgreen';
4. [Link](0,0,200,200);
5. // eyes
6. [Link]='red';
7. [Link](35,30,20,20);
8. [Link](140,30,20,20);
9. // interior of eye
10. [Link]='yellow';
11. [Link](43,37,10,10);
12. [Link](143,37,10,10);
13. // Nose
14. [Link]='black';
15. [Link](90,70,20,80);
16. // Mouth
17. [Link]='purple';
18. [Link](60,165,80,20);
19. // coordinate system at (0, 0)
20. drawArrow(ctx, 0, 0, 100, 0, 10, 'red');
21. drawArrow(ctx, 0, 0, 0, 100, 10, 'red');
22. }
This code is the just the same as in the previous example except that we
removed all Xs and Yx in the code. We also added at the end (lines 25-26) two
lines of code that draw the coordinate system. The drawArrow(startX,
startY, endX, endY, width, color) function is a utility function that we will
present later. You can see it in the source code of the complete online example
on JS Bin: look in the JavaScript tab.
Result:
1. [Link](100, 100);
2. drawMonster(0, 0);
Line 1 changes the position of the coordinate system, line 2 draws a monster in
the new translated coordinate system. All subsequent calls to drawing methods
will be affected and will work in this new system too.
And here is the code of the transformations we used, followed by the call to the
function that draws the monster:
1. [Link](100, 100);
2. [Link]([Link]/4);
3. [Link](0.5, 0.5);
4.
5. drawMonster(0, 0);
Line 1 does:
Line 2 does:
Line 3 does:
Line 4 draws the monster in this new translated, rotated, scaled coordinate
system:
BEWARE: all drawings to come will be in that
modified coordinate system!
If we draw two shapes at two different positions, they will be relative to this
new coordinate system.
1. [Link](100, 100);
2. [Link]([Link]/4);
3. [Link](0.5, 0.5);
4. // Draw the monster at (0, 0)
5. drawMonster(0, 0);
6. // Draw a filled rectagle at (250, 0)
7. [Link](250, 0, 100, 100);
Contexts saved will be stacked, the last one that has been saved will be
restored by the next call to restore(), so it is very important to have one
restore for each save.
We added parameters for setting the position and orientation of the monster,
and added calls to [Link](x, y) and [Link](angle) in the
function.
We added parameters for the head color and eye color.
We saved the context at the beginning of the function (BEST PRACTICE),
We restored it at the end (BEST PRACTICE).
Source code:
1. <!DOCTYPE HTML>
2. <html>
3. <head>
4. <title>Some rectangles drawn in immediate mode</title>
5. <style>
6. #myCanvas {
7. border: 1px solid #9C9898;
8. }
9. </style>
10. <script>
11. var canvas, ctx;
12.
13. [Link] = function () {
14. canvas = [Link]('myCanvas');
15. ctx = [Link]('2d');
16.
17. // black rectangle, default color (black)
18. [Link](10, 10, 100, 100);
19. // outlined rectangle, default color
20. [Link](150, 10, 100, 100);
21.
22. // outlined rectangle filled in red, outline blue
23. [Link] = 'red';
24. [Link] = 'lightBlue';
25. [Link] = 10;
26. [Link](100, 150, 150, 150);
27. [Link](100, 150, 150, 150);
28.
29. // A function that automatizes previous drawing
30. var angle = [Link] / 10;
31.
drawFilledRectangle(300, 150, 150, 150, 'pink', 'green', 10, angle);
32.
drawFilledRectangle(300, 150, 150, 150, 'yellow', 'purple', 10, angle +0.5);
33. };
34.
35. function drawFilledRectangle(x, y, w, h, fillColor, strokeColor, lw, ang
le) {
36. // GOOD PRACTICE: save if the function changes the context
37. // or coordinate
38. // system
39. [Link]();
40.
41. // position coordinate system
42. [Link](x, y);
43. [Link](angle);
44.
45. // set colors, line width...
46. [Link] = lw;
47. [Link] = fillColor;
48. [Link] = strokeColor;
49.
50. // draw at 0, 0 as we translated the coordinate
51. // system already
52. [Link](0, 0, w, h);
53. [Link](0, 0, w, h);
54.
55. // GOOD PRACTICE: a restore for a save!
56. [Link]();
57. }
58. </script>
59. </head>
60. <body>
61. <canvas id="myCanvas" width="578" height="400">
62. </canvas>
63. </body>
64. </html>
Drawing text
Introduction
The canvas API provides two main methods for drawing
text: [Link](message, x, y) and [Link](message, x, y).
It also provides a set of context properties for setting the character font and
style, for laying out the text, etc.
Typical use
Try this example online: [Link]
Examples:
[Link] = "60pt Calibri";
[Link] = "normal normal 20px Verdana";
[Link] = "normal 36px Arial";
[Link] = "italic bold 36px Arial";
There is a fourth optional parameter maxWidth that forces the text to fit into a
given width, distorting it if necessary:
1. ...
2. [Link] = "60pt Calibri";
3. [Link] = 3;
4. [Link] = "blue";
5. [Link] = "red";
6. [Link]("Hello World!", 10, 100);
7. [Link]("Hello World!", 10, 100);
8. // Draw text with constrained width of 250 pixels
9. [Link]("Hello World!", 10, 160, 250);
[Link]("Hello World!", 10, 160, 250);
11. // Constrain width to 150 pixels
[Link]("Hello World!", 10, 220, 150);
[Link]("Hello World!", 10, 220, 150);
The [Link]() method can be used to get the current width in pixels
of a given text, taking into account the diverse properties involved such as
font, size, shadow, lineWidth, etc.
The textBaseline property of the context is used to specify the different ways
one can position the baseline of a given text. The example above shows the
different possible values for this property and the corresponding results. The
default value is "alphabetic" and corresponds to what has been used in the
previous "Hello World" example.
Possible values:
The text is aligned based on the top of the tallest glyph in the text.
top
The text is aligned based on the line the text seems to hang from. This is almost identical
hanging to top, and in many cases, you cannot see the difference.
The text is aligned according to the middle of the text.
middle
The bottom of vertically oriented glyphs, e.g. western alphabet like the latin.
alphabetic
The text is aligned based on the bottom of the glyph in the text, that extends
bottom furthest down in the text.
1. [Link] = "top";
2. [Link]("top", 0, 75);
3. [Link] = "hanging";
4. [Link]("hanging", 40, 75);
5. [Link] = "middle";
6. [Link]("middle", 120, 75);
1. [Link] = "center";
2. [Link]("center", 250, 20);
3. [Link] = "start";
4. [Link]("start", 250, 40);
5. [Link] = "end";
6. [Link]("end", 250, 60);
7. [Link] = "left";
8. [Link]("left", 250, 80);
9. [Link] = "right";
10. [Link]("right", 250, 100);
Drawing images
Introduction
Load images in the background, wait for them to be loaded
before drawing!
Working with images is rather simple, except that we need the images to be
fully loaded into memory before drawing them. Loading images is
an asynchronous process we need to take care of. Working with multiple
images might also be difficult for beginners. Later on in this course, we will
present a multiple image loader.
Source code:
1. <!DOCTYPE HTML>
2. <html>
3. <head>
4. <script>
5. [Link] = function() {
6. // It is necessary to wait for the web page to load before running this code.
7. var canvas = [Link]("myCanvas");
8. var context = [Link]("2d");
9. var imageObj = new Image();
10. // Callback function called by the [Link] = .... line
11. //located after this function
12. [Link] = function() {
13. // Draw the image only when we have the guarantee
14. // that it has been loaded
15. [Link](imageObj, 0, 0);
16. };
17.
18. // Calls the [Link] function asynchronously
19. [Link] =
20. "[Link]
21. };
22. </script>
23. </head>
24. <body>
25. <canvas id="myCanvas" width="512" height="512"></canvas>
26. </body>
27. </html>
WRONG => indeed, you could try drawing it using some code like this:
1. <body>
2. <canvas id="myCanvas" width="512" height="512"></canvas>
3. <p>Original image as an <img> element:</p>
4. <img id="logo"
5. src="[Link]
texture_85_by_voyager168-[Link]">
6. <script>
7. canvas = [Link]("myCanvas");
8. var ctx = [Link]("2d");
9. var logo = [Link]("#logo");
10. [Link](logo, 0, 0, 100, 100);
11. </script>
12. </body>
Although you will find many examples on the Web that do it this way, they will
only work most of the time with small images, or with images that are in the
browser's cache. Remember that you cannot draw an image that has not
been fully loaded!
If you try to draw an image that is not loaded or partially loaded, you will have
unexpected results!
Best practice: only draw an image that is fully loaded, use
the onload callback!
GOOD => the right way to do this is shown in this
example: [Link] that starts drawing only from
the onload callback function:
1. <!DOCTYPE HTML>
2. <html>
3. <head>
4. <script>
5. var canvas, context;
6. [Link] = function() {
7. canvas = [Link]("myCanvas");
8. context = [Link]("2d");
9.
10. draw();
11. };
12. function draw() {
13. var imageObj = [Link]("#logo");
14. [Link]("image is already loaded, we draw it!");
15. [Link](imageObj, 0, 10, 100, 100);
16. }
17. </script>
18. </head>
19. <body>
20. <canvas id="myCanvas" width="512" height="512"></canvas>
21. </p>
22.<img id="logo" src="[Link]
HTML5_Logo_512.png">
23. </body>
24. </html>
With large image files, this will not break nor produce unexpected
results: [Link]
1. <script>
2. var video;
3. var canvas, ctx;
4. var angle = 0;
5.
6. function init() {
7. video = [Link]('sourcevid');
8. canvas = [Link]('myCanvas');
9. ctx = [Link]('2d');
10.
11. setInterval("processFrame()", 25); // call processFrame each 25ms
12. }
13.
14. function processFrame() {
15. [Link](video, 0, 0, 320, 180);
16. drawRotatingVideo(480, 90);
17. [Link](video, 0, 180, 320, 180);
Line 11: the call to setInterval will make the browser execute
the processFrame function each 25ms.
Lines 15, 17 and 18: in processFrame, drawImage(...) is called 3 times with
the video element passed as first parameter.
Line 43: the video element declared at line 43
has autoplay=true and loop=true, it starts playing the video as soon as
possible and will loop it.
Line 21: We implemented a rotating video effect in
the drawRotatingVideo. The use of context save/restore is primordial as this
function changes the coordinate system at each call, translating and rotating it.
Notice the extra translation at line 31 that translates the coordinate system
backwards with half of the size of the image that is drawn. We did this in order
to make the image rotate around the center of the rectangle, instead of around
the top left corner at (0, 0) by default. Try commenting out this line in the
running example and you will see what we mean.
Lines 12-18 draw 1000 rectangles of random sizes in immediate mode. We also
measure the time using the
usual [Link](name_of_timer) and [Link](name_of_timer)
that will write in the browser console the time elapsed. Note
that [Link](...) and [Link](...) display results only in
the browser's console, not in the JS Bin console.
Path drawing mode allows parallelism: if you need to draw 10,000 rectangles,
it's better to store the orders in the graphics card, then execute the drawing all
at once, rather than doing 10,000 immediate calls to strokeRect(...) for
example. With the buffered mode, the Graphic Processing Unit (GPU) of the
graphics card hardware will be able to parallelize the computations (modern
graphics cards can execute hundreds/thousands of things in parallel).
Same example as before, this time using the buffered mode for drawing
rectangles: [Link]
Extract from source code (the part that draws the rectangles):
The call to [Link]() (line 9) or to its sister method [Link]() will draw
the entire buffer contents in fill or stroke mode.
And here is what the timer gives: a slightly faster execution time. Changing
1000 to 100,000 will give even larger differences.
Also, do not forget to use the cheatsheet provided at the beginning of the
course. You will find it very helpful when you start playing with the canvas.
Now let's go a bit further by introducing the notion of "path drawing". This
approach uses the [Link](x, y) method of the context, in conjunction
with other drawing methods that end in "To", such as [Link](x, y).
[Link] the "pencil" somewhere with a call to [Link](x1, y1). This will be
the origin of the first line.
[Link] the [Link](x2, y2) method to draw a line from the previous
position (previous step) to the position passed as parameters to
the lineTo(...) method. This position will serve as the origin for the next line
to be drawn.
[Link] lineTo(x3, y3) again to draw a line that goes from (x2, y2) to (x3, y3).
This line will start at the end of the previous one.
[Link] step 3 to draw more connected lines.
[Link] the [Link]() or the [Link]() methods to draw the path defined
by the different lines.
Note the call to [Link]() or [Link]() will use the current values of
the strokeStyle or fillStyleproperties. It is possible to call [Link](x,
y) in the middle of steps 1 through 5 in order to move the pen somewhere else
without connecting to the last drawn line.
1. var canvas=[Link]('myCanvas');
2. var ctx=[Link]('2d');
3. // Vertical lines
4. for (var x = 0.5; x < 500; x += 10) {
5. [Link](x, 0);
6. [Link](x, 375);
7. }
8. // Horizontal lines
9. for (var y = 0.5; y < 375; y += 10) {
10. [Link](0, y);
11. [Link](500, y);
12. }
13.
14. // Draw in blue
15. [Link] = "#0000FF";
16.
17. // Until the execution of the next line, nothing has been drawn!
18. [Link]();
In this example, the entire grid is drawn during the execution of the last line of
code, with the single call to [Link]().
1. var canvas=[Link]('myCanvas');
2. var ctx=[Link]('2d');
3. // a filled rectangle in immediate mode
4. [Link]='#FF0000';
5. [Link](0,0,80,100);
6. // two consecutive lines in path mode
7. [Link](0,0);
8. [Link](100, 100);
9. [Link](100,0);
10. // draws only the two lines in wireframe mode
11. [Link] = "#0000FF";
12. [Link]();
This example shows that filled and wireframe shapes should be drawn
differently (here a filled rectangle is drawn using a call to
the fillRect(...) method while a wireframe set of connected lines is drawn
using the stroke() method of the context).
1. var canvas=[Link]('myCanvas');
2. var ctx=[Link]('2d');
3. // first part of the path
4. [Link](20,20);
5. [Link](100, 100);
6. [Link](100,0);
7. // second part of the path, moveTo(...) is used to "jump" to another place
8. [Link](120,20);
9. [Link](200, 100);
10. [Link](200,0);
11. // indicate stroke color + draw the path
12. [Link] = "#0000FF";
13. [Link]();
In this example, we simply called the moveTo() method between each part of
the path. And we called stroke() only once to draw the whole path.
Drawing lines with different styles
Common mistake: drawing the same path twice
Let's look at the drawing from the last example of the previous section:
Imagine that we would like to draw them with different styles and colors: the
shape on the left will stay as it is now (blue, wireframe), while the shape on the
right will be filled, colored in pink. Let's look at how we can do this...
What we will try first is to call stroke() after the first half of the path, then
call fill() after the second half of the path (check this interactive example):
Hey - it does not work! Weirdly, the two parts of the path are filled in pink! But
we called stroke() after the first half of the path was drawn (lines 5-8). Then
we called fill() only after the second part of the path was specified (lines 14-
19)... so, what happened?
[Link] call to stroke() has drawn the path corresponding to the lines 5-7.
Indeed, the first part of the path (on the left) has actually been drawn once in
wireframe mode, and in blue.
[Link], the call to fill() at line 20 has drawn the whole path again, but in
pink and in filled mode. But this time the path corresponds to lines 5-7 plus
lines 14-16 that make up the second shape on the right. So the path that has
been drawn this time is made of both of the triangles.
Important: If you do not want to draw parts of the same path several times,
you need to draw two different paths, using the [Link]() method, as
shown in the next example.
Now, the right way!
Online example: [Link]
Source code:
1. var canvas=[Link]('myCanvas');
2. var ctx=[Link]('2d');
3. // first part of the path
4. [Link](20,20);
5. [Link](100, 100);
6. [Link](100,0);
7. // indicate stroke color + draw first part of the path
8. [Link] = "#0000FF";
9. [Link]();
10.// start a new path, empty the current buffer
[Link]();
12. // second part of the path
13. [Link](120,20);
14. [Link](200, 100);
15. [Link](200,0);
16. // indicate stroke color + draw the path
17. [Link] = "pink";
18. [Link]();
This time, in order to draw the two shapes differently, we defined two separate
paths. The way to do this is just to call [Link]() to start a new path. In
this example, the first path has been drawn in wireframe mode, then a new
path has been started that is drawn in filled mode.
Drawing lines in immediate mode
Sometimes it might be useful to draw just one line without being in another
path.
It's interesting to see how we can write a single "draw line" function that takes
the start and end coordinates, the color, the line width, etc.
Line 13 starts a new path so that the function will only draw what it is meant
to draw: a single line.
Lines 15-17 move the "pen" at (x1, y1) then draw a line to (x2, y2), and the
stroke at line 17 makes it appear on the screen.
You may find multiple implementations on the Web for drawing arrows in a
canvas, but the one we are presenting has the advantage of being rather
simple and enables you to set the color and line width of the arrows.
An arrow is made of one line (the arrow body) and three connected lines (the
arrow head).
Examples
Online example that uses the above code: [Link]
1. drawArrow(ctx, 10, 10, 100, 100, 10, 'red');
2. drawArrow(ctx, 100, 10, 140, 140, 3, 'black');
Result:
Draw nicer arrows?
On the Web, you will find many different ways to draw arrows.
Closing a path
The [Link]() method indicates that we would like a closed path: draw
from the last point to the first.
1. var canvas=[Link]('myCanvas');
2. var ctx=[Link]('2d');
3. // Path made of three points (defines two lines)
4. [Link](20,20);
5. [Link](100, 100);
6. [Link](100,0);
7. // Close the path, try commenting this line
8. [Link]();
9. // indicate stroke color + draw first part of the path
10. [Link] = "blue";
11. [Link]();
Try commenting the line in the online example and see the results!
Typical usage
Typical usage for drawing an arc/circle/ellipse is:
1. [Link](centerX, centerY, radius, startAngle, endAngle); // clockwise
drawing
2. [Link](centerX, centerY, radius, startAngle, endAngle, false);
The angles are in radians (between 0 and 2*[Link]). The arc is drawn
clockwise. Beware that this may not seem natural if you're used to the
trigonometric order.
The last parameter is optional and has a value of false by default. If true,
instead of drawing an arc of circle that corresponds to the parameters, it will
draw its complementary. See the examples below to see the difference.
If we change the last parameter (we omitted it, so it took a value of false by
default):
1. [Link]();
2. // we omitted the last parameter
3. [Link](100, 75, 50, 0, [Link]/2, true);
4.
5. [Link] = 10;
6. [Link]();
Source code:
Proposed projectS
Project 1 - modify the previous example
on [Link] in order to get:
Typical use
1. [Link](x0, y0);
2. [Link](x1, y1, x2, y2, radius);
This method can be confusing. It was defined mainly for drawing rounded
shapes like rounded rectangles. We used an excerpt here from the excellent
tutorial on the arcTo(...) method available at [Link]
[Link]/tutorials/canvas/[Link].
1. [Link]();
2. [Link](0, 20);
3. [Link](100, 100, 200, 20, 50);
4. [Link] = 5;
5. [Link] = "#0000ff";
6. [Link]();
Source code:
1. var roundedRect=function(ctx,x,y,width,height,radius,fill,stroke) {
2. [Link]();
3. // draw top and top right corner
4. [Link](x+radius,y);
5. [Link](x+width,y,x+width,y+radius,radius);
6. // draw right side and bottom right corner
7. [Link](x+width,y+height,x+width-radius,y+height,radius);
8. // draw bottom and bottom left corner
9. [Link](x,y+height,x,y+height-radius,radius);
10. // draw left and top left corner
11. [Link](x,y,x+radius,y,radius);
12. if(fill) {
13. [Link]();
14. }
15. if(stroke){
16. [Link]();
17. }
18. }
19. var canvas = [Link]('myCanvas');
20. var ctx = [Link]('2d');
21. [Link] = 'rgb(150,0,0)';
22. [Link] = 'rgb(0,150,0)';
23. [Link] = 7;
24. roundedRect(ctx, 15, 15, 160, 120, 20, true, true);
In this example, each call to [Link](...) draws a side plus a corner. This
makes us suspect that the arcTo() method has been designed primarily for
drawing rounded rectangles...
JS Bin example
Example 4: use the unrounded vertices in arcTo
For drawing a rounded square, this code also works:
1. [Link](x+radius, y);
2. [Link](x+width, y,x+width, y+height, radius);
3. [Link](x+width, y+height, x, y+height, radius);
4. [Link](x, y+height, x, y,radius);
5. [Link](x, y, x+width, y,radius);
which might be easier than trying to figure out where the arc will end like this:
1. [Link](x+radius, y);
2. [Link](x+width, y, x+width, y+radius, radius);
3. [Link](x+width, y+height, x+width-radius, y+height,radius);
4. [Link](x, y+height, x, y+height-radius, radius);
5. [Link](x, y, x+radius, y,radius);
This could be particularly helpful if you are dealing with something other than a
rectangle, like this rounded triangle (try the code at JsBin):
Quadratic curves
Introduction
Quadratic curves are defined by a starting point (called a "context point"), a
control point, and an ending point. The curve fits the tangents between the
context and control points and between the control and ending points.
The context point may be defined by a call to the moveTo(x, y) method of the
context, or it may be the ending point of a previous path, if we're drawing a
path made of several shapes. For example, drawing a line and a quadratic
curve will make the endpoint of the line the context point for the quadratic
curve.
The control point controls the curvature - if we move the control point farther
we get a sharper curve.
Typical use
1. [Link](contextX, contextY);
2. [Link](controlX, controlY, endX, endY);
3. // Optional : set lineWidth and stroke color
4. [Link] = 5;
5. [Link] = "#0000ff";
6. // Draw!
7. [Link]();
Source code:
1. var canvas=[Link]('#myCanvas1');
2. var context=[Link]('2d');
3.
4. [Link]();
5.
6. [Link](100, 20);
7. [Link](230, 200, 250, 20);
8.
9. [Link] = 5;
10. [Link] = "#0000ff";
11. [Link]();
We set a starting point in line 6: moveTo(...), then set the control and ending
points with a call to quadraticCurve(...), at line 7, then set some properties
for color, thickness, and finally we call the stroke() method for drawing the
curve.
1. [Link]();
2. [Link](100, 20);
3. [Link](200, 80);
4. [Link](230, 200, 250, 20);
5. [Link](500, 90);
6. [Link] = 5;
7. [Link] = "#0000ff";
8. [Link]();
We propose a useful function for drawing curved arrows. The code is a modified
version of one that has been proposed by several contributors to this thread at
StackOverflow.
Source code of the function that draws a curved arrow:
This function takes as parameters the start and end points, the control point of
the curve, the arrow width, the width of the arrow head.
It computes the angle of the arrow at its endpoint (line 14) in order to compute
the rotated endpoints of the two lines of the arrow head (lines 24 and 29).
Notice that once again, as we modify the context properties (color, lineWidth)
in the body of the function, we save and restore the context at the beginning /
end of the function.
Bezier curves
Introduction
Bezier curves are interesting - used mostly for drawing "S" shapes or
asymmetric curves.
(Picture from : [Link]
bezier-curves/)
Bezier curves are defined by a context point, like quadratic curves, two control
points that define two tangents, and an ending point.
The first part of the curve is tangential to the imaginary line defined by the
context point and the first control point. The second part of the curve is
tangential to the imaginary line defined by the second control point and the
ending point.
The best way to understand how they work is to check out one of these
interactive applications:
[Link]
[Link]
[Link]
Nice video tutorial: [Link]
1. [Link]();
2. [Link](100, 20);
3. [Link](290, -40, 200, 200, 400, 100);
4. [Link] = 5;
5. [Link] = "#0000ff";
6. [Link]();
1. [Link]();
2. [Link](100, 20);
3. [Link](200, 160);
4. [Link](230, 200, 250, 120);
5. [Link](290, -40, 300, 200, 400, 150);
6. [Link](500, 90);
7. // TRY COMMENTING THIS LINE OUT
8. [Link]();
9. [Link] = 5;
10. [Link] = "#0000ff";
11. [Link]();
In this example we use the closePath() method to draw a line between the
last path point and the first path point (line 11), so that the drawing looks like a
pair of goggles.
Note how the different parts are linked together and make a "path":
Screenshot:
Canvas context: colors
Introduction
In previous examples, we saw how to set the current color using
the strokeStyle and fillStyle properties of the canvas context object.
We will now look at color in a little more detail, and see how we can use
gradients or patterns/textures/images (in other words: fill shapes or fill the
outline of the shapes with some images that repeat themselves).
Note that:
Here is an example that shows how to draw different filled rectangles in blue,
with different levels of transparency.
Linear gradients
It is possible to define the stroke or the fill style as a "gradient", a set of
interpolated colors, like in this example below (try it online
at: [Link]
The concept of linear gradient is seen as an "invisible" rectangle in which a set
of colors are interpolated along a line.
The gradient becomes visible when we draw shapes on top of the invisible
gradient, and when the fillStyleor strokeStyle property has for value this
gradient.
... where the (x0, y0) and (x1, y1) parameters define "the direction of the
gradient" (as a vector with a starting and an ending point). This direction is an
invisible line along which the colors that compose the gradient will be
interpolated.
This line defines the direction of the gradient: a virtual, invisible line that goes
from the top left corner of the canvas (0, 0) to the top right corner of the
canvas (300, 0). The interpolated colors will propagate along this line.
1. [Link](0, "blue");
2. [Link](0.5, "white");
3. [Link](1, "red");
In our example, the gradient corresponds to an invisible rectangle that fills the
canvas. If we draw a rectangle of the canvas size, it should be filled with the
entire gradient:
1. [Link] = grdFrenchFlag;
2. [Link](0, 0, 300, 200);
The result is shown below: a big rectangle that fills the whole canvas, with
colors going from blue (left) to white (middle) to red (right).
Changing the direction of the gradient
If you modify the source code that defines the direction of the gradient as
follows...
1. grdFrenchFlag = [Link](0, 0, 300, 200);
... then you will define a gradient that goes from the top left corner of the
canvas to the bottom right of the canvas. Let's see what it does (online version
here: [Link]
1. [Link] = grdFrenchFlag;
2. [Link](0, 0, 50, 50);
3. [Link](100, 0, 50, 50);
4. [Link](200, 0, 50, 50);
5. [Link](50, 50, 50, 50);
6. [Link](150, 50, 50, 50);
7. [Link](250, 50, 50, 50);
8. [Link](0, 100, 50, 50);
9. [Link](100, 100, 50, 50);
10. [Link](200, 100, 50, 50);
11. [Link](50, 150, 50, 50);
12. [Link](150, 150, 50, 50);
13. [Link](250, 150, 50, 50);
This code is rather ugly isn't it? It would have been better to use a loop...
This code is much more complex than the previous one, taking 16 lines instead
of 13, but is much more powerful. Try to call the function with a value of 10,
20, or 2...
1. function drawCheckboard(n) {
2. [Link] = grdFrenchFlag;
3. [Link]=10;
4. ...
5. for(i = 0; i < n; i++) {
6. for(j = i % 2; j < n; j++) {
7. [Link](cellWidth*i, cellHeight*j, cellWidth, cellHeight);
8. }
9. }
10. }
Like in the first example we will draw a filled rectangle that is the same size as
the canvas. Here is the online version: [Link] and here
is a screenshot of the result:
We notice that "before" the gradient starts, the first color of the gradient is
repeated without any interpolation (columns 0-100 are all blue), then we "see
through" and the gradient is drawn (columns 100-200), then the last color of
the gradient is repeated without any interpolation (columns 200-300 are red).
The red color is beyond the bottom right corner.... we see only the top left
quarter of the gradient.
It suffices to create a new gradient before drawing each filled rectangle, and
set it with the starting and ending point of its direction/virtual line accordingly
to the rectangle coordinates. Here is an online example and the resulting
display:
Extract from source code:
We slightly modified the examples of this chapter so that the flag looks more
like the French flag. Look at the modified versions below, and try to find out
what has changed in the gradient definitions:
[Link]
[Link]
[Link]
[Link]
[Link]
[Link]
[Link]
Radial gradients
Basic principle / syntax: define two circles at
gradient creation
Radial gradients are for creating gradients that propagate/interpolate colors
along circles instead of propagating/interpolating along a virtual line, like linear
gradients.
Here is an example of a radial gradient that interpolates the color of the
rainbow. Online version: [Link]
In the above example, the gradients starts at a circle located at (150, 100),
with a radius of 30, and propagates to a circle with the same center as the first
(150, 100), but with a bigger radius of 100, as shown below:
We added color stops using a method similar to that used for linear gradients.
We call the "first color" the color defined for the inner circle, the "last color" the
last color of the gradient, that corresponds to the outer circle:
The color inside the first circle will be the first color. In our example above,
the first color is red: and the small circle of the gradient in our example is filled
in red!
The color outside the outer circle will be the last color of the gradient - which
is not interpolated. The last color in our example is purple, and it fills the rest of
the filled rectangle area "after" the external circle of the gradient.
The colors between the two circles will be interpolated.
[Link] = function(){
2....
3.}
[Link] the source of this image to the URL of the pattern (in our example
with url of the pattern),
[Link] = "[Link]
[Link] soon as step 3 is executed, an HTTP request is sent in background by the
browser, and when the image is loaded in memory, the callback defined at step
2 is called. We create a pattern object inside, from the loaded image:
1.// callback called asynchronously, after the src attribute of imageObj is set
[Link] = function(){
3. // We enter here when the image is loaded, we create a pattern object.
4. // It is good practice to set this as a global variable, easier to share
5. pattern1 = [Link](imageObj, "repeat");
6.};
[Link] the callback function (or inside a function called from inside
the callback) we can draw.
1.// callback called asynchronously, after the src attribute of imageObj is set
[Link] = function(){
3. pattern1 = [Link](imageObj, "repeat");
4. // Draw a textured rectangle
5. [Link] = pattern1;
6. [Link](10, 10, 500, 800);
7.};
Here we have two rectangles drawn using a pattern (an image that can be
repeated along the X and Y axis). The first is a filled rectangle while the second
is "stroked" with a lineWidth of 10 pixels.
1. <!DOCTYPE html>
2. <html>
3. <body onload="init();">
4. <canvas id="myCanvas" width="500" height="400">
5. Your browser does not support the canvas tag. </canvas>
6. </body>
7. </html>
When all images have been loaded, we call a callback function that has been
passed to our loader.
A complete example code that produces the result shown at the beginning of
this page is at: [Link]
We first count the number of images to load (lines 7-9), then for each image to
be loaded we create a new JavaScript image object (line 12) and set its src
attribute (line 19) - this will start to load the image.
When an image comes in, the onload callback is called (line 14) and inside, we
increment the number of images loaded (line 15) and test if this number is >=
the total number of images that should be loaded. If this is the case, the
callback function is called (line 16).
1. function drawRectanglesWithPatterns() {
2. [Link]=patternFloor;
3. [Link](0,0,200,200);
4. [Link]=patternLion;
5. [Link](200,0,200,200);
6. [Link]=patternFlowers;
7. [Link](0,200,200,200);
8.
9. [Link]=patternBW;
10. [Link](200,200,200,200);
11. }
Drawing shadows
Context properties to draw with shadows
There are 4 properties of the canvas context that are useful for indicating that
we want to draw shapes with shadows:
[Link]: color to use for shadows,
[Link]: blur level for shadows,
[Link]: horizontal distance of the shadow from the shape,
[Link]: vertical distance of the shadow from the shape
Example 1: Simple
Online example: [Link]
1. <!DOCTYPE html>
2. <html>
3. <body onload = init();>
4. <canvas id="myCanvas" width="400" height =800>
5. Your browser does not support the canvas tag.
6. </canvas>
7. </body>
8. </html>
1. ...
2. [Link]();
3. // Add to the path a full circle (from 0 to 2PI)
4. [Link](centerX, centerY, radius, 0, 2*[Link], false);
5. // With path drawing you can change the context
6. // properties until a call to stroke() or fill() is performed
7. [Link] = "lightBlue";
8. // add shadows before drawing the filled circle
9. addShadows();
10. // Draws the filled circle in light blue
11. [Link]();
12. // Prepare for the outline
13. [Link] = 5;
14. [Link] = "black";
15. // draws the path AGAIN (the circle), this
16. // time in wireframe
17. [Link]();
18. // Notice we only once called [Link]()! And drew it twice
19. // with different styles
20. ...
21.
[Link] addShadows() {
23. [Link] = "Grey"; // color
24. [Link] = 20; // blur level
25. [Link] = 15; // horizontal offset
26. [Link] = 15; // vertical offset
27. }
The trick is to save the context before setting the shadow properties, then draw
the filled circle, then restore the context (to its previous state: without
shadows), then draw the outlined circle by calling [Link]().
1. ...
2. // save the context before setting shadows and drawing the filled
circle
3. [Link]();
4. // With path drawing you can change the context
5. // properties until a call to stroke() or fill() is performed
6. [Link] = "lightBlue";
7. // add shadows before drawing the filled circle
8. addShadows();
9. // Draws the filled circle in light blue
10. [Link]();
11.// restore the context to its previous saved state
12. [Link]();
13. ...
They apply to all shapes that are drawn in path mode (lines, curves, arcs) and
some also apply to rectangles.
Source code:
1. <!DOCTYPE html>
2. <html>
3. <head>
4. <title>A simple example of lineWidth property use</title>
5. </head>
6. <body>
7. <canvas id="myCanvas" width="500">
8. Your browser does not support the canvas tag.
9. </canvas>
10. <script>
11. var canvas = [Link]('myCanvas');
12. var ctx = [Link]('2d');
13.
14. // first path
15. [Link](20, 20);
16. [Link](100, 100);
17. [Link](100, 0);
18.
19.
20. // second part of the path
21. [Link](120, 20);
22. [Link](200, 100);
23. [Link](200, 0);
24.
25. // indicate stroke color + draw first part of the path
26. [Link] = "#0000FF";
27. // Current line thickness is 20 pixels
[Link] = 20;
29. [Link](); // draws the whole path at once
30.
31. // Draws a rectangle in immediate mode
32. [Link](230, 10, 100, 100);
33. </script>
34.
35. </body>
36. </html>
Line style: changing the end caps for a line
The lineCap property of the context indicates the way line end caps are
rendered. Possible values are butt(default), round, square (from top to bottom
in the next illustration). Note that a value of "round" or "square" makes the
lines slightly longer than the default value "butt".
1. <!DOCTYPE html>
2. <html>
3. <head>
4. <title>A simple example of lineCap property use</title>
5. </head>
6. <body>
7.
8. <canvas id="myCanvas" width="500">
9. Your browser does not support the canvas tag.</canvas>
10. <script>
11. var canvas = [Link]('myCanvas');
12. var ctx = [Link]('2d');
13.
14. // first path
15. [Link](20, 20);
16. [Link](100, 100);
17. [Link](100, 30);
18.
19. // second part of the path
20. [Link](120, 20);
21. [Link](200, 100);
22. [Link](200, 30);
23.
24. // indicate stroke color + draw first part of the path
25. [Link] = "#0000FF";
26. // Current line thickness is 20 pixels
27. [Link] = 20;
28.
29.// Try different values: butt, square, round
[Link] = "round";
31.
32. [Link]();
33. // Draws a rectangle
34. [Link](230, 10, 100, 100);
35. </script>
36.
37. </body>
38. </html>
Note that in this example, the rectangle is not affected. It has no line ends
visible - all its sides meet. However, the next property we're going to look at
will have an effect on rectangles!
1. <!DOCTYPE html>
2. <html>
3. <head>
4. <title>A simple example of lineJoin property use</title>
5. </head>
6. <body>
7.
8. <canvas id="myCanvas" width="500">Your browser does not support
the canvas tag.</canvas>
9.
10. <script>
11. var canvas = [Link]('myCanvas');
12. var ctx = [Link]('2d');
13. // first path
14. [Link](20, 20);
15. [Link](100, 100);
16. [Link](100, 30);
17.
18. // second part of the path
19. [Link](120, 20);
20. [Link](200, 100);
21. [Link](200, 30);
22.
23. // indicate stroke color + draw first part of the path
24. [Link] = "#0000FF";
25. // Current line thickness is 20 pixels
26. [Link] = 20;
27.// Try different values : miter(default), bevel, round
[Link] = "round";
29. [Link]();
30. // Draws a rectangle
31. [Link](230, 10, 100, 100);
32. </script>
33.
34. </body>
35. </html>
In order to avoid this situation, we can set the miterLimit property of the
context to a threshold value. If the miter length exceeds the miterLimit value,
then the corner will be rendered as if the lineJoin property had been set to
"bevel" and the corner will be "cut".
In the example, try different values for the miterLimit property. You'll see that
the way the corners are rendered changes at values around 2 and 3.
Source code:
1. <!DOCTYPE html>
2. <html>
3. <head>
4. <title>A simple example of miterLimit property use</title>
5. </head>
6. <body>
7.
8. <canvas id="myCanvas" width="500">Your browser does not support
the canvas tag.</canvas>
9.
10. <script>
11. var canvas = [Link]('myCanvas');
12. var ctx = [Link]('2d');
13. // first path
14. [Link](20, 20);
15. [Link](100, 100);
16. [Link](100, 30);
17.
18. // second part of the path
19. [Link](120, 20);
20. [Link](200, 100);
21. [Link](200, 30);
22.
23. // indicate stroke color + draw first part of the path
24. [Link] = "#0000FF";
25. // Current line thickness is 20 pixels
26. [Link] = 20;
27. // Try different values : miter(default), bevel, round
[Link] = "miter";
29.// try to change this value, try 2, 3, 4, 5 et...
[Link] = 1;
31. [Link]();
32.
33. // Draws a rectangle
34. [Link](230, 10, 100, 100);
35. </script>
36. </body>
37. </html>
Week 4
PRINCIPLES OF ANIMATION
In order to perform an animation, we need to:
[Link] the content of the canvas: this can be done using
the [Link](0, 0, canvasWidth, canvasHeight) method;
[Link] some shapes: use any of the drawing methods we have seen so far;
[Link] the shapes: modify the position and/or orientation, size and color of the
shapes;
[Link] (go to step 1).
These are the basic steps for animating objects in a canvas. The order of the
steps can be changed (i.e. you can move the shapes before drawing them),
but, the principle is the same: clear-draw-move-repeat. Step 1 could be
avoided if you redraw the whole canvas content during step 2.
BEFORE HTML5
Even before HTML5 and the introduction of the canvas element, people created
HTML games. They used CSS backgrounds inside <div> elements, and used to
change the CSS top, left, width and height properties of the divs to
animate graphic images on the screen.
During the late 1990s and early 2000s, JavaScript became increasingly popular.
The community created a first 'umbrella term' describing a collection of
technologies used together to create interactive and animated Web sites
- DHTML (Dynamic HTML). For example, check the games developed at this
time by Brent Silby (they all use DHTML).
For animation,
the setInterval(function,
ms) and setTimeout(function,
ms) methods were the only
solutions. Both methods take a function
as the first parameter, and a number of
milliseconds as the second parameter.
AFTER HTML5
The methods described above are now completed by a new method that
comes with multiple advantages: the requestAnimationFrame API.
We will compare the old methods with the new one, and implement the same
example with each of them to highlight the differences.
1. <body>
2. <div id="animatedDIV">Animated DIV :-)</div>
3. <button onclick="start()">Start animation</button>
4. <button onclick="stop()">Stop animation</button>
5. <script>
6. var elm = [Link]("animatedDIV");
7. var requestId;
8. var x = 0;
9. function render(time) {
10. [Link] = x++ + "px";
11. }
12. function start() {
13. requestId = setInterval(render, 10);
14. }
15. function stop() {
16. if (requestId) {
17. clearInterval(requestId);
18. }
19. }
20. </script>
21. </body>
Here, we define a <div> element, (see the online source code for the CSS
properties involved), and we use the setInterval method (line 17) to call
every 10ms the render() method that will just increment the position of this
element. Notice that since we're using the DOM, the horizontal position of the
div is modified by changing its left CSS property.
1. <body onload="init();">
2. <canvas id="myCanvas" width="400" height="400">
3. Your browser does not support the canvas tag.
4. </canvas>
5. <p>
6. <button onclick="start()">Start animation</button>
7. <button onclick="stop()">Stop animation</button>
8. <script>
9. var canvas, ctx;
10. var monsterX=100, monsterY=100, monsterAngle=0;
11. function init() {
12. // This function is called after the page is loaded
13. // 1 - Get the canvas
14. canvas = [Link]('myCanvas');
15. // 2 - Get the context
16. ctx=[Link]('2d');
17. }
18. function animationLoop() {
19. // 1 - Clear the canvas
20. [Link](0, 0, [Link], [Link]);
21. // 2 Draw the monster using variables for pos, angle, etc.
22.
drawMonster(monsterX, monsterY, monsterAngle, 'green', 'yellow');
23. // 3 Move the monster (change pos, angle, size, etc.)
24. monsterX += 10;
25. monsterX %= [Link]
26. monsterAngle+= 0.01;
27. }
28. function drawMonster(x, y, angle, headColor, eyeColor) {
29. // BEST PRACTICE: SAVE CONTEXT AND RESTORE IT AT THE END
30. [Link]();
31. // Moves the coordinate system so that the monster is drawn
32. // at position (x, y)
33. [Link](x, y);
34. [Link](angle)
35. // head
36. [Link]=headColor;
37. [Link](0,0,200,200);
38. ...
39. // BEST PRACTICE!
40. [Link]();
41. }
42. function start() {
43. // Start the animation loop, change 20 for bigger values
44. requestId = setInterval(animationLoop, 20);
45. }
46. function stop() {
47. if (requestId) {
48. clearInterval(requestId);
49. }
50. }
51. </script>
52. </body>
Lines 52-61: The code for launching and stopping the animation is similar to
that from the previous example.
Lines 34-50: The code that draws the monster is that which we saw earlier
when we presented the 2D transformations. Best practice is to save and
restore the context at the beginning and end of each function that changes the
context.
Lines 21-32: The most interesting part is the animation loop that
implements the basic animation steps: clear-draw-move. In order to make a
shape "movable", we use some "state variables" for its position and angle, and
we modify them at each iteration (lines 29-32). We will see later on how to
modify the value of these variables on user interactions (keyboard, mouse,
etc.).
This function works like setInterval(...) with one difference: it calls your
function ONCE and AFTER a given amount of time.
1. function animationLoop() {
2. // 1 - Clear
3. [Link](0, 0, [Link], [Link]);
4. // 2 Draw
5. drawMonster(monsterX, monsterY, monsterAngle, 'green', 'yellow');
6. // 3 Move
7. monsterX += 10;
8. monsterX %= [Link]
9. monsterAngle+= 0.01;
10. // call mainloop again after 20ms
11. requestId = setTimeout(animationLoop, 20);
12. }
13.
14. function start() {
15. // Start the animation loop, change 20 for bigger
16. // values
17. requestId = setTimeout(animationLoop, 20);
18. }
19. function stop() {
20. if (requestId) {
21. clearTimeout(requestId);
22. }
23. }
This function is certainly more suitable for doing graphic animation, such as for
writing an HTML5 game. It will never interrupt an ongoing animation, even if
the instructions inside the animation loop take too long.
This problem also occurs with setInterval, the timing is not "very" reliable. If
you plan to run a function every 20ms, and if you measure precisely the real
timing, sometimes you will discover big differences between what is scheduled
and what is performed. This is because these methods were designed a long
time ago, when high precision timers and 60 frames per second animation
were not an option.
requestAnimationFrame() - 60
frames/second animation (best
practice)!
The scheduling is much more accurate: if the code inside the function can
be executed in less than 16.6ms, then the average error between the
scheduled time and the real time will be much smaller than with the old
functions.
High resolution timer: even if this difference is small, the function that is
called after 16.6ms has an extra parameter that is a high resolution time, very
useful for writing games that do time-based animation. Time-based animation
will be studied in detail in the HTML5 Part 2 course at W3Cx. It is a technique
that comprises measuring the amount of time elapsed between two frames,
then computing the distance in pixels to move objects on screen so that the
visible speed for a human eye remains constant, even if the frame rate is not.
Multiple animations are merged: browsers can bundle animations
happening at the same time into a single paint redraw (thus happening
faster/with less CPU cycles), solving the problems that can occur with
simultaneous setInterval calls.
CPU/GPU optimization, battery saved on mobiles: if the JavaScript
execution is occurring in a tab/window which is not visible, it doesn’t have to be
drawn. However the animation loop is still executed (objects will be moved, not
drawn). This is the same when a mobile phone or tablet screen is black or if the
application is put in background.
Typical use
You will note that requestAnimationFrame(function) is used
like setTimeout(function, delay). A call to requestAnimationFrame just
asks the browser to call the function passed as a parameter ONCE, and the
target delay is fixed, and corresponds to a 60 frames/s frame rate (16.6ms).
Notice that an id is used for stopping an animation
with cancelAnimationFrame(id).
Source code:
1. <body onload="init();">
2. <script>
3. var canvas, ctx;
4. function init() {
5. // This function is called after the page is loaded
6. // 1 - Get the canvas
7. canvas = [Link]('myCanvas');
8. // 2 - Get the context
9. ctx=[Link]('2d');
10. // 3 - start the animation
11. startAnimation();
12. }
13.
14. var id;
15. function animationLoop(timeStamp) {
16. // 1 - Clear
17. [Link](0, 0, [Link], [Link]);
18. // 2 Draw
19. drawShapes(...);
20. // 3 Move
21. moveShapes(...);
22. // call mainloop again after 16.6ms (corresponds to 60 frames/second)
23. id = requestAnimationFrame(animationLoop);
24. }
25.
26. function startAnimation() {
27. id = requestAnimationFrame(animationLoop);
28. }
29. function stopAnimation() {
30. if (id) {
31. cancelAnimationFrame(id);
32. }
33. }
34. </script>
35. </body>
1. function animationLoop(timeStamp) {
2. // 1 - Clear
3. [Link](0, 0, [Link], [Link]);
4.
5. // 2 - Draw
6. drawMonster(monsterX, monsterY, monsterAngle, 'green', 'yellow');
7.
8. // 3 - Move
9. monsterX += 10;
10. monsterX %= [Link]
11. monsterAngle+= 0.01;
12.
13. // call mainloop again after 16.6 ms (60 frames/s)
14. requestId = requestAnimationFrame(animationLoop);
15. }
16. function start() {
17. // Start the animation loop, targets 60 frames/s, this
18. // calls animationLoop only ONCE!
19. requestId = requestAnimationFrame(animationLoop);
20. }
21. function stop() {
22. if (requestId) {
23. cancelAnimationFrame(requestId);
24. }
25. }
Many HTML5 games perform what we call a "time-based animation". For this,
we need an accurate timer that will tell us the elapsed time between each
animation frame.
Depending on this time, we can compute the distances that must be achieved
by each object on the screen in order to move at a constant speed (for a
human eye), independently of the CPU or GPU of the computer or mobile
device that is running the game.
Using time-based animation, and more generally, using the canvas element for
writing HTML5 games, will be a chapter of the HTML5 Part-2 course to come.
Current support
Current support (as of June 2016) is really good and all modern browsers
support this API.
position or speed of an alien ship, and the animation loop will take care of
The events are called DOM events, and we use the DOM JavaScript API to
easy to use. Mixing the 'visual layer' (HTML) and the 'logic layer'
(JavaScript) in one place is ok for small examples (we have used this in
some examples in this course) but is not the recommended way for full
JavaScript
Here is an example:
1. [Link]('someDiv').onclick = function(evt) {
2. alert('clicked!');
3. }
This method is fine, but you will not be able to attach several listener
functions. If you need to do this, the preferred version is the next one.
1. [Link]('someDiv').addEventListener('click', function(
evt) {
2. alert('clicked!');
3. }, false);
The third parameter is not important for now, just set it to false, or
1. [Link]('click', function(event) {
2. // now you can use the event object inside the callback
3. }, false);
Depending on the type of event you are listening to, we will use different
properties from the event object in order to get useful information like:
"what keys have been pressed down?", "what is the position of the mouse
We will now cover how to deal with the keyboard and the mouse. Some
experimental APIs like the gamePad API are on their way and supported
by some browsers (to be studied in the HTML5 Part-2 course to come at
W3Cx).
1. <!DOCTYPE html>
2. <html lang="en">
3. <head>
4. <meta charset="utf-8">
5. <title>Click on button</title>
6. </head>
7. <body>
8. <button id="myButton">Click me!</button>
9. <script>
10. var button = [Link]('myButton');
11. // Define a click listener on the button
12. [Link]('click', processClick);
13. // callback
14. function processClick(event) {
15. [Link]("Button clicked");
16. // What is the event parameter?
17. }
18. </script>
19. </body>
20. </html>
Dealing with key events
Introduction
This has been a bit of a nightmare for years, as different browsers have had
different ways of handling key events and key codes (read this if you are fond
of JavaScript archeology: [Link] Fortunately it's
much better today, and we are able to rely on methods that should work on
any browser.
1. [Link]('keydown', function(event) {
2. if ([Link] === 37) {
3. //left arrow was pressed
4. }
5. }, false);
At line 2, the value "37" is the key code that corresponds to the left arrow. It
might be difficult to know the correspondences between real keyboard keys
and codes, so here are handy pointers:
Indeed this solution works well if you write a game, and want to detect events
wherever the mouse cursor is, and without worrying about what HTML element
has the focus, etc...
1. <script>
2. var canvas, ctx;
3. var monsterX=100, monsterY=100, monsterAngle=0;
4. var incrementX = 0;
5. function init() {
6. // This function is called after the page is loaded
7.
8. // 1 - Get the canvas
9. canvas = [Link]('myCanvas');
10.
11. // 2 - Get the context
12. ctx=[Link]('2d');
13.
14. // 3 add key listeners to the window element
15. [Link]('keydown', handleKeydown, false);
16. [Link]('keyup', handleKeyup, false);
17. // 4 - start the animation
18. requestId = requestAnimationFrame(animationLoop);
19. }
[Link] handleKeydown(evt) {
21. if ([Link] === 37) {
22. //left key
23. incrementX = -1;
24. } else if ([Link] === 39) {
25. // right key
26. incrementX = 1;
27. }
28. }
[Link] handleKeyup(evt) {
30. incrementX = 0;
31. }
32. function animationLoop() {
33. // 1 - Clear
34. [Link](0, 0, [Link], [Link]);
35.
36. // 2 Draw
37. drawMonster(monsterX, monsterY, monsterAngle, 'green', 'yellow');
38.
39. // 3 Move
40. monsterX += incrementX;
41.
42. // call again mainloop after 16.6 ms (60 frames/s)
43. requestId = requestAnimationFrame(animationLoop);
44. }
45. </script>
Example 2: What if I want to listen to key events
only in my canvas?
If you add a key listener to a canvas element, the problem is that it will get
events only when it has the focus. And by default, it will never have the focus!
The tabindex attribute of the canvas element makes it
focusable. Without it, it will never get the focus!
The trick is to declare the canvas like this:
1. <canvas id="myCanvas" width="350" tabindex="1" height="200">
2. </canvas>
1. canvas=[Link]('myCanvas');
2. ...
3. [Link]();
Now, if we try an example with the above canvas declaration, we show when
an HTML element has the focus: a border is added to it, as shown
here: [Link]
Note that the line that forces the focus to the canvas is commented by default.
Try to click on the canvas, then press a key, then click out of the canvas, then
press a key: this time nothing happens!
1. var canvas;
2. function init() {
3. canvas=[Link]('myCanvas');
4.
5. // This will work only if the canvas has the focus
6. [Link]('keydown', handleKeydown, false);
7. // We can set the focus on the canvas like this:
8. //[Link]();
9. // ... but it will stop working if we click somewhere else
10. // in the document
11. }
12.
13.
14. function handleKeydown(e){
15. alert('keycode: '+[Link]);
16. return false;
17. };
Line 10 is useful to initially set the focus on the canvas, but this trick will not
work if we click somewhere else in the HTML page.
Here is a modified version of the "move monster example" seen earlier. This
time, you move the monster with the left and right arrow only when the mouse
cursor is over the canvas. We added two mouse event listeners on the canvas:
one for the mouseenter event and the other for the mouseout event.
When the mouse enters the canvas we call [Link]() to set the focus to
the canvas, and when the mouse cursor goes out of the canvas, we
call [Link]() to unset the focus.
1. function init() {
2. // This function is called after the page is loaded
3. // 1 - Get the canvas
4. canvas = [Link]('myCanvas');
5. // 2 - Get the context
6. ctx=[Link]('2d');
7. // 3 - Add key listeners to the window element
8. [Link]('keydown', handleKeydown, false);
9. [Link]('keyup', handleKeyup, false);
10. [Link]('mouseenter', setFocus, false);
11. [Link]('mouseout', unsetFocus, false);
12. // 4 - Start the animation
13. requestId = requestAnimationFrame(animationLoop);
14. }
15. function setFocus(evt) {
16. [Link]();
17. };
18. function unsetFocus(evt) {
19. [Link]();
20. incrementX = 0; // stop the monster if the mouse exists the canvas
21. };
The third parameter (false) of lines 12 and 13 means "we do not want to
propagate the event to the ancestors of the canvas in the DOM."
Introduction
Detecting mouse events in a canvas is quite straightforward: you add an event
listener to the canvas, and the browser invokes that listener when the event
occurs.
The example below is about listening to mouseup and mousedown events (when
a user presses or releases any mouse button):
The event received by the listener function will be used for getting the button
number or the coordinates of the mouse cursor. Before looking at different
examples, let's look at the different event types we can listen to.
mouseleave: similar to mouseout, fired when the mouse leaves the surface of
the element. The difference between mouseleave and mouseout is
that mouseleave does not fire when the cursor moves over descendant
elements, and mouseout is fired when the element moved is outside of the
bounds of the original element or is a child of the original element.
mouseover: the mouse cursor is moving over the element that listens to that
event. A mouseover event occurs on an element when you are over it - coming
from either its child OR parent element, but a mouseenter event only occurs
when the mouse moves from the parent element to the child element.
mousedown: fired when a mouse button is pressed.
mouseup: fired when a mouse button is released.
mouseclick: fired after a mousedown and a mouseup have occured.
mousemove: fired while the mouse moves over the element. Each time the
mouse moves, a new event is fired, unlike with mouseover or mouseenter,
where only one event is fired.
Most of the time you need to work with the mouse position relative to the
canvas, not to the window, so you must convert the coordinates between the
window and the canvas. This will take into account the position of the canvas,
and the CSS properties that may affect the canvas position (margin, etc.).
Fortunately, there exists a method for getting the position and size of any
element in the page: getBoundingClientRect().
WRONG code:
1. ...
2. [Link]('mousemove', function (evt) {
3. mousePos = getMousePos(canvas, evt);
4. var message = 'Mouse position: ' + mousePos.x + ',' + mousePos.y;
5. writeMessage(canvas, message);
6. }, false);
7.
8. ...
9. function getMousePos(canvas, evt) {
10. // WRONG!!!
11. return {
12. x: [Link],
13. y: [Link]
14. };
15. }
Here is the result, when the mouse is approximately at the top left corner of
the canvas:
Good version of the code: [Link]
Source code:
1. ...
2. <script>
3. var canvas, ctx, previousMousePos;
4. ...
5. function drawLineImmediate(x1, y1, x2, y2) {
6. // a line is a path with a single draw order
7. // we need to do this in this example otherwise
8. // at each mouse event we would draw the whole path
9. // from the beginning. Remember that lines
10. // normally are only usable in path mode
11. [Link]();
12. [Link](x1, y1);
13. [Link](x2, y2);
14. [Link]();
15. }
16.
17. function handleMouseMove(evt) {
18. var mousePos = getMousePos(canvas, evt);
19.
20. // Let's draw some lines that follow the mouse pos
21. if (!started) {
22. previousMousePos = mousePos; // get the current mouse position
23. started = true;
24. } else {
25. // We need to have two consecutive mouse positions before drawing
a line
26. drawLineImmediate(previousMousePos.x, previousMousePos.y,
27. mousePos.x, mousePos.y);
28. previousMousePos = mousePos;
29. }
30. }
31. [Link] = function () {
32. ...
33. started = false;
34.
35. [Link]('mousemove', handleMouseMove, false);
36. };
37. </script>
1. function handleMouseMove(evt) {
2. var mousePos = getMousePos(canvas, evt);
3.
4. // Let's draw some lines that follow the mouse pos
5. if (painting) {
6. drawLineImmediate(previousMousePos.x, previousMousePos.y,
7. mousePos.x, mousePos.y);
8. previousMousePos = mousePos;
9. }
10. }
11. function clicked(evt) {
12. previousMousePos = getMousePos(canvas, evt);
13. painting = true;
14. }
15.
16. function released(evt) {
17. painting = false;
18. }
19.
20. [Link] = function () {
21. canvas = [Link]('myCanvas');
22. ctx = [Link]('2d');
23. painting = false;
24.
25. [Link]('mousemove', handleMouseMove, false);
26. [Link]('mousedown', clicked);
27. [Link]('mouseup', released);
28. };
Introduction
Resizing a canvas can be tricky if we don't know a few rules that might not
be easily guessed:
[Link] the width or height property of a canvas in JavaScript erases its
content and resets its context,
[Link] percentages (%) in the CSS width and height properties of a
canvas does not change its number of pixels/resolution. Instead, it scales the
existing pixels without erasing the content, giving a blurry effect when a
canvas becomes larger, for example.
Before looking at how best to handle canvas resizing, let's see some
examples below:
1. <script>
2. ...
3. function resizeCanvas() {
4. [Link] = 300;
5. }
6.
7. </script>
8. ...
9. <button onclick="resizeCanvas();">
10. Click this button to resize the canvas and erase it!
11. </button>
Then, we added this CSS rule. Try it online (resize the windows, you will see
what happens): [Link]
1. <style>
2. #myCanvas {
3. border: 1px solid black;
4. width:100%
5. }
6. </style>
And the result shows clearly that the resolution is still the same, only the pixels
are bigger!
Even bigger:
HTML code:
1. <div id="parentDiv">
2. <canvas id="myCanvas" width="100" height="100" ></canvas>
3. </div>
CSS code:
1. <style>
2. #parentDiv {
3. width:100%;
4. height:50%;
5. margin-right: 10px;
6. border: 1px solid red;
7. }
8.
9. canvas {
10. border: 2px solid black;
11. }
12. </style>
1. function init() {
2. ...
3. // IMPORTANT: there is NO WAY to listen to a DIV's resize
4. // listen to the window instead.
5. [Link]('resize',
6. resizeCanvasAccordingToParentSize, false);
7. ...
8. }
9.
10. function resizeCanvasAccordingToParentSize() {
11. // adjust canvas size, take parent's size, this erases content
12. [Link] = [Link];
13. [Link] = [Link];
14. ...
15. // draw something, taking into account the new canvas size
16. }
Initial size:
When the canvas is resized, its width became smaller than the monster's size.
We scaled down the monster (using [Link]!)
The code is very similar to the previous example, we just
replaced drawDiagonals() by drawMonster(...), and we added a test in
the drawMonster(...) function for scaling the monster if it's bigger than the
canvas width (look at lines 10-16), this is a common trick:
Introduction
With HTML5, forms, which had shown little improvement since 1997, evolved
considerably. To achieve this, web developers relied on many popular
JavaScript frameworks for validating input formats, providing various input
GUIs, such as calendars for dates, sliders, etc. Frameworks such as jQueryUI,
Dojo, and Sencha all provide a widget set for improving forms. Furthermore, it
was time to take into account the specifics of mobile web applications, where
the GUI of a date chooser cannot be the same as a 400x400 pixel wide
calendar on a desktop. Contextual virtual keyboards provided the way forward
on smartphones and tablets thanks to Apple, Google and others.
A new set of input fields that include a validation API and visual feedback,
contextualized keyboards, etc. Of course the look and feel depends on the web
browser's implementations, but the HTML5 forms specification introduced 13
new <input type=.../> fields: email, tel, color, url, date, datetime,
datetime-local, month, week, time, range, number and search.
Built-in validation system: JavaScript API for custom validation, CSS pseudo
classes that are useful for changing an input field style depending on the
validity of the input.
Other goodies, such as the option to set an input field out of a <form>, new
elements such as<datalist> for autocompletion, <output> for feedback, etc.
There is a lot of course content covered this week, and before we get into all
the details of the elements and attributes introduced by
HTML5 we suggest playing with running examples of full featured forms.
The examples
These examples are creations by students from a previous version of this
course, when it was hosted at the [Link] Web site (the W3C e-
learning platform). They are given "as is". They use the geolocation API that
will be presented in Week 6 for auto-filling the address input fields. This part
will be explained next week.
Feel free to look at the source code, and do not hesitate to ask questions in the
forum if you need explanations.
Example 1 (by Steve K.)
Example 2 at JS Bin (by Mels Le N.)
Forms are a way to get user input which is sent to a remote server. This section
of the course focuses on the HTML5 additions to forms, and as such will only
cover the client-side part.
On the server side, you may have PHP, Java, C#, Ruby, Python, etc.
components. There are several ways to collect server-side data from a form in
a Web page: REST Web services, servlets, Microsoft ASP pages, etc.
On the client side, the forms indicate to which server and how the data should
be sent, using the action and method attributes respectively. A <button
type="submit"> or an <input type=submit> field is used to submit the form
content.
Another approach is to use JavaScript for sending the form content with
Ajax. This will be covered in the HTML5 Part-2 course.
This week, we will study the new elements and attributes offered by HTML5,
and will also cover the new HTML5 form validation API.
The example in the video shows some best practices for writing accessible
forms and does some basic layout using CSS. The additional example below
(external resource) shows the same good practices but presents a more
complete form with CSS rules to make a nice layout.
Additional example
A more complete example is on JS Bin, adapted from this very good article
from the Mozilla Developer Network.
Creating accessible forms
Forms are commonly used to enable user interaction in Web sites and Web
applications. For example for login, registering, commenting, and purchasing.
[Link] every form field, ensure that a descriptive label is provided and use
the <label> element to identify each form control.
[Link] larger or complex forms, use the <fieldset> and <legend> elements to
respectively group and associate related form controls.
We will give usage examples for each of these two basic guidelines in the
following pages.
Further reading
The WAI Web site hosts a Forms tutorial where you will find more guidelines to
follow in order to make your forms truly accessible: Form Instructions,
Validating Input, User Notifications, Multi-Page Forms, and Custom Controls.
When these labels are marked up correctly, people can interact with them
using only the keyboard, using voice input, and using screen readers. Also, the
label itself becomes clickable, which enables a person who has difficulty
clicking on small radio buttons or checkboxes to click anywhere on the label
text.
Source code:
Alternative example 1
Note that you can also include the <input> element inside
the <label>...</label> element, and also add a <span lang="en"> for
example, to indicate the language used in the label. Sometimes, nesting labels
and inputs can also make CSS styling easier and produce better results with
screen readers.
Source code:
labeling buttons
The label of a <button> element is set inside the element and can include
markup. This allows advanced accessibility hints to be included, such as
marking up language change.
When using the <input> element to create buttons, the label is set in
the value attribute of the element.
1. <button type="submit">Submit</button>
2. <button type="button">Cancel</button>
3.
4. <input type="submit" value="Submit">
5. <input type="button" value="Cancel">
Source code:
Grouping controls
Groupings of form controls, typically groups of related checkboxes and radio
buttons, sometimes require a higher level description. Grouping related form
controls makes forms more understandable for all users, as related controls are
easier to identify.
1. <fieldset>
2. <legend>Output format</legend>
3. <div>
4. <input type="radio" name="format" id="txt" value="txt" checked>
5. <label for="txt">Text file</label>
6. </div>
7. <div>
8. <input type="radio" name="format" id="csv" value="csv">
9. <label for="csv">CSV file</label>
10. </div>
11. […]
12. </fieldset>
Example 2 - Checkboxes
In the example below, there are three checkboxes that are all part of an opt-in
function for receiving different types of information.
Source code:
1. <fieldset>
2. <legend>I want to receive</legend>
3. <div>
4. <input type="checkbox" name="newsletter" id="check_1">
5. <label for="check_1">The weekly newsletter</label>
6. </div>
7. […]
8. </fieldset>
WAI-ARIA roles are very important in the accessibility world, and we invite you
to see an example provided in the associated WAI tutorial. This article by Oscar
Cao gives an Introduction to understanding WAI-ARIA 1.0 roles.
HTML4 HTML5
color
date
button
datetime
checkbox
datetime-local
file *
email
hidden
month
image
number
password
range
radio
search
reset
tel
submit
time
text
url
week
* The "file" type is disabled on IOS as this operating system does not give access to a
filesystem.
Five HTML5 types are variants about choosing a date (in red)
Now, let's play with some small examples and use these new input types and
attributes.
<input type=color>
Introduction
For years we used hundreds of lines of JavaScript for selecting colors, but now
it's bundled in the browser.
Here is how it looks on a mobile device: the first screenshot is from Opera
mobile, the second with Chrome mobile, and the third on Blackberry. Note
that, although no screenshot is shown here, FireFox mobile also has support.
Typical use
Inserting a color chooser is as simple as:
1. <!DOCTYPE html>
2. <html>
3. <body>
4. Choose a color : <input type="color" value="#FF00FF"/>
5. </body>
6. </html>
1. <!DOCTYPE html>
2. <html>
3. <body>
4. Select a color : <input type="color" id="colorChooser"/>
5. <script>
6. var colorInputField = [Link]("#colorChooser");
7. [Link]('input', function(evt) {
8. [Link] = [Link];
9. }, false);
10.</script>
11. </body>
12. </html>
Example: if you are using Opera or Chrome, click the black rectangle on the
right: . The following should be displayed:
Note that the id of the <datalist> element should be the same as the value of
the list attribute of the input field.
Warning: color values must use the CSS hexadecimal notation; using
'blue', 'green' and 'red' does not work in current implementations.
Below is an example with the polyfill [Link]. See how it renders in Safari
(the same code renders natively on browsers that support <input
type="color">):
For those of you who would prefer using a CDN, here is another example that
uses this polyfill, directly on JS Bin. You just have to include two lines in the
HTML and your <input type=range> will work on Safari and IE too :-) Notice
that this polyfill does not fire the input event, only the change event, when a
color is picked.
Example on JS Bin
1. <script src="[Link]
2. <scriptsrc="[Link]
[Link]"></script>
3. <link rel="stylesheet" type="text/css"
4.
href="[Link]
>
Another example of this polyfill. This time we downloaded it and made our own
HTML page:
And here is the HTML code (note, you first need to download the lib from the
Web site):
1. <!doctype html>
2. <html>
3. <head>
4. <title>Spectrum polyfill example, for input type=color</title>
5. <link rel="stylesheet" type="text/css" href="../[Link]">
6. <script type="text/javascript" src="../docs/[Link]"></script>
7. <script type="text/javascript" src="../[Link]"></script>
8. </head>
9. <body>
10. <input type="color" onchange="alert([Link]);"></p>
11. </body>
12. </html>
Another problem is that there is no way to control where the dialog that
contains the color chooser will appear - no positioning via CSS or JavaScript is
possible. The specification does not say anything about how to position it over
the page, thus the result is vendor specific.
The solution proposed by the W3C and its contributors is called Web
Components, a new approach for designing HTML5 widgets, that will be
covered in the HTML5 Part-2 course.
In FireFox:
The <input type="date"> and its
variants (datetime, datetime-
local, time, month, week)
Introduction
For years, date and time pickers in
HTML forms made Web developers
rely heavily on JavaScript based
widgets. The process is simpler in
HTML5, which provides a special
control to handle this specific kind of
data natively. All mobile browsers
support<input type="time"> and <input type="date">, while support on
desktop computers is not yet as good.
Below are a few screenshots of the HTML5 date picker on several mobile
devices. Note that the native date pickers of the operating systems are used:
The problem is different on a desktop. While it's great to have native support
for a date picker, Web developers would sometimes prefer 100% control over
the look and feel of the date picker widget. For this purpose, the
solution undoubtedly lies with the new Web Components (a way to make
custom reusable widgets in HTML/CSS/JS), that will be detailed in the HTML5
Part-2 course.
Result:
Most of the time you will add other attributes to give some restrictions (choose
a date in the past, in the future, only on a Saturday, etc.).
Try this example: just click the next input field: , or try it online on JS Bin if you
want to tweak the source code:
Errata: the online example is correct, but the above screenshot shows a year
equal to "2014" for the maxattribute, which is incorrect.
Source code:
1. ...
2. <input type="date"
3. id="birthdayParty"
4. value="2015-06-20"
5. min="2015-06-20"
6. max="2015-06-30">
7. ...
1. <input type="date"
2. id="birthdayParty"
3. value="2015-06-20"
4. min="2015-06-20"
5. max="2015-06-30"
6. step="7">
The list attribute of the input element must match the id attribute of
the datalist element.
If you use the min, max, or step attributes with a list attribute, it may
filter the restricted list even more. Check this example on JS Bin (tested
with Google Chrome), that has a restricted list of three elements, one of
which is filtered because it is not in in the min/max range.
responding to date changes, trying date/time and
other variants
Listening to the input event
Here is an interactive example at JS Bin where you can change the type of
date/time chooser. It also shows how to listen to the input event when a
date/time is chosen.
Source code:
1. <!DOCTYPE html>
2. <html>
3. <body>
4. Testing the new date input field. So far works only in Chrome and Opera
browsers.<p>
5. Choose a date/time : <input type="date" id="date" /></p>
6. <p>
7. You picked: <span id="pickedDate"></span>
8. </p>
9. After you have tried the first example, change the value of the "type" attribute
to:
10. <ul>
11. <li>datetime</li>
12. <li>datetime-local</li>
13. <li>time</li>
14. <li>week</li>
15. <li>month</li>
16. </ul>
17. And see the result.
18. <script>
[Link] field = [Link]("#date");
20. var result = [Link]("#pickedDate");
[Link] = function(evt) {
22. var date = [Link];
23. [Link] = "<b>"+date+"</b>";
24. }
25. </script>
26. </body>
27. </html>
Lines 20-26 show how we can detect a date change using JavaScript.
The following example at JS Bin shows how to ascertain whether a date is in the
past or in the future:
1. <body>
2. <label for="birthDate">Enter your birth date: </label><p>
3. <input type="date" id="birthDate" >
4. <p>
5. You picked: <span id="pickedDate"></span><p>
6. <span id="pastFuture"></span>
7. </p>
8. <script>
9. var field = [Link]("#birthDate");
10. var result = [Link]("#pickedDate");
11. var pastFuture = [Link]("#pastFuture");
[Link] = function(evt) {
13. var date = [Link];
14. [Link] = "<b>"+date+"</b>";
15. if([Link] <= new Date()) {
16. [Link] = 'green';
17. [Link] = "<b>Date in the past, ok!</b>"
18. } else {
19. [Link] = 'red';
20. [Link] = "<b>Date in the future, you're not even
born!</b>"
21. }
22. }
23. </script>
24. </body>
Lines 17-23 show how we can compare the date picked in the calendar widget
with the current date. Note that we can compare any given dates using
JavaScript. To check that the chosen date is before 2000 we would do this:
These variants have been moved to the HTML 5.1 specification (still a work in
progress) because so far they have only been implemented by Chrome and
Opera.
Here is an interactive example at JS Bin where you can change the type of date
chooser and try all the different possible values for the type attribute of date
pickers.
<input type="time">:
<input type="datetime">
<input type="datetime-local">
<input type="week">:
<input type="month">:
Current support
These new input types are not yet supported by all browsers in their
desktop versions (while mobile support is 100% for major browsers).
However, for simple date picking (especially on mobiles), these elements are
very practical as is, and many polyfills are available, bringing compatibility to
browsers that do not yet support it.
There is also a growing set of Web Components for picking date/time. For
example, see [Link] and enter the "date" keyword in the
search field.
So far, as at early 2015, Safari, Internet Explorer and FireFox desktop browsers
still do not support this input type, as shown in the table below:
See the up-to-date version of the above table and check for the mobile support.
<input type="email">
this new input type pops up a keyboard layout adapted to email input. Note
behaviors:
If the value entered looks like an email address (contains a "@"...), the field
If the value entered does not contain an "@", and does not look like
an email address, the field isinvalid and gets the pseudo CSS
class :invalid
See the next example to see this in action. More details will be presented
Typical use
1. <!DOCTYPE html>
2. <html>
3. <head>
4. <meta charset="utf-8">
5. <title>Example of input type=email</title>
6. <style>
7. input:invalid {
8. background-color:pink;
9. }
10. </style>
11. </head>
12. <body>
13. <label for="email">Enter your email </label>
14.<input type="email" id="email">
15. </body>
16. </html>
Note the CSS rule that turns the background color of the email input field
to pink if a user enters an invalid address (lines 7-8). Also note that the
should contain a "@", a ".", etc.). It does not check if the address is an
existing one.
<input type="tel">
This input field is really useful on smartphones and tablets, as it makes the
Try it in your browser (we used the same CSS for changing the background-
Source code:
1. <!DOCTYPE html>
2. <html>
3. <body>
4. <head>
5. <title>Example of input type=tel</title>
6. <style>
7. input:invalid {
8. background-color:pink;
9. }
10. </style>
11. </head>
12. <body>
13. <label for="tel">Enter a telephone number:</label>
14.<input type="tel" id="tel"
15. placeholder="(555) 555-5555"
16. pattern="^(?\d{3})?[-\s]\d{3}[-\s]\d{4}.*?\)"/>
17. </body>
18. </html>
<input type="URL">
This input field is really useful on smartphones and tablets, as it makes the
another section).
the placeholder and pattern attributes for entering only URLs that start
Source code:
1. <!DOCTYPE html>
2. <html>
3. <head>
4. <title>Example of input type=url</title>
5. <style>
6. input:invalid {
7. background-color: lightPink;
8. }
9. </style>
10. </head>
11. <body>
12. <label for="url1">Enter a URL (default validation):</label>
13.<input type="url1" id="url"/>
14. <p>
15. <label for="url2">Enter a URL (custom validation, must start with http,
https or ftp):</label>
16. <input id="url2" type="url" placeholder="[Link]
17. pattern="(http|https|ftp)\:\/\/[a-zA-Z0-9\-\.\/]*"/><p>
18. </body>
19. </html>
Lines 16-17 show the use of a pattern attribute with a JavaScript regexp
that accepts only URLs starting with http, https or ftp. More details on
the pattern attribute are given in the section that presents the new
<input type="search">
The search type is used for search fields (i.e., for a search engine). A search
field behaves like a regular text field, except that it may provide some
feedback GUI for stopping the current request and emptying the search
The specification does not state what the GUI should look like, so current
Typical use:
Results on Chrome and Opera desktop - notice the small cross on the right
screenshot borrowed from this excellent site about HTML5 forms that is
worth reading):
Source code for the Knowledge check below
1. <!DOCTYPE html>
2. <html>
3. <head>
4. <meta charset="utf-8">
5. <title>Example of input type=email</title>
6. <style>
7. input:? {
8. background-color:pink;
9. }
10. input:?? {
11. background-color:lightGreen;
12. }
13. </style>
14. </head>
15. <body>
16. <label for="email">Enter your email:</label>
17. <input type="email" id="email">
18. </body>
19. </html>
<input type="number">
5" max="500"/>
Screenshot examples taken with mobile devices (left: IOS, right: Android)
Examples on desktop (the width will be adjusted depending on
Typical usage
0"/>
This field accepts specific attributes max, min, step, value (default
displayed value).
behaviors:
If the value entered using a keyboard is not a valid number, or is not in the
range defined by the min andmax attributes, the field is invalid and gets
the step value, and make the input field valid only when the
of step.
Or, do it here in your browser (Manually enter a value that is not in the
Source code:
1. <!DOCTYPE html>
2. <html>
3. <head>
4. <style>
5. #number:invalid {
6. background-color:pink;
7. }
8. #number:valid {
9. background-color:lightGreen;
10. }
11. </style>
12. </head>
13. <body>
14. Example of <code><input type=number></code>:<p>
15. <label for="number">Quantity (between 0 and 500, should be a
multiple of 5 otherwise it's invalid): </label>
16.<input type="number" id="number" value="25" min="0" step="5"
max="500"/>
17. <p>
18. Change the different values for attributes step, max, min, value. Don't
forget to try step="any" for float values...
19. </body>
20. </html>
1. <!DOCTYPE html>
2. <html lang="en">
3. <head>
4. <meta charset="utf-8">
5. <title>Example type=number</title>
6. <style>
7. #myField:valid {
8. background-color:lightGreen;
9. }
10. #myField:invalid {
11. background-color:pink;
12. }
13. </style>
14. </head>
15. <body>
16. <label for="myField">Please enter a number between 0 and
30: </label>
17.
<input type="number" id="myField" min="0" step="5" max="30"/>
18. </body>
19. </html>
<input type="range">
This input type renders as a slider. It accepts the same attributes as the <input
type="number"/> : min, max, step and value.
But most of the time, you will need a visual feedback that shows the current
value selected by the slider.
This online example at JS Bin shows how to add a visual feedback using a very
short JavaScript function and an <output> element. The result is shown in the
first screenshot of this page, and can be tried here live in your browser, just
click and drag the small cursor of the slider (or use up and down arrow keys
when the field has the focus):
Source code:
1. <!DOCTYPE html>
2. <html>
3. <head>
4. <style>
5. #rangeValue1 {
6. border:1px solid black;
7. padding:2px;
8. }
9. </style>
10. <script>
11. [Link] = function() {
12. // Called when the page is loaded, for displaying initial value in the
output
13. printValue('slider1','rangeValue1');
14. }
15. function printValue(sliderId, outputId) {
16. var x = [Link](outputId);
17. var y = [Link](sliderId);
18. [Link] = [Link];
19. }
20. </script>
21. </head>
22. <body>
23. <form >
24. <label for="slider1">Select a value:</label>
25. <input id="slider1" type="range"
26. min="100" max="500" step="10" value="150"
27. oninput="printValue('slider1','rangeValue1')"/>
28. <output id="rangeValue1"></output>
29. </form>
30. <br/>
31. Play with attributes: value, min, max, step...
32. </body>
33. </html>
34.
Snapping behavior and
the step attribute
When you click and drag the slider,
it "jumps" to some snap points corresponding to the integer values of the range
defined by the min and max attributes, and the "size of the jumps" depends on
the value of the step attribute.
Try these examples and look at their behavior (complete online version is also
available at JS Bin):
Note that in the previous example, the default value displayed is 14, not 12
(the value just above minplus an integer step value). 12 is not possible so it's
been "snapped" to 14.
value=5 min=0, max=10 step="0.5":
In the previous example, it's necessary to add quotes for
setting step="0.5" (while HTML5 authorizes not using quotes for setting
integer values to attributes).
value=5 min=0, max=10 step="any":
Using the <datalist> element, it's possible to display "ticks" above the range
slider, at given positions.
This feature is not yet (in 2015) supported by all browsers, check this
compatibility table.
value=20 min=10, max=50 step=5, ticks at 0, 10, 20, 30, 40 and 50:
External resource
A script with the code from the above resource, that automatically generates
ticks, depending on the min, max and step attributes, codepen demonstration
here: see the Pen Auto-Generated HTML5 range input Ticks by Dudley Storey
(@dudleystorey) on CodePen.
Or try it here:
HTML:
1. <p>
2. <label for="sliderVolume">value=0.5 min=0, max=11 step="0.1":
3. </label><p>
4. <input id="sliderVolume" type="range" min="0" max="11" step="0.
1" value="0.5"
5. oninput="printValue('sliderVolume','volumeValue')" class="custom"/>
6. <output id="volumeValue"/>
7. </p>
CSS:
JavaScript (just for changing the linear gradient of the CSS background color,
the CSS transition (line 7 of the above code) makes the color change
animated/smooth:
11. val *= 100; // val is between 0 and 1, values of the min and max
attributes
12. // We scale this to appropriate values for a gradient
13. var cssProp = 'linear-gradient(to right , lightGreen, blue '+val +'%,
red)';
14. [Link] = cssProp;
15. }
form
readonly
autocomplete
name
autofocus
disabled*
list
type
pattern
maxlength
required*
readonly
placeholder
size
multiple
value
list
alt
min
src
max
height
step
width
formaction
checked*
formenctype
align **
formmethod
formtarget
formnovalidate
We have already
seen the use of
pseudo CSS classes
used together with
the input field and
form validation
(pattern attribute,
input:invalid CSS
rule). We also
briefly looked at the
use of the placeholderattributes for displaying a helper message in the input
field.
In this section, we will cover the rest of the new attributes and provide further
examples of using the previously discussed attributes.
Another part of the course, about form validation and visual feedback using
CSS, will examine some of the most useful attributes in even greater detail.
Typical use
Try this interactive example in JS Bin, or try it directly in your browser:
Source code:
1. <!DOCTYPE html>
2. <html>
3. <body>
4. <label for="yourName">Enter your name:</label>
5. <input type="text" id="yourName" name="yourName" form="form1"/>
6. <p>
7. <form id="form1" action="[Link]" method="post">
8. <fieldset>
9. <legend>Choose option</legend>
10. <label for="free">Free registering</label>
11. <input type="checkbox" id="free"/>
12. <label for="premium">Premium</label>
13. <input type="checkbox" id="premium"/>
14.
15. <button type="submit">Send form</button>
16. </fieldset>
17. </form>
18. </body>
19. </html>
Line 5 and 7 shows the form attribute. Make sure that its value matches
the id of the form!
This attribute targets most input types (those that allow typing in them).
Typical use
Online example: [Link]
form's autocomplete=onattribute):
form's autocomplete=onattribute):
To see auto-completion in action: enter something in both fields and
submit the form. Then enter the same thing: you will see that only
This attribute is useful for transferring the focus to a field other than the
first field in a page/form (by default the first input field has the focus).
Attention: there must not be more than one element in the document
the autofocusattribute: the focus is put on the second input field of the
The required attribute makes the input field invalid if kept empty.
autofocus attribute
autofocus attribute):
1. <form>
2. ...
3. <input type="text" id="test"/><p>
4. ...
5. <input id="name" name="inputName"
6. placeholder="6 to 9 chars please..."
7. pattern="\w{6,9}"
8. required
9. autofocus
10. type="text"/>
11. ...
12. </form>
Boolean attributes.
1. <!DOCTYPE html>
2. <html lang="en">
3. <head>
4. <title>Example for a knowledge check</title>
5. </head>
6. <body>
7. <form>
8. <label for="studentID">Student ID (disabled field, cannot type in
it): </label>
9. <input type="text" value="S134356" id="studentID" disabled/><p>
10. <label for="name">First name: </label>
11. <input type="text" id="firstName"
12. placeholder="John"
13. autofocus
14. />
15. <label for="lastName">Last name: </label>
16. <input type="text" id="lastName"
17. placeholder="Smith"
18. autofocus
19. />
20. </form>
21. </body>
22. </html>
Here is a small code extract from a more complete example shown in the
section about the new <datalist> element (see next unit).
Online example at JS Bin
At lines 3 and 5, the value of the list attribute of the input field must match
the one of the id of the <datalist> element.
The pattern attribute
Cartoon from xkcd #1171: Perl Problems
The pattern attribute enables the validation of the user's input on the fly (also
at submission time), based on regular expressions. It applies to
the text, search, url, tel, email, and password input types.
You can also try this online JavaScript RegExps tester, and follow this
tutorial about "using JavaScript RegExps" that has step by step exercices
and explanations.
Typical use
Just add a pattern attribute
with a value that is the
JavaScript regular expression
that must match the entire
string entered in the field.
Note that the empty string is
valid by default (except if the required attribute is used - this makes empty
fields invalid).
With the previous example, until the value of the input field is equal to 3
alphabetic characters, the field is invalid.
As seen in the previous examples, we used some CSS pseudo classes for
automatically setting the background-color of the input field as we type.
1. <!DOCTYPE html>
2. <html>
3. <head>
4. <meta charset="utf-8">
5. <title>Example of the pattern attribute</title>
6. <style>
7. input:invalid {
8. background-color: lightPink;
9. }
10. input:valid {
11. background-color: lightGreen;
12. }
13. </style>
14. </head>
15. <body>
16. <label for="code">Please enter a 3 letter country code:</label>
17. <input type="text" name="country_code"
18. pattern="[A-Za-z]{3}"
19. title="3 letter country code"
20. id="code"/>
21. </body>
22. </html>
Their detailed use with these input fields has already been explained
in the different sections of this course dedicated to these particular
input field types.
Typical use
1. <input id="mydate" name="mydate"
2. type="date"
3. min="2012-01-01"
4. max="2013-01-01"
5. value="2012-01-01"
6. />
7.
8. <input name="time" id="time" type="time"
9. min="09:00"
10. max="17:00"
11. value="12:00"
12. />
13.
14.<input id="range" name="range" type="range" min="0" max="100" ste
p="5"/>
<input type="email|file"
multiple>
<input type="email|file" multiple="multiple">
<input type="email|file" multiple="">
iple attribute
Try these in your browser, look at the small variations (text in the buttons,
messages):
Use the standard key modifiers (shift, control, command) for selecting multiple
files when the file chooser dialog pops up.
Warning about the next attributes
presented
In the following pages, we present a set of rarely
used attributes introduced by HTML5. There will be
no questions about them in the exercises at the end
of the week.
Typical use
1. <form action="[Link]" method="post">
2. <input type="submit"
3. formaction="[Link]" formmethod="get"
4. value="Preview">
5. <input type="submit" value="Send">
6. </form>
Examples
Here are two online examples at JS Bin:
Example 1
Example 2
the first button submits to the default URL specified by the action attribute of
the form,
the second button submits to another action specified by
its formaction attribute.
1. <form action="[Link]">
2. <fieldset>
3. <legend>Example of formnovalidate attribute</legend>
4. <label for="email">E-mail:</label>
5. <input type="email" name="email" id="email"/><br>
6. <input type="submit" value="Submit" /><br>
7. <input type="submit"
8. formnovalidate
9. value="Submit without validation" />
10. </fieldset>
11. </form>
message. Using the other submit button will submit the form anyway.
formnovalidate attribute
Typical use
1. <input type="submit"
2. formtarget="_blank"
3. value="Submit but show results in a new window/tab">
First name:
Last name:
Source code:
1. <form action="[Link]">
2. <label for="firstName">First name:</label>
3. <input type="text" name="firstName" id="firstName"><br>
4. <label for="lastName">Last name:</label>
5. <input type="text" name="lastName" id="lastName"><br>
6. <input type="submit" value="Submit as usual">
7. <input type="submit"
8. formtarget="_blank"
9. value="Submit but show results in a new window/tab">
10. </form>
attribute of
with forms that contain file input fields. For sending files to a remote server,
1. <!DOCTYPE html>
2. <html lang="en">
3. <body>
4. <form action="[Link]" method="post" enctype="multipart/form-
data">
5. First name: <input type="text" name="fname"><br>
6. Last name: <input type="text" name="lname"><br>
7. <input type="submit" value="Submit">
8. </form>
9. </body>
10. </html>
Note that when you send form content using Ajax, this attribute is not
needed, as you will specify the type of data sent to the remote server in
enctype=...> element
the <form enctype=...> element (or its default value, if not present).
Typical use
1. <form action="[Link]">
2. ...
3. <input type="submit" formenctype="multipart/form-data"
4. value="Submit as Multipart/form-data">
5. </form>
Source code:
1. <!DOCTYPE html>
2. <html>
3. <body>
4. <form action="[Link]" method="post"
5. enctype="application/x-www-form-urlencoded">
6. <label for="firstName">First name:</label>
7. <input type="text" name="firstName" id="firstName"><br>
8. <label for="lastName">Last name:</label>
9. <input type="text" name="lastName" id="lastName"><br>
10. <input type="submit" value="Submit">
11. <input type="submit"
12. formenctype="multipart/form-data"
13. value="Submit as Multipart/form-data">
14. </form>
15.
16. <p><b>Note:</b> The formenctype attribute is not supported by all
browsers.</p>
17. </body>
18. </html>
submissions
If you run this example in the JS Bin standalone mode (click the black arrow
on the top right of the output tab, in JS Bin), you should see this:
Then, open the devtools and go to the "Network" tab, click on the POST
request. Once done, click on the right on the "Header" tab to see the HTTP
headers, and scroll down, you should see the form-data entries in the
the formenctype attribute, you should see that the form content has been
HTML4 HTML5
<form> <datalist>
<fieldset>
<legend>
<textarea>
<output>
<label>
<meter>
<select>
<progress>
<option>
<keygen> *
<optgroup>
<input>
<button>
The oninput event handler directly uses the <output> element using the value
of its name attribute.
x =
Example 2
+=
Source code:
1. <form >
2. <input name="a" value="50" type="range"
3. oninput="[Link] = [Link] + [Link];
4. [Link] = [Link];"/>
5. <output id="y">50</output> +
6. <input name="b" value="50" type="number" /> =
7. <output name="x" id="x" for="a b"></output>
8. </form>
This is why we used the valueAsNumber property also introduced by HTML5 for
some input fields such as <input type="range"> and <input
type="number">, we also encountered the valueAsDate properties when we
studied <input type="date">.
The <meter> element should not be used to indicate progress. You should
instead use a <progress> element.
More explanations about the colors and the meaning of the optimum attribute
will come further in this lesson.
Interactive example
Try the next example online at JS Bin or just play with it in your browser by
dragging the slider below:
optimum=19></meter>
Grades:
Explanations:
The optimum attribute indicates the optimal numeric value and gives an
indication where along the range is considered preferable. Just think of
the <meter> ranges as follows:
... and depending on the value you set to optimum attribute, one of the ranges
above becomes the "good (optimum)" range.
So in the previous example, with the value of the optimum attribute set to 19, a
number between min and low(not inclusive), the Range 1
(between min=0 and low=20) becomes the "good (optimum)" range (displayed
in green), the Range 3 (between high=80 and max=100) becomes the "bad"
(displayed in red color) range, and the Range 2, in the middle, will be displayed
in yellow (not optimum, not bad).
So, a <meter> element used for displaying blood pressure might be a good
candidate for setting the optimumvalue to "Range 2", and a <meter> element
used for displaying memory usage might be a good candidate for setting
the optimum value to "Range 1", meaning that a low memory usage is "good".
External resources
A good article about <meter> is to be found on the css-trick Web site. It shows
how to use proprietary CSS pseudo classes to style the element.
How to use and style the meter element, good blog post.
Gives:
Download progress:
Source code:
It is often "linked" to input fields either for restricting the value set that can be
proposed (i.e., restricted set of colors or possible dates, or for displaying slider
ticks, as shown above), but it may also be used in a more general way,
for providing client-side auto-completion without the need to use
JavaScript.
Current support
All major browsers support this element except Safari (as of June 2015).
See [Link] for details and polyfills.
Validation, CSS pseudo class feedback,
and custom validation API
In this section of the course,
we will look at CSS pseudo
classes that are useful for
giving instant feedback
when the user's input is not
valid. We will also look at
the new JavaScript API introduced by HTML5 for validating forms and form
elements.
In the following pages, we will first illustrate the concept of form validation with
the <input type="email"/>field. It can be generalized to all kind of input
types, such as url, number, etc. Some form attributes, such as pattern, will
also affect input field validity!
A first step to improve your HTML form is to add some CSS rules to your input
fields. This will add visual feedback to the validity of input fields values - while
the user is typing - such as changing the color of the border of input fields, or
green/red icons on the right of the field, as shown in the small picture at the
top right of this page.
Also, at the time of submitting the form, some extra messages may be
displayed as pop up text bubbles.
For example, Firefox 15+ provides default feedback on the input field's border
(red = invalid, green = ok). This default behavior can be overridden by CSS
rules as illustrated in the section about new input type attributes.
Try the online example with different Web browsers, both with and without the
CSS rules. See the differences between FireFox/Chrome/Opera in the default
visual feedback behavior. Don't worry: all default behavior can be overridden if
you provide your own CSS rules.
Safari and old browsers will still need a polyfill as of June 2015 (see the
different polyfills at the end of this page).
The rule at line 1 says that any time we click on an input field, it will enlarge
itself to the right, while the rule at line 4 will make it animated.
The rules at lines 8 and 11 target the input fields with a required attribute.
They will change the background by displaying a small green or red icon,
corresponding to the valid/invalid status of the input field.
Try the online example at JS Bin, or try it here in your browser (type invalid
values and look at the custom messages):
Extract from source code:
1. <form class="myForm">
2. <fieldset>
3. <legend>Type invalid values and see the result</legend>
4. <label for="myEmail" class="formLabel">E-mail:</label>
5. <input type="email" id="myEmail"
6. title="You don't know what an email address looks like, do you?"
7. required/><br>
8. ...
9. <button>Submit form</button><br />
10. </fieldset>
11. </form>
Beware: browser implementations differ. Chrome, IE, Opera (as of June 2015)
will display the title attribute value in error message bubbles when the form
is submitted, while Safari and FireFox (desktop and mobile) will simply ignore
it.
You must also take care of the different languages, otherwise you will get error
message bubbles that show some parts in the local language, and the message
from the title attribute "as is".
How can we change the style of these bubbles (for example, to unify the look
and feel between different browsers)? Unfortunately we can’t.
However, beware! While this tutorial shows some very good tricks about the
look'n'feel, it also unfortunately shows a very common mistake:
The "for" attribute of a <label> has to match the "id" attribute of the related
input, not the "name" attribute!
Typical use
Example of password checking at JS Bin, be careful to try this example in JS
Bin standalone mode (click the small black arrow on the top right of the output
tab).
At lines 17 and 20 we added an input event listener: each time a key is typed,
the checkPasswords()function is called.
Lines 28 and 29 get the input fields' values, and lines 31-35 check if the
passwords are the same and set the validity of the field using the validation
API's method setCustomValidity(error_message).
valueMissing
typeMismatch
patternMismatch
tooLong
rangeUnderflow
rangeOverflow
stepMismatch
valid
customError
Here is an example at JS Bin that shows how to test the different types of
validation errors, or you may try it here in your browser (enter bad values, too
big, too small, enter invalid characters, etc.):
Source code:
1. <!DOCTYPE html>
2. <html>
3. ...
4. <body>
5. <script>
6. function validate() {
7. var input = [Link]('b');
8. var validityState_object = [Link];
9.
10. if(validityState_object.valueMissing) {
11. [Link]('Please set an age (required)');
12. } else if (validityState_object.rangeUnderflow) {
13. [Link]('Your value is too low');
14. } else if (validityState_object.rangeOverflow) {
15. [Link]('Your value is too high');
16. } else if (validityState_object.typeMismatch) {
17. [Link]('Type mismatch');
18. } else if (validityState_object.tooLong) {
19. [Link]('Too long');
20. } else if (validityState_object.stepMismatch) {
21. [Link]('stepMismatch');
22. } else if (validityState_object.patternMismatch) {
23. [Link]('patternMismatch');
24. } else {
25. [Link]('');
26. }
27. }
28. </script>
29. <form class="myForm">
30. <label for="b">Enter a value between 10 and 20: </label>
31.
32. <input type="number" name="text" id="b" min="10" max="20"
33. required oninput='validate();'/>
34. <button>Submit</button>
35. </form>
36. </body>
37. </html>
The validationMessage property
It is also possible to get the validation error message, using
the validationMessage property of input fields.
1. var input = [Link]('b');
2.
3. [Link]("Validation message = " + [Link]);
This will be useful for making custom error messages. More about this topic in
the next section of the course.
Explanations:
Line 32: we added an empty unnumbered list (<ul>..</ul>) to the form, with
the CSS class="error-messages". We will use this class attribute for styling,
and hiding by default, the error messages using CSS (see lines 12-20, line 13
hides the messages by default).
Lines 97-102 look at all forms in the document and call a function that will
replace the default validation behavior for all of them:
the replaceValidationUI(form) function.
This function first disables all default behavior (no more display of
bubbles during form submission), this is done at lines 45-57.
Line 66: we add a click listener to the submit button of the current form.
Line 67 gets all invalid input fields for that form,
Lines 76-83: For each invalid field, we get the value of the name attribute of
the corresponding label, we also get the validation error message, and we build
a list item(<li>...</li>).
Line 86: Then we add this list element (a formatted error message
corresponding to an invalid input field) to the error message container.
Lines 90-93: The focus is given to the first invalid field that shows an error
message.
Week 6
However, HTML5 also comes with several APIs that are not
directly related to HTML elements, namely: the Orientation API;
the Geolocation API; most APIs related to client-side persistence;
the Web Storage API; the Web Workers API; and some other APIs
that are not in the HTML5 specification, but are related to it,
such as the GamePad API, the Web Audio API, etc.
This week, we will look at some of the most useful APIs. Others will be covered
in the HTML5 Part-2 course:
The HTML5 Cache API for making Web sites and Web applications
work offline.
The "Web Storage" API, sort of "super cookies", for storing pairs of
key/values client side. This API is useful for enabling Web sites to
save/restore their state, or for writing serverless applications. You will see a
small contact manager that stores its data locally, without the need for a
remote Web server.
The File API, that enables Web applications to work with local files.
For example, a picture editor, or media player that can work with your music
and video files - the ones on your phone or your hard disk! With this API you
will also be able to preview image files directly in your page - there is no need
to send them to a remote server.
The Geolocation API for obtaining
data such as longitude, latitude,
altitude (when available),
and speed. You will learn how to write
applications in combination with
interactive maps. You will also learn how
to guess the address of a user, for
example for pre-filling a registration
form with the city, country, and zip code that corresponds with the current
location.
Happy learning!
Meaning, it may be a video game that usually retrieves data from a Web
server, saves high scores, etc. It may be a mail application (like Gmail) that
shows the most recent emails, checks for new ones, and has features for
composing and sending new emails, etc.
In these cases, having a controllable "cache API" helps implement things like:
When offline, you can read and compose emails, but you cannot receive or
send new emails.
A more complex behavior would be that, when offline, you can write emails
that will be stored locally on the client side and sent only when connectivity is
available.
Or, in a static Web site, everything can be retrieved from the cache, so that a
user is able to read the Web site offline, but the login page will not be
available... instead, a disclaimer page will be displayed, etc.
The HTML5 cache tries to address aspects of these needs, and is pretty useful
for mobile Web applications, where connections are not always
available/reliable.
Using the HTML5 cache is both useful for mobile applications, as these device
can often be offline, and for traditional Web developers who do not specifically
target mobile devices. Any Web site (even comprised 100% of static
pages/images/videos/etc.) can benefit from being intelligently cached, as the
HTML5 cache can dramatically decrease the load time for any given site,
especially if the same browser/person visits the Web site regularly, as
illustrated by these pictures below (borrowed from a MSDN blog post about
offline applications that is worth reading):
Current support
Current support is very good, as stated by the [Link] Web site. All major
browsers - desktop or mobile - have supported the HTML5 cache since 2012.
External resources (optional, if you wish to learn
more about this topic)
Tutorials
The W3C specification about Offline Web Applications / cache
Article from [Link] about the cache API
Appcache facts: good resume of the cache
API + best practices
Tools
Cache manifest validator tool
ManifestR bookmarklet, a tool for
automatically generating a cache manifest file
1. <html manifest="[Link]">
2. ...
3. </html>
You must include the manifest attribute on every page for which you
want to cache resources (images included in the page, JavaScript files, CSS
files). The manifest file will contain lines that will dictate which image/js/css
needs to be cached, which must never be cached, etc.
The page with the manifest is de facto included in the list of files that
will be cached. This means that any page the user navigates to that
includes a manifest will be implicitly added to the application cache.
The browser does not cache a page if it does not contain the manifest
attribute. The default cache behavior, prior to HTML5, will be used (depending
on the browser versions). If you want a Web site or a Web app to work
offline, then please include a manifest in every HTML page!
The manifest attribute value is a relative path (relative to the page URL), but
an absolute URL can be used (not recommended) if it respects the same origin
policy.
1. CACHE MANIFEST
2. [Link]
3. [Link]
4. [Link]
Lines 2-4 show that a given HTML page, in which this manifest is included, asks
the browser to cache three files: the HTML page itself ([Link], cached by
default, but the specification recommends adding it to the manifest as best
practice), a CSS file [Link] and a JavaScript file [Link].
The first time you run this in Chrome, you may see the cache content with the
dev. tools (F12):
With the same example, Firefox asks if you agree to cache some data (the
sentence is in French here but it says: "This Web site would like to save data on
your computer for offline use. Authorize? Never? Just for this time?"):
Let's have a look at another example of [Link] (this one comes
from the [Link] Web site), that does a little more:
1. CACHE MANIFEST
2. CACHE:
3. #images
4. /images/[Link]
5. /images/[Link]
6. #pages
7. /pages/[Link]
8. /pages/[Link]
9. #CSS
10. /style/[Link]
11. #scripts
12. /js/[Link]
13. FALLBACK:
14. / /[Link]
15. NETWORK:
16. [Link]
The CACHE section specifies the URLs of the resources that must be
cached (generally relative to the page, but they can also be absolute and
external, for example for caching jQuery from a Google repository, etc.). These
resources will be 1) cached when online, and 2) available from the cache when
offline.
Using a wildcard * in this section is also common practice; this means "do not
cache all files that are not in the CACHE or FALLBACK section":
1. NETWORK:
2. *
Partial URLs may also be used in this section, such as "/images", which means,
all URLs that end with images/*... should not be cached. Notice that wildcards
and partial URLs are not allowed in the CACHE section, where all individual
files must be explicitly specified.
1. /images/ /images/[Link]
... tells us that all images in the sub-directory "images" relative to the Web
page that includes the manifest, if unavailable in the cache when the browser
is offline, will be replaced by an image named "[Link]".
What to cache?
Do you need to cache resources included by your
CSS/JavaScript files, etc.?
If your CSS files use @import or include some external pictures, you need to
explicitly add them one by one to the manifest file. The same applies to your
JavaScript files: if they include other files, and you want them to be added to
the cache, you must add them one by one to the manifest file. This can be
tricky, so fortunately there are several tools to help you generate a manifest
file. More on these in the next unit of this course section.
However, the specification, , says that for Web sites accessible only
through https:// secure connections, the same origin policy should apply.
Only resources from the same domain, when referenced by [Link] should
be cached.
In fact, some browsers, such as Google Chrome, do not adhere to this part of
the specification and also cache resources referenced by [Link] It has been
argued that the single origin policy for https is too restrictive in the real world
for app caching to be of genuine value.
Useful tools for generating or validating
a manifest file
If a user visits your Web site and if this Web site asks
to be cached, and if there is no more free space
available, the browser will find some (in general by
asking the user permission to increase the cache size
limit for the current domain - see screenshots-, or by
clearing least recently used data). On mobile devices, the cache size limits are
lower but reasonable.
With some atypical applications that need to cache large amounts of data
(images, videos), there may indeed be inadequate space in the cache. In this
case, the browser prints an error message in the console. It's also possible to
use a JavaScript API to detect this situation and show the user an error or a
warning message in the page "Sorry, this Web site will not be available offline
as we could not cache it due to size limitations...". This advanced part will not
be covered in this course.
Anyway, if you wish to find out more about size limits and what the various
HTML5 persistence mean, please read the rest of this page. As such, there will
be no exercises related to the optional content material below!
For example, with Chrome there is no maximum size limit for cached data (it is
computed depending on the configuration and on the current amount of data
already persisted). But if you use the LocalStorage persistence for storing
data, (see next section of this course), then, for this special kind of data,
Chrome applies a 10Mbytes per domain limit. And this is completely different
on FireFox, on Safari, etc. The W3C specification recommends at least 5Mbytes
per domain with support for at least 20 domains.
We recommend reading this article from HTML5 rocks (January 2014). The
author wrote a Web application that tries to fill all available space and "guess
how the different persistent storage spaces" are managed by different
browsers. He tried with all major browsers on mobile devices and on desktop.
On the right: a screenshot of some of the resulting measures (extract from the
above article).
Also, for greater detail, see this paper about "Managing HTML5 offline storage".
A quota management
JavaScript API exists!
In order to make Web
applications aware of the free
space available for persisting
their data, a Quota Management
API is being developed. Note that this API specification is under active
discussion and is subject to change in the future. It's still experimental.
Try this example on JS Bin that shows the available disk space for all HTML5
persistence means (cache, localStorage, IndexedDB, etc.). Try it with Google
Chrome: as of June 2015, it is the only browser that implements the Quota API.
1. function showFreeSpace() {
2. //the type can be either TEMPORARY or PERSISTENT
3. [Link]([Link],
4. onSuccess, onError);
5. }
6.
7. function onSuccess(usedSpace, remainingSpace) {
8. var displaySpace = [Link]("#space");
9. [Link] = "Used space = " + usedSpace + ", remaining
space = "
10. + remainingSpace;
11. }
12.
13. function onError(error) {
14. [Link]('Error', error);
15. }
Applications from stores or applications that run on a
Web-based operating system
A note about "non traditional Web applications"
1. <!DOCTYPE html>
2. <html lang="en">
3. <head>
4. <meta charset=utf-8>
5. <title>HTML5 Demo: Online connectivity monitoring</title>
6. </head>
7. <body>
8. <header>
9. <h1>Online connectivity monitoring</h1>
10. <style>
11. #status {
12. color: #FFFFFF;
13. padding: 5px;
14. }
15. .online {
16. background: green;
17. }
18. .offline {
19. background: red;
20. }
21. </style>
22. </header>
23. <article>
24. <p>Current network status (try to disconnect wifi or unplug
25. your ethernet cable):
26. <span id="status">checking...</span>
27. </p>
28. <ol id="state"></ol>
29. </article>
30. <script>
31. var statusElem = [Link]('status'),
32. var state = [Link]('state');
33. function online(event) {
34. [Link] = [Link] ? 'online' : 'offline';
35. [Link] = [Link] ? 'online' : 'offline';
36. [Link] += '<li>New event: ' + [Link] + '</li>';
37. }
38. [Link]('online', online);
39. [Link]('offline', online);
40. // call the online function so that it refreshes display when
41. // the page is first loaded
42. online({ type: 'ready' });
43. </script>
44. </html>
Usually, one checks if the application is running in online or offline mode (in the
latter case, data may be retrieved from the client side using one of the various
methods presented in this week's course). Instead of displaying messages
(lines 41-42 in the code source shown above), you should use an
implementation like this:
1. [Link]('online', function(e) {
2. // Re-sync data with server.
3. }, false);
4. [Link]('offline', function(e) {
5. // Queue up events for server, store them on the browser side
6. }, false);
Example 1: a form that never loses what you entered, even if you reload
'Michel' if this value has been previously saved as in the example from the
line above.
Open this online example at JS Bin, and use F12 or cmd-alt-i (Mac OS) to
look at the dev. tools. As you type in the different input fields, their content
order to save the first name input field's content, we just added:
1. oninput="[Link]=[Link];"
Where firstName in red is the key and [Link] the current value of
In the same way, we added an input listener to all the input fields in this
example's form.
Restoring the form content on page load/reload
be called each time the page is loaded. In this function, we will read the
Complete example on JS Bin: enter data and press reload at any time. The
The tests at lines 7, 10, 13, etc., verify that data has been saved, before
trying to restore it. Without these tests, it would put the "undefined" string
As you can easily guess from the above, we use var value = getItem(key) to
retrieve a key's value and setItem(key, value) to set it. This is similar to
what we saw in the examples of the page above, except that this time:
Note that it will probably only be the rare occasion that you will want the entire
store to be cleared by the user in production software (since that effectively
deletes their entire data). However, it is a rather a common operation needed
during development, since bugs may store faulty data the persistence of which
can break your application, since the way you store data may evolve over time,
or simply because you also need to test the experience of the user when first
using the application.
Observant students will note that something seems a bit off in the example
above: instead of calling [Link](k), we simply
access localStorage[k]. Why? Because keys in the local store can also be
accessed as if the store were a simple JavaScript object. So instead
of [Link]("foo") and [Link]("foo",
"bar"), one can write [Link] and [Link] = "bar". Of
course there are limitations to this mapping: any string can serve as a key, so
that [Link]("one two three") works, whereas that string
would not be a valid identifier after the dot (but it could still work
as localStorage["one two three"]).
Example that
shows all the
methods of the
local storage API in
action
Online example at JS Bin, run
it, then click on the first
button to show all key/values
in the localStorage. Open
the URL in another tab, and
see that the data is shared between tabs, as local stores are attached to an
origin.
Then click on the second button to add data to the store, click on the third to
remove data. Finally, the last one clears the whole data store.
Source code:
1. <!DOCTYPE html>
2. <html lang="en">
3. <head>
4. <meta charset=utf-8 />
5. <title>Example of localStorare API use</title>
6. <script>
7. // Using localStorage
8. var counter = [Link]("count") || 0;
9. counter++;
10. [Link]("count", counter);
11. function getCountValue() {
12. // retrieve data
13.
[Link]("#counter").innerHTML = [Link];
14. }
15. function seeAllKeyValuePairsStored() {
16. // clear list first
17. [Link]('#list').innerHTML="";
18. for (var i = 0, n = [Link]; i < n; i++) {
19. var key = [Link](i);
20. var value = localStorage[key];
21. [Link](key + ": " + value);
22. var li = [Link]('li');
23. [Link] = key + ": " + value;
24. [Link]('#list').insertBefore(li, null);
25. }
26. }
27. function resetStore() {
28. // erase all key values from store
29. [Link]();
30. // reset displayed list too
31. [Link]('#list').innerHTML="";
32. }
33. function addSomeData() {
34. // store data
35. [Link] = "Buffa";
36. [Link] = "Michel";
37. // refresh display
38. seeAllKeyValuePairsStored();
39. }
40. function removeSomeData() {
41. // store data
42. [Link]("lastName");
43. [Link]("firstName");
44. // refresh display
45. seeAllKeyValuePairsStored();
46. }
47. </script>
48. </head>
49. <body onload="getCountValue()">
50. <h1>Number of times this page has been seen on this
browser: <spanid="counter"></span></h1>
51. <button onclick="seeAllKeyValuePairsStored()">Show all key value
pairs stored in localStorage</button><br/>
52. <output id="list"></output>
53.
54. <button onclick="addSomeData()">Add some data to the
store</button><br/>
55. <button onclick="removeSomeData()">Remove some
data</button><br/>
56. <button onclick="resetStore()">reset store (erase all key/value
pairs)</button>
57. </body>
58. </html>
You can check in the Chrome dev. tools user interface that the content of
the localStorage changes as you click on the buttons.
Practical example 2: save/restore
user's preferences
Introduction
Local stores are also useful for saving/restoring user preferences of Web
Applications. For example, the JS Bin tool you have been using since the
beginning of this course uses localStorage to store the list of tabs you open,
and their width:
In this way, the next time you come back to JS Bin, "it will remember your last
settings".
Another example is a guitar FX processor / amp simulator your instructor is
writing with some of his students. It uses localStorage to save/restore presets
values:
We would like to save the current values and find them back as they were
when we come back to the page.
Here is a modified example that saves/restores its state, you can try it at JS
Bin. In this modified version of the animated rectangle example, you can set
the color, size, speed, etc. And if you reload the page, the state of the different
input field is restored, but also the internal variables. Check the source code in
the JS Bin example and read the following explanations.
We used the same generic code for saving/restoring input fields' values we saw
in the first example that used localStorage. The only difference is that we
renamed the two generic functions so that they correspond better to their role
here (instead of saveFormContent we called the
function restorePreferences).
1. function initPreferences() {
2. [Link]("Adding input listener to all input fields");
3. // add an input listener to all input fields
4. var listOfInputsInForm = [Link]("input");
5. for(var i= 0; i < [Link]; i++) {
6. addInputListener(listOfInputsInForm[i]);
7. }
8. // restore preferences
9. restorePreferences();
10. applyGUIvalues(); // Use the input fields' values we just restored to set
internal
11. // size, incX, color, lineWidth variables
12. }
13.
14. function addInputListener(inputField) {
15. // same as before
16. }
17.
18. function restorePreferences() {
19. // same as old restoreFormContent
20. }
21.
22. function applyGUIvalues() {
23. // Check restored input field content to set the size of the rectangle
24. var sizeWidget = [Link]("size");
25. size = [Link](incX)*parseInt([Link]);
26. // also update the outline element's value
27. [Link]("sizeValue").innerHTML = size;
28. // Check restored input field content to set the color of the rectangle
29. var colorWidget = [Link]("color");
30. [Link] = [Link];
31. // Check restored input field content to set the speed of the rectangle
32. var speedWidget = [Link]("speed");
33. incX = [Link](incX)*parseInt([Link]);
34. // also update the outline element's value
35. [Link]("speedValue").innerHTML = [Link](incX);
36. // Check restored input field content to set the lineWidth of the
rectangle
37. var lineWidthWidget = [Link]("lineWidth");
38. [Link] = parseInt([Link]);
39. }
Furthermore, we removed all input listeners in the HTML, making it cleaner (no
more oninput="[Link] = [Link];'...)
Source code:
1. function addInputListener(inputField) {
2. [Link]('input', function(event) {
3. [Link]([Link], [Link]);
4. }, false);
5. }
In this function, we first get the list of input fields (line 5), then iterate on it
(line 14). For each input field, we get its id, which value is the key
in localStorage for the previous data saved for this field (lines 15-16). Then if
the value is not undefined, we restore it by setting the value of the input field
(lines 19-20).
These generic functions can be used in many
different projects
Indeed, if you look carefully, you will see that these functions are really useful.
You may easily embed them in your own projects, or perhaps adapt them for a
particular need (i.e. for saving input type="checkboxes" that work a bit
differently), etc. Later in the course, we will show how to reuse them with
another example: the animated red rectangle.
Size limitation,
security, localStorage or sessionSto
rage?
We have already talked about client-side storage limits when we studied the
HTML5 cache. We saw that the limit varies depending on various parameters.
However, it's good to recall a few things from the specification:
User agents (browsers) should limit the total amount of space allowed for
storage areas.
User agents may prompt the user when quotas are reached, allowing the user
to grant more space to a site. This enables sites to store many user-created
documents on the user's computer, for instance.
User agents should allow users to see how much space each domain is using.
A mostly arbitrary limit of five megabytes per origin is recommended
(translation: give at least 5Mb per origin).
In many cases, local storage is all that your application will need for
saving/loading data on demand. More complex ways to do it exist, such as
IndexedDB, a No SQL database, that proposes transactions and usually
comes with far more available space than local storage. IndexedDB usage is for
advanced users and will be covered in the HTML5 part-2 course.
Additionally, there will be a limit on the amount of data that you can store
there. Browsers enforce quotas that will prevent you from cluttering your users'
drives excessively. These quotas can vary from platform to platform, but are
usually reasonably generous for simple cases (around 5MB), so if you are
careful not to store anything huge there, you should be fine.
For serious applications, you might want to synchronize existing data with the
server on a regular basis, in order to avoid data loss (and in general, because
users enjoy using the same service from multiple devices at once). This is a
rather complex feat, and frameworks such as Firebase can help. Such
techniques are beyond the scope of this course and will not be covered.
Cookies' big danger: if a user has two tabs open to the same site, they will
share the same cookies. Which is to say that if you are storing information
about a given operation using cookies in one tab, that information will leak to
the other side — this can be confusing if the user is performing different tasks
in each.
There are some simple approaches, such as creating your own minimal record
format (e.g. a string with fields separated with a given character, using join()
on store and split() upon retrieval) or using multiple keys (e.g.post_17_title,
post_17_content, post_17_author, etc.). But these are really hacks. Thankfully,
there's a better way, [Link]() and [Link]() methods.
JSON provides a great way of encoding and decoding data that is a really good
match for JavaScript. You have to be careful not to use circular data structures
or non-serializable objects, but in the vast majority of cases, plugging JSON
support into your local store is straightforward.
Typical usage
1. [Link] = [Link](object); // or...
2. [Link](key, [Link](object));
Let's try a simple toy example (online at JS Bin). The example below saves a
JavaScript object in JSON, then restores it and checks that the object properties
are still there!
Source code:
1. <!DOCTYPE html>
2. <html>
3. <head>
4. <meta charset=utf-8 />
5. <title>Storing JSON Objects with Local Storage</title>
6. <script>
7. var personObject= {'firstName': 'Michel', 'lastName': 'Buffa'};
8. // Store the object as a JSON String
9. [Link]('testObject', [Link](personObject));
10. // Retrieve the object from storage
11.
var retrievedObject = [Link]([Link]('testObject'))
;
12. [Link]([Link] + "
" + [Link]);
13. // then you can use [Link],
[Link]...
14. </script>
15. </head>
16. <body>
17. </body>
18. </html>
Explanations:
Add contacts using the form, see how the HTML table is updated. Try to reload
the page: data are persisted in localStorage.
Well structured page with the new elements seen during Week 1 (section,
article, nav, aside, etc.)
HTML5 form elements with builtin and custom validation (the date cannot be
in the past, the firstName and lastName fields do not accept &, #, ! or $
characters),
localStorage for saving / restoring an array of contacts in JSON
It shows how to use the DOM API for dynamically updating the page content
(build the HTML table from the array of contacts, add a new line when a new
contact is submitted, etc.)
The File API
Introduction
The objective of this chapter is to provide an overview of the File API.
Source code:
1. <!DOCTYPE html>
2. <html lang="en">
3. <head>
4. <meta charset="utf-8">
5. <title>Example of using readAsDataURL</title>
6. </head>
7. <body>
8. <input type="file" multiple onchange="readImagesAndPreview([Link]
s);">
9. <p>
10. <div id="thumbnails"></div>
11. <script>
12. var container = [Link]("thumbnails");
13. function readImagesAndPreview(files) {
14. for(var i=0; i < [Link]; i++) {
15. var f = files[i];
16. var reader = new FileReader();
17. [Link] = function(e) {
18. var img = [Link]("img");
19. [Link] = [Link];
20. [Link] = 100;
21. [Link](img);
22. }
23. [Link](f);
24. }
25. }
26. </script>
27. </body>
28. </html>
Getting
details
about a
file:
reading
metadata
Imagine you have an input field like this:
1. Select one or more files: <input type="file" id="input"/>
This will render as a "select files" or "browse files" button. If you select one file
in the file chooser dialog that has popped up, before HTML5 you couldn't do
anything with it in the client-side: no access from JavaScript. With the File API,
you can read what we call "file metadata": name, size, type and last
modification date.
Look at the the code below: the file API defines a files property on the DOM
node corresponding to the <input type="file".../> input field. This property
is an array.
File name:
File size:
File type:
Example on JS Bin, or try it in your browser: click on the button, and select
multiple image files. Notice that in the file selector, files that are not images
will be greyed and non selectable.
...
Explanations:
Line1: we used the multiple attribute to allow the selection of multiple files in
the file chooser (using shift or control keys). The accept="image/*" attribute
is a filter that restricts selection to images only. Finally, the onchange listener
will call the filesProcess(...) function, passing as parameter the list of
selected files for the current element ([Link]).
Lines 7 and 12: we prepare the HTML code for building a <table> with the
results.
Line 10: this for loop builds all the rows that compose the table, adding HTML
code to the selectionstring variable. At the end of the loop, this variable
contains all the HTML code that corresponds to the table of results.
Line 18: the table is added to the page. We use the innerHTML attribute of the
DOM element corresponding to the <div id="result"> in order to insert the
table as its child in the DOM tree. As such, the table appears on the page
dynamically.
Blob and File: what are they?
The HTML5 File API specification introduces several
new Interfaces
The FileList interface (we already met it:
the files property is aFileList),
the File interface that is useful for getting
details about a file (thefile variable in
the for loop of the last example illustrates
this) .
the Blob interface helps read binary data
(only) that is accessed slice by slice (as
chunks of data, each one being a "Blob"),
and a FileReader interface for reading file
content (we will see how to use it in the next
section of the course),
Blob objects have two properties, namely:size and type, which respectively
retrieve the size in bytes of the data handled by the Blob and their MIME type.
There is also a method called slice(), but this is not used in common
applications. If you are curious, check the "slicing a file" section of this
"Reading files in JavaScript using the File APIs" article.
The File object
File objects are useful for
manipulating... files! They
inherit the properties and
methods of Blob objects, and
have two additional properties
that are name, for the file name,
and lastModifiedDate to get the
date of the last modification of
the file (in the form of a
JavaScript Date object,
obviously) .
Most of the time, we will work with File objects. Blobobjects will have real
interest when the Filesystem API is widely available (at the moment there is
only an experimental version in Chrome), or when you download binary files
using Ajax (see example below). This last API will be covered in the HTML5
part-2 course.
[Advanced] If you are interested in seeing how Blob objects can be used, here
is an example "as is" that shows how to download an image using Xhr2 (Xml
Http Request version 2). The examples uses a <progress>element to show the
download progress, and uses [Link] = 'blob'; to indicate that
the file we are going to download is a binary file (a blob). Try the example, then
comment the line with responseType='blob'. In this case, you will notice that
the image file is not properly decoded by the browser and is not displayed in
the page. Xhr2 will be covered in the HTML5 part-2 course.
All these methods take as a unique parameter a File object (for example, a file
chosen by a user after clicking on a <input type=file> input field). Below, we
use, as an example, the readAsText method:
1. function readFileContent(f) {
2. // Executed last: called only when the file content is loaded, [Link]
is
3. // The content
4. [Link] = function(e) {
5. var content = [Link];
6. // do something with the file content
7. [Link]("File " + [Link] + " content is: " + content);
8. };
9. // Executed first: start reading the file asynchronously, will call the
10. // [Link] callback only when the file is read entirely
11. [Link](f);
12. }
The above code shows how a file can be read as text. The function is called, for
example by clicking on the button corresponding to a <input type="file"
id="file" onchange="readFileContent([Link])"/>, and by choosing
a file.
Line 12 is executed first, and asks the Reader object to read the file f as text.
As this takes some time, it's an asynchronous operation that will be executed
by the browser in the background. When the file is read,
the [Link] callback function is called.
Line 4 is executed after line 12, and is called only when the file content is
available. This callback takes an event e as a unique parameter,
and [Link] is the file content.
Try a variation of the above code in your browser, that displays the file content
in a text area. This example is detailed further in the course. Click and select a
text file below:
In following next course sections, we will look at different examples that read
file contents as text, dataURL and binary.
This example is the one at the end of the previous page. This time, we show
the complete source code above. Remember that the instruction at line 29 is
executed first, then when the file is read, the browser will call asynchronously
the onload callback at line 20.
Source code:
1. <!DOCTYPE html>
2. <html lang="en">
3. <head>
4. <meta charset="utf-8">
5. <title>Example of use of FileReader with a text file</title>
6. </head>
7. <body>
8. <label for="files">Choose multiple text files:</label>
9. <input type="file" id="files"
10. multiple onchange="readFilesAndDisplayAsText([Link]);"/><br/>
11. <p>
12. <textarea rows=30 cols=50 id="filesContent"></textarea>
13. <script>
14. var filesContent = [Link]("filesContent");
15. function readFilesAndDisplayAsText(files) {
16. [Link]("dans read files");
17. // Loop through the FileList
18. for (var i = 0, f; f = files[i]; i++) {
19. var reader = new FileReader();
20. // Add an onload listener to the reader
21. addOnLoadListener(reader, [Link]);
22. // start reading, will call the listener later, when the file f is read
23. [Link](f);
24. }
25. }
26. function addOnLoadListener(reader, name) {
27. // Add an onload listener that will be able to print the name of the
28. // file...
29. [Link] = function(e) {
30. [Link] += "###### READING FILE " + name + "
######";
31. [Link] += [Link];
32. };
33. }
34. </script>
35. </body>
36. </html>
Explanations:
This example is similar to the previous one, except that this time we read
multiple files.
Line 20: this is the for loop that will iterate on the files object passed as
parameter by the onchangelistener declaration at line 10
Line 25: instead of declaring the onload listener with a [Link] =...
directly in the loop, this time we preferred to write a separate function that will
do this. This technique is useful when you want the listener to work with extra
variables computed in the loop (in our case, the name of the file).
Introduction
This method is rarely used, except for loading "raw" binary data. For
images you would like to see in your HTML page using the <img src=
tag> or for drawing in a canvas, or for audio and video files that you
of the course.
readAsArrayBuffer is often used for purposes such as reading audio
samples that should be loaded in memory and played using the WebAudio
API, or for loading textures that you will use with WebGL for 3D animations.
Example 1: read a local audio file and play it with the WebAudio API
The WebAudio API is useful for reading audio sound samples from memory
(no streaming), and has been designed for music application and games.
This example shows how a local audio file can be read and played directly
Example on JS Bin (does not work on IE, as it does not support the
Explanations:
Line 11: when a user chooses a file, the listener will be executed. Line 11
will start the reading of the file content, as a binary file (this is
browser.
Line 7 is the onload callback, executed when the file content is loaded in
memory. We pass the file content to the initSound function (see JS Bin
example for complete source code) that uses WebAudio to decode it (it
1. data:image/
png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHEl
EQVQI12P4//8/
w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==
This data URL in a browser address bar should look like this:
If we set the src attribute of an image element <img
src="data:image/png...."> with the data URL of the above screenshot, it will
work exactly as if you used a URL that started with http://
In your browser, you will see a small red circle rendered by this source code:
1. <img src="data:image/
png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA
2. AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
3. 9TXL0Y4OHwAAAABJRU5ErkJggg==" alt="Red square" width=50
height=50/>
This dataURL format enables file content to be stored in a base64 format (as a
string), and adds the MIME type specification of the content. The dataURL can
therefore store a file as a URL readable with modern browsers. It is becoming
more commonly used on the Web, especially for mobile applications, as inlining
images reduces the number of HTTP requests and makes the Web page load
faster.
You will find lots of Web sites and tools for generating dataURL from files, such
as the DataURL maker Web site (screenshot below):
With the above example, you can copy and paste the characters on the left and
use them with an <img src="...">. Just set the src attribute with it!
Notice that you can encode any type of file as dataURL, but this format is most
frequently used with media files (images, audio, video).
Explanations:
Line 35: starts the reading of the file f. When f is read, the onload callback
will be called.
Lines 25-31: we build, using the DOM API, a <span
class="thumb">...</span> and inside we add an<img src=the data
url> element with its src attribute equal to the url of the image that has been
read (the image content as dataURL is in [Link]). Finally, at line 31,
we insert the span in the document before the current children of the <output
id="list"> element (declared at line 5).
1. function drawImage(imageFile) {
2. var reader = new FileReader();
3.
4. //capture the file information.
5. [Link] = function(e) {
6. // For drawing an image on a canvas we
7. // need an image object
8. var img = new Image();
9. // Even if the file has been read, decoding
10. // the dataURL format may take some time
11. // so we need to use the regular way of
12. // working with images: onload callback
13. // that will be called after setting the src attribute
14. [Link] = function(e) {
15. // draw the image!
16. [Link](img, 0, 0, 400, 400);
17. }
18. // [Link] is the dataURL, so we set the
19. // src if the image with it. This will call
20. // asynchonously the onload callback
21. [Link]= [Link];
22. };
23. // Read in the image file as a data URL.
24. [Link](imageFile);
25. }
26. function readFileAndDraw(files) {
27. drawImage(files[0]);
28. }
Explanations:
Try this example online on gitHub (or click the screenshot below)
The Geolocation API
Let's start with an example!
Click the button to get your position and display a map as a picture.
This may take some time, or fail, if a geolocation is not available with
the device and connection you are using (e.g. at work, beyond a
Introduction
This chapter presents the new Geolocation API
and illustrates its use with several examples.
It is possible to prompt the user to activate the GPS (this is what most GPS
navigation software does on mobile phones), or ask for a particular mean
among those available. It is also possible to track the current position when it
changes. This is useful for writing a navigation application or for tracking in real
time the position of different participants in the case of an application that
involves several persons at the same time (using WebSockets, for example).
Typical use
1. [Link](showPosition, onError);
2.
3. function showPosition(position) {
4. [Link]("latitude is: " + [Link]);
5. [Link]("longitude is: " + [Link]);
6. }
7.
8. function onError(err) {
9. [Link]("Could not get the position");
10. }
This online example at JS Bin shows how to get the current longitude and
latitude and display them in an HTML page. Try it below in your browser:
1. <!DOCTYPE html>
2. <html lang="en">
3. <head>
4. <title>Basic example of use of the geolocation API</title>
5. </head>
6. <body>
7. <p id="msg">Click the button to get your coordinates:</p>
8. <button onclick="getLocation()">Where am I ?</button>
9. <script>
10. var displayCoords=[Link]("msg");
11. function getLocation() {
12. if ([Link]) {
13. [Link](showPosition);
14. } else {
15. [Link]="Geolocation API not supported by your
browser.";
16. }
17. }
18. function showPosition(position) {
19. [Link]="Latitude: " + [Link] +
20. "<br />Longitude: " + [Link];
21. }
22. </script>
23. </body>
24. </html>
Explanations:
Line 14 checks if the Web browser supports the geolocation API by testing the
[Link]. If not null, then the geolocation API is
supported.
Line
15 calls [Link](showPosition) passin
g a callback function as a parameter (in this example we did not specify a
callback in case of error). When a current position is available, the
callback function will be called asynchronously, and the input
parameter of this callback function will be the current position, like in
the function showPosition(position) of the example.
Line 22: the position objects has a coords property that is the object that
holds the longitude and thelatitude.
External resources:
The W3C specification about the geolocation API (in Recommendation status,
aka, Web standard)
Good article from the Opera dev Web site
Excellent tutorial on the Google Maps API. Some examples in this part of the
course are illustrated using Google Maps.
accuracy The accuracy of the measure of the longitude and latitude (in
meters)
Not all these values may be available in all Web browsers. When one of these
properties is null, it means that it is not available.
1. <!DOCTYPE html>
2. <html lang="en">
3. <head>
4. <title>Basic example of use of the geolocation API</title>
5. </head>
6. <body>
7. <p id="msg">Click the button to get your coordinates:</p>
8. <button onclick="getLocation()">Where am I ?</button>
9. <script>
10. var displayCoords=[Link]("msg");
11. function getLocation() {
12. if ([Link]) {
13.
[Link](showPosition, errorPositio
n);
14. } else {
15. [Link]="Geolocation API not supported by your
browser.";
16. }
17. }
18. function showPosition(position) {
19. [Link]="Latitude: " + [Link] +
20. "<br />Longitude: " + [Link];
21. }
22. function errorPosition(error) {
23. var info = "Error during geolocation: ";
24. switch([Link]) {
25. case [Link]:
26. info += "Timeout !";
27. break;
28. case error.PERMISSION_DENIED:
29. info += "Permission denied, geolocation could not be obtained...";
30. break;
31. case error.POSITION_UNAVAILABLE:
32. info += "Location could not be obtained though the available
means...";
33. break;
34. case error.UNKNOWN_ERROR:
35. info += "Unknown error";
36. break;
37. }
38. [Link] = info;
39. }
40. </script>
41. </body>
42. </html>
Tracking a position in real time
Introduction
In order to track the current position, the geolocation API provides a method
similar to the getCurrentPosition(onSuccess,
onError) named watchPosition(onSuccess, onError).
It gets the callback function only when the current position changes.
If you stay in the same location, the callback function won't be called
regularly.
It returns an id so that you can use the clearWatch(id) method to stop the
current tracking.
Typical use
1. // get an id of the current tracking, the showPosition callback is like the one we
saw in earlier examples.
2. var watchPosId = [Link](showPosition);
3. ...
4. // stop the tracking
5. [Link](watchPosId);
External resource
An article on [Link] that shows how to write a simple trip meter
using the geolocation API: in particular, you will find a JavaScript function that
computes the distance (in meters) between two positions defined by their
longitude and latitude.
Options available when using the geolocation API, in
particular real time tracking
Several options are available when using HTML5 geolocation. We can pass a
third parameter to the getCurrentPosition and watchPosition methods, that
will hold one or several of the following options:
timeout The maximum time (in milliseconds) for which you are
prepared to allow the device to try to obtain a Geo location.
After this timeout value has elapsed, the onError callback is
called.
2. [Link](onSuccess, onError,
3. {enableHighAccuracy:true});
4. // maximumAge = 10 mins, the position can be cached for 10 mins,
5. // useful when in tunnels...When the device tries to get
6. // a position, if it does not succeed, then go on error
7. // immediately
8. [Link](onSuccess, onError,
9. {maximumAge:600000, timeout:0});
10. // Position will never come from the cache (maximumAge: 0), and
11. // if after 0.1s the position could not be computed, then go on
12. // error
13. [Link](onSuccess, onError,
14. {maximumAge:0, timeout:100});
15. // Ask for GPS, cache for 30s, 27s before going on error...
16. watchId=[Link](onSuccess, onError,
17. {enableHighAccuracy:true, maximumAge:30000, timeout:27000});
The following three examples increase in complexity, but most of the code is
reused and adapted without even reading the Google documentation about the
different APIs.
It also illustrates the use of the error callback from the previous section. The
Google Map API is used to get an image centered at the longitude and latitude
collected with the HTML5 Geolocation API.
1. <!DOCTYPE html>
2. <html>
3. <body>
4. <p id="demo">Click the button to get your position:</p>
5. <button onclick="getLocation()">Try It</button>
6. <div id="mapholder"></div>
7. <script>
8. var x=[Link]("demo");
9.
10. function getLocation() {
11. if ([Link]) {
12. [Link](showPosition,showError);
13. } else{
14. [Link]="Geolocation is not supported by this browser.";
15. }
16. }
17.
18. function showPosition(position) {
19. // Google map API needs the latitude and longitude separated by a
comma
20. var latlon=[Link]+","+[Link];
21. // Google map API URL that returns an image centered on the longitude
and latitude
22. var img_url="[Link]
center="
23. +latlon+"&zoom=14&size=400x300&sensor=false";
24. [Link]("mapholder").innerHTML="<img
src='"+img_url+"' />";
25. }
26.
27. function showError(error) {
28. ...
29. }
30. </script>
31. </body>
32. </html>
The magic occurs at line 23, where we use the Google Static Map API.
Example 2 (a bit more complicated...) that shows
how to display an interactive Google map centered
on the current position
This example is just given "as is", as there are so many possibilities for
rendering a map with the Google Map API. However, we think having such a
basic example might be useful.
1. <!doctype html>
2. <html>
3. <head>
4. </head>
5. <body>
6. <!-- for position display -->
7. <div id="myposition"></div>
8.
9. <!-- for gmap display -->
10. <div id="map" style="width:640px;height:480px"></div>
11.
12. <!-- get gmap API -->
13. <script src="[Link]
script>
14.
15. <script>
16. // Default position
17. var centerpos = new [Link](48.579400,7.7519);
18.
19. // default options for the google map
20. var optionsGmaps = {
21. center:centerpos,
22.
navigationControlOptions: {style: [Link]
},
23. mapTypeId: [Link],
24. zoom: 15
25. };
26.
27. // Init map object
28. var map = new [Link]([Link]("map"), o
ptionsGmaps);
29.
30. if([Link]) {
31.
32. // callback function, called by getCurrentPosition() in case of success
33. function drawPosition(position) {
34. var infopos = "Got position : <br>";
35. infopos += "Latitude : "+[Link] +"<br>";
36. infopos += "Longitude: "+[Link]+"<br>";
37. infopos += "Altitude : "+[Link] +"<br>";
38. [Link]("myposition").innerHTML = infopos;
39.
40. // Make new object LatLng for Google Maps
41. var latlng = new [Link]([Link],
42. [Link]);
43.
44. // Add a marker at position
45. var marker = new [Link]({
46. position: latlng,
47. map: map,
48. title:"You are here"
49. });
50. // center map on longitude and latitude
51. [Link](latlng);
52. }
53.
54. // callback function, called by getCurrentPosition() in case of error
55. function errorPosition(error) {
56. ...
57. }
58. [Link](drawPosition,errorPosition);
59. } else {
60. alert("Geolocation API not supported by your browser");
61. }
62. </script>
63. </body>
64. </html>
1. <!DOCTYPE html>
2. <html lang="en">
3. <head>
4. <script src="[Link]
v=[Link]&sensor=false"></script>
5. <script>
6. // p elements for displaying lat / long and address
7. var displayCoords, myAddress;
8. // used with the google apis
9. var geocoder;
10. var map;
11. var infowindow = new [Link]();
12. var marker;
13. // Called when the page is loaded
14. function init() {
15. displayCoords=[Link]("msg");
16. myAddress = [Link]("address");
17. geocoder = new [Link]();
18. // In order to show something even before a user clicks on the button
19. var latlng = new [Link](34.0144, -6.83);
20. var mapOptions = {
21. zoom: 8,
22. center: latlng,
23. mapTypeId: 'roadmap'
24. }
25.
map = new [Link]([Link]('map_canvas'), ma
pOptions);
26. } // end of init()
27. // Called when the button is clicked
28. function getLocation() {
29. if ([Link]) {
30. [Link](showPosition);
31. } else {
32. [Link]="Geolocation API not supported by your
browser.";
33. }
34. }
35. // Called when a position is available
36. function showPosition(position) {
37. [Link]="Latitude: " + [Link] +
38. "<br />Longitude: " + [Link];
39. // Display the map
40. showOnGoogleMap(new [Link]([Link],
41. [Link]));
42. }
43. function showOnGoogleMap(latlng) {
44. // Ask google geocoder for an address once we get a longitude and
45. // a latitude. In fact, the reverse geocoder sends back an array of
"guesses"
46. // i.e. not just one address object, but several. Each entry in this array
47. // has several properties such as street, city, etc. We use the
"formatted_address"
48. // one here, but it might be interesting to get the detailed properties in
other
49. // applications like a form with street, city, zip code etc.
50. [Link]({'latLng': latlng},reverseGeocoderSuccess);
51. function reverseGeocoderSuccess(results, status) {
52. if (status == [Link]) {
53. if (results[1]) {
54. [Link](11);
55. marker = new [Link]({
56. position: latlng,
57. map: map
58. });
59. [Link](results[1].formatted_address);
60. [Link](map, marker);
61. // Display address as text in the page
62. [Link]="Adress:
" + results[0].formatted_address;
63. } else {
64. alert('No surface address found');
65. }
66. } else {
67. alert('Geocoder failed due to: ' + status);
68. }
69. } // end of reverseGeocoderSuccess
70. } // end of showOnGoogleMap
71. </script>
72. </head>
73. <body onload="init()">
74. <title>HTML5 + Geolocalisation + Google Maps API Reverse
Geocoding</title>
75. <p id="msg">Click the button to get your coordinates:</p>
76. <p id="address"></p>
77. <button onclick="getLocation()">Where am I ?</button>
78. <div id="map_canvas" style="width: 500px; height: 300px"></div>
79. </body>
80. </html>
In this section, we will see how we can get the different parts of the responses
(city, street, zip code, country, etc.) The reverse geocoding service tries to
guess what is the "best" address that matches the longitude and latitude, but
sometimes the first guess is not the best one.
Look at this line of code from the last example from the previous page - the
example that showed the address when you clicked on the button:
It's very hard to create a single code that will work in all situations and in all
countries, since postal addresses are formatted differently depending on the
country. A decoder that works well 99% of the time in the UK may be wrong for
Australia, for instance. So, it's just a "guess system", and in real life, if you
create a Web site and would like to help the user with completing a form, just
fill in the country, city, postal code, and suggest the rest, propose a small icon
for deleting the street input field content, etc. You could also add a drop down
menu that offers not only the first guess but the second and third, etc.
1. function showOnGoogleMap(latlng) {
1. ...
1. // Display address as text in the page
2. [Link]="Adress: " + results[0].formatted_address;
3. // Call the function that parses the results and fills
4. // the input fields
5. parseResult(results[0].address_components);
6. ...
7. }
8. var country, postalCode, state, route, streetNumber, locality, areaLvl
1, areaLvl2;
9. function parseResult(result) {
10. for(i in result){
11. // Let's print all the data we can collect from the reverse geocoder,
12. // Look at the debug console to see what we get...
13. [Link]("type = " + result[i].types[0] + " long_name = " +
14. result[i].long_name);
15.
16. if(result[i].types[0] == 'postal_code')
17. postalCode = result[i].long_name;
18. ...
19. // fill input fields now, check if variables are undefined
20. if((route != undefined) && (streetNumber != undefined)) {
21. [Link]("let's fill the street");
22. [Link]("#address1").value = streetNumber + "
" + route;
23. }
24. if(locality != undefined) {
25. [Link]("let's fill the city");
26. [Link]("#address2").value = locality;
27. }
28. if(country != undefined) {
29. [Link]("let's fill the country");
30. [Link]("#country").value = country;
31. }
32. ...
33. }
34. }
35. </script>
This example is rather long and we have only shown an extract of the source
code. Take your time and look at the online example.