HTML5 Guidelines for Web Developers


Upper Saddle River, NJ • Boston • Indianapolis • San Francisco New York • Toronto • Montreal • London • Munich • Paris • Madrid Capetown • Sydney • Tokyo • Singapore • Mexico City HTML5 Guidelines for Web Developers Klaus Förster Bernd Öggl Figure 4.9 © 2008 Blender Foundation / www.bigbuckbunny.org Cover design: Marco Lindenbeck, webwo GmbH, mlindenbeck@webwo.de Many of the designations used by manufacturers and sellers to distinguish their products are claimed as trademarks. Where those designations appear in this book, and the publisher was aware of a trademark claim, the designations have been printed with initial capital letters or in all capitals. The authors and publisher have taken care in the preparation of this book, but make no ex- pressed or implied warranty of any kind and assume no responsibility for errors or omissions. No liability is assumed for incidental or consequential damages in connection with or arising out of the use of the information or programs contained herein. The publisher offers excellent discounts on this book when ordered in quantity for bulk pur- chases or special sales, which may include electronic versions and/or custom covers and con- tent particular to your business, training goals, marketing focus, and branding interests. For more information, please contact: U.S. Corporate and Government Sales (800) 382-3419 corpsales@pearsontechgroup.com For sales outside the United States, please contact: International Sales international@pearson.com Visit us on the Web: informit.com/aw Library of Congress Cataloging-in-Publication Data Förster, Klaus, 1964-   [HTML 5. English]   HTML5 guidelines for Web developers / Klaus Förster, Bernd Öggl.   p.  cm.   Includes bibliographical references and index.   ISBN 978-0-321-77274-9 (pbk. : alk. paper)   1. HTML (Document markup language) 2. Internet programming. 3.   Web site development. I. Öggl, Bernd. II. Title. III. Title: HTML 5   guidelines for Web developers. QA76.625.F6713 2012 006.7’4—dc23   2011014135 Copyright © 2011 Pearson Education, Inc. All rights reserved. Printed in the United States of America. This publication is protected by copyright, and permission must be obtained from the publisher prior to any prohibited repro- duction, storage in a retrieval system, or transmission in any form or by any means, electronic, mechanical, photocopying, recording, or likewise. For information regarding permissions, write to: Pearson Education, Inc. Rights and Contracts Department 501 Boylston Street, Suite 900 Boston, MA 02116 Fax: (617) 671-3447 ISBN-13: 978-0-321-77274-9 ISBN-10: 0-321-77274-1 Text printed in the United States on recycled paper at RR Donnelley in Crawfordsville, Indiana. First printing, June 2011 Editor-in-Chief Mark L. Taub Senior Acquisitions Editor Trina MacDonald Development Editor Susan Brown Zahn Translator Almut Dworak Managing Editor John Fuller Full-Service Production Manager Julie B. Nahil Project Editor and Compositor Mary Sudul, Fastpages Copy Editor Anne Marie Walker Indexer Jack Lewis Proofreader Linda Seifert Thanks to Andrea and Sabine—you are wonderful! This page intentionally left blank v Contents Preface ............................................................................................................... xi About the Authors ............................................................................................ xiii 1 Overview of the New Web Standard............................................................ 1 1.1 How It All Started....................................................................................... 1 1.2 Time Travel through Historic Events........................................................ 7 1.3 In Medias Res.............................................................................................. 9 1.3.1  What Is New?................................................................................... 9 1.3.2  What Has Become Obsolete?....................................................... 13 1.3.3  And What About XHTML?............................................................ 15 1.4 Can I Start Using HTML5 Now?.............................................................. 16 Summary............................................................................................................ 18 2 Structure and Semantics for Documents.................................................. 19 2.1 Header with “header” and “hgroup”...................................................... 21 2.2 Content with “article”.............................................................................. 22 2.3 Footer with “footer” and “nav”............................................................... 24 2.4 Sidebar with “aside” and “section”......................................................... 25 2.5 The Outline Algorithm............................................................................. 27 2.6 Figures with “figure” and “figcaption”................................................... 28 2.7 Text-Level Semantics—More New Tags................................................. 29 2.7.1  The Elements “ruby,” “rt,” and “rp”........................................... 30 2.7.2  The “time” Element...................................................................... 31 2.7.3  The “mark” Element..................................................................... 32 2.7.4  The “wbr” Element....................................................................... 32 2.7.5  Elements with Marginal Changes............................................... 33 Summary............................................................................................................ 35 3 Intelligent Forms.......................................................................................... 37 3.1 New Input Types...................................................................................... 38 3.1.1  The Input Types “tel” and “search”............................................ 39 Contentsvi 3.1.2  The Input Types “url” and “email”............................................. 40 3.1.3  Date and Time with “datetime”, “date”, “month”, “week”, “time”, and “datetime-local”........................................ 40 3.1.4  The Input Types “number” and “range”.................................... 40 3.1.5  The Input Type “color”................................................................ 41 3.1.6  The New Input Types in Action................................................... 41 3.2 Useful Attributes for Forms..................................................................... 43 3.2.1  Focusing with “autofocus”.......................................................... 43 3.2.2  Placeholder Text with “placeholder”.......................................... 44 3.2.3  Compulsory Fields with “required”............................................ 44 3.2.4  Even More Attributes for the “input” Element.......................... 45 3.3 New Elements........................................................................................... 47 3.3.1  Displaying Measurements with “meter”.................................... 47 3.3.2  Displaying the Progress of a Task with “progress”.................... 50 3.3.3  Lists of Options with “datalist”.................................................... 51 3.3.4  Cryptographic Keys with “keygen”............................................. 53 3.3.5  Calculations with “output”.......................................................... 55 3.4 Client-Side Form Validation.................................................................... 57 3.4.1  The “invalid” Event....................................................................... 59 3.4.2  The “checkValidity” Function..................................................... 59 3.4.3  Error Handling with “setCustomValidity()”............................... 61 3.4.4  Summary of Validity Checks........................................................ 63 3.4.5  Or Perhaps Better Not to Validate? “formnovalidate”............... 63 3.5 Example: A Support Form....................................................................... 64 Summary............................................................................................................ 68 4 Video and Audio........................................................................................... 69 4.1 A First Example......................................................................................... 70 4.2 The “video” Element and Its Attributes................................................. 71 4.3 Video Codecs............................................................................................ 73 4.3.1  Ogg: Theora and Vorbis............................................................... 75 4.3.2  MPEG-4: H.264 and AAC.............................................................. 75 4.3.3  WebM: VP8 and Vorbis................................................................. 76 4.4 Tools for Video Conversion..................................................................... 76 4.4.1  FFmpeg.......................................................................................... 76 4.4.2  VLC................................................................................................. 78 4.4.3  Firefogg.......................................................................................... 79 4.4.4  Miro Video Converter................................................................... 81 Contents vii 4.5 Which Format for Which Browser?......................................................... 82 4.6 Interim Solutions for Older Browsers..................................................... 83 4.6.1  mwEmbed..................................................................................... 83 4.6.2  html5media................................................................................... 85 4.7 Video and Scripting—A Simple Video Player......................................... 86 4.7.1  Integrating the Video.................................................................... 87 4.7.2  Starting and Stopping the Video................................................. 88 4.7.3  Displaying and Setting the Playback Position........................... 89 4.7.4  Fast Forward and Backward........................................................ 91 4.7.5  Selecting Specific Scenes in the Film.......................................... 93 4.7.6  Set Volume to High, Low, or Mute.............................................. 93 4.7.8  Other Attributes and Methods of the “HTMLMediaElement” Interface................................................ 94 4.7.9  The Long List of Media Events.................................................... 98 4.8 And What About Audio?........................................................................... 99 Summary.......................................................................................................... 105 5 Canvas........................................................................................................ 107 5.1 A First Example....................................................................................... 108 5.2 Rectangles............................................................................................... 111 5.3 Colors and Shadows............................................................................... 113 5.4 Gradients................................................................................................. 114 5.5 Paths........................................................................................................ 117 5.5.1  Lines............................................................................................. 119 5.5.2  Bézier Curves.............................................................................. 120 5.5.3  Arcs.............................................................................................. 121 5.5.4  Rectangles................................................................................... 126 5.5.5  Outlines, Fills, and Clipping Masks.......................................... 127 5.6 Text.......................................................................................................... 130 5.6.1  Fonts............................................................................................ 130 5.6.2  Horizontal Anchor Point............................................................ 132 5.6.3  Vertical Anchor Point................................................................. 133 5.6.4  Drawing and Measuring Text.................................................... 134 5.7 Embedding Images................................................................................. 135 5.8 Pixel Manipulation................................................................................. 141 5.8.1  Working with the “ImageData” Object..................................... 141 5.8.2  Color Manipulation with “getImageData()”, “createImageData()”, and “putImageData()”.......................... 145 viii Contents 5.9 Compositing............................................................................................ 149 5.10 Patterns................................................................................................... 152 5.11 Transformations..................................................................................... 156 5.12 Base64 Encoding with “canvas.toDataURL()”..................................... 163 5.13 “save()” and “restore()”.......................................................................... 165 5.14 Animations.............................................................................................. 166 5.14.1  Animation with Multicolored Spheres................................... 166 5.14.2  Playing a Video with “drawImage()”....................................... 169 5.15 Anything Still Missing?........................................................................... 173 5.15.1  “isPointInPath(x, y)”................................................................. 173 5.15.2  Accessibility in Canvas?............................................................ 174 5.15.3  Security Aspects........................................................................ 175 5.15.4  Browser Support....................................................................... 176 5.15.5  Further Links............................................................................. 176 Summary.......................................................................................................... 177 6 SVG and MathML....................................................................................... 179 6.1 MathML................................................................................................... 180 6.2 SVG.......................................................................................................... 182 Summary.......................................................................................................... 183 7 Geolocation................................................................................................ 185 7.1 Introduction to Geolocation.................................................................. 186 7.1.1  About Geographical Data........................................................... 186 7.1.2  Online Map Services................................................................... 186 7.2 A First Experiment: Geolocation in the Browser................................. 190 7.3 Technical Background of Determining Position................................. 193 7.4 Display of Current Position on OpenStreetMap................................. 194 7.5 Location Tracking with Google Maps................................................... 196 7.6 Example: Geonotes................................................................................. 197 7.6.1  Operation.................................................................................... 198 7.6.2  Important Code Fragments....................................................... 199 7.7 Browser Support..................................................................................... 202 Summary.......................................................................................................... 203 8 Web Storage and Offline Web Applications............................................ 205 8.1 Storage..................................................................................................... 206 8.1.1  The “Storage” Interface.............................................................. 206 8.1.2  “sessionStorage”......................................................................... 208 ixContents 8.1.3  “localStorage”............................................................................. 209 8.1.4  The “storage” Event.................................................................... 210 8.1.5  Debugging................................................................................... 210 8.2 Offline Web Applications....................................................................... 212 8.2.1  The Cache Manifest File............................................................. 213 8.2.2  Offline Status and Events........................................................... 214 8.2.3  Debugging................................................................................... 217 8.3 Browser Support..................................................................................... 220 8.4 Example: Click to tick!............................................................................ 220 8.4.1  Using the Application: As a Player............................................ 221 8.4.2  Using the Application: As an Administrator............................ 222 8.4.3  Important Code Fragments....................................................... 223 8.4.4  Expansion Options..................................................................... 229 Summary.......................................................................................................... 230 9 WebSockets............................................................................................... 231 9.1 The WebSocket Server........................................................................... 233 9.2 Example: A Broadcast Server................................................................. 234 9.2.1  The Broadcast Client.................................................................. 235 9.2.2  The Broadcast Server.................................................................. 237 9.3 Example: Battleships!............................................................................. 239 Summary.......................................................................................................... 248 10 Web Workers.............................................................................................. 249 10.1 Introduction to Web Workers............................................................... 249 10.2 Search for Leap Years............................................................................. 251 10.3 Calculate Altitude Profiles with Canvas............................................... 253 10.3.1  Important Code Fragments..................................................... 255 Summary.......................................................................................................... 259 11 Microdata.................................................................................................... 261 11.1 The Syntax of Microdata........................................................................ 263 11.1.1  The Attributes “itemscope” and ”itemprop”......................... 263 11.1.2  The “itemtype” Attribute......................................................... 266 11.1.3  The “itemid” Attribute............................................................. 268 11.1.4  The “itemref” Attribute............................................................ 268 11.2 The Microdata DOM API....................................................................... 269 Summary.......................................................................................................... 271 x Contents 12 Finishing Touches: Some Global Attributes............................................ 273 12.1 News for the “class” Attribute............................................................... 274 12.2 Defining Custom Attributes with “data-*”........................................... 275 12.3 The “hidden” Attribute.......................................................................... 276 12.4 The “classList” Interface........................................................................ 276 12.5 Drag and Drop with the “draggable” Attribute.................................... 278 12.5.1  Drag and Drop in Combination with the “FileAPI”.............. 284 12.6 The Attributes “contenteditable” and “spellcheck”............................ 288 Summary.......................................................................................................... 290 Afterword.......................................................................................................... 293 Index.................................................................................................................. 295 xi Preface In 2010, HTML5 became the buzzword on the web developer scene. Large com- panies, such as Google, Apple, and Microsoft, began to use the new technology. The popularity of the catchword HTML5 grew, not least of all because of the heated debate between Apple and Adobe over whether this would mean the end of Flash. In this book, we give you extensive insight into the new possibilities of HTML5. In addition to the classic specification components, such as video, audio, canvas, intelligent forms, offline applications, and microdata (to name but a few), this overview also includes topics in the immediate context of HTML5—for example, geolocation, web storage, WebSockets, and web workers. Numerous compact, clear, and practical examples illustrate the new elements and techniques in HTML5. There is something here for everyone, whether you decide you want to construct a web log, program your own video and audio play- er, use the browser as a graphics program, work with geographical data, test to the limit the capacity of your browser, or prefer to live out your playful nature by trying a quiz with drag and drop or playing Battleships! with WebSockets. We also give you plenty of tips and tricks regarding JavaScript and the DOM. It is to be expected that sooner or later all browsers, in order to remain com- petitive in the future, will accommodate HTML5. We therefore decided not to include workarounds and compatibility libraries in most cases. In this book you will find pure HTML5, supported in our examples by at least one browser, but in most cases supported already by several manufacturers. For an up-to-date and complete reference of the new HTML elements, we refer you to the Internet. You will find the relevant links in the appropriate text passages of this book. How to Read This Book How you decide to explore this book is entirely up to you. The individual chap- ters do not necessarily have to be read consecutively and are designed to be eas- ily understandable, even if you have not yet read the other chapters. So, you can read the book in the traditional way, from front to back; alternatively, you can read it from back to front or in any order, letting your curiosity guide you. xii Preface Who This Book Is for You should definitely have a basic knowledge of HTML, JavaScript, and CSS; a willingness to work with a different browser for a change, not just the one you are used to; and above all, a desire to discover something new. Try new ideas, such as those in this book, or have a look at the companion website where you can see all the examples in color. Decide what you want to do and, most important, have fun! The companion website can be found at http://html5.komplett.cc/welcome. xiii About the Authors The authors of this book are as versatile and multifaceted as the new web stand- ard they were brave enough to write about while it was still in development. Klaus Förster, an open source enthusiast, works at the Department of Geog- raphy of the University of Innsbruck, Austria. He has attended numerous SVG Open conferences as speaker, reviewer, and workshop leader, and contributed SVG modules to the free software projects PostGIS, GRASS GIS, and SpatiaLite. Bernd Öggl, lecturer and system administrator at the University of Innsbruck, is the coauthor of a book on PHP and MySQL and has many years of experience programming web applications. This page intentionally left blank 1 Overview of the New Web Standard As is appropriate for a web standard, the story of HTML5 starts with the World Wide Web Consortium (W3C), or more precisely, with the W3C Workshop on Web Applications and Compound Documents in June 2004. But rather unusu- ally, the development of HTML5 initially took place outside of the W3C, because the W3C was not at all thrilled with the idea of HTML5 to start with. What had happened? 1.1  How It All Started In a joint position paper, Mozilla and Opera demanded that the W3C should ensure the continued development of HTML, DOM, and CSS as the basis of web applications of the future. Given the fact that the W3C had already sidelined 1 Chapter 1—Overview of the New Web Standard2 HTML4 six years before and had instead elected to back XHTML, XForms, SVG, and SMIL, it was hardly surprising that this suggestion was rejected. The re- sult was very close, with 8 votes in favor and 11 votes against, but the decision still had far-reaching consequences. In the following years, the development of HTML5 was to take place in direct competition with the W3C. Ian Hickson, who at the time supported the position paper, together with the second Opera representative Håkon Wium Lie and Mozilla’s David Baron, re- viewed the events in his web log and came to the conclusion: The issues have been discussed, the positions have been given, everyone knows where everyone else stands, now it’s time to get down and actually start doing work. Referring to recent events, he finishes with these words: What working group is going to work on extending HTML... He is referring to the Web Hypertext Applications Technology Working Group (WHATWG), which was created on June 4, 2004, just two days after the end of the workshop. The WHATWG describes itself as a loose, unofficial, and open col- laboration of the browser manufacturers Safari, Opera, and Mozilla, as well as interested parties. Its aim is to continue development of the HTML standard and to submit the results of this process to a standards organization to achieve standardization. The founding members of the WHATWG include Anne van Kesteren, Brendan Eich, David Baron, David Hyatt, Dean Edwards, Håkon Wium Lie, Ian Hickson, Johnny Stenbäck, and Maciej Stachowiak. This select circle of developers from the browser and HTML community was to shape the fate of HTML5 from then on, together with the active WHATWG community. Three specifications were initially on the agenda of Ian Hickson, who took on a central role as editor: Web Forms 2.0 as advancement of HTML forms; Web Apps 1.0, which focused on application development within HTML; and Web Controls 1.0, a specification centered around interactive widgets. The latter project was soon abandoned, and Web Forms was integrated into Web Apps at a later time. The working method of the WHATWG has always been geared toward collabora- tion with the community; if you look at the homepage (see Figure 1.1), you can see this very clearly. 1.1  How It All Started 3 Figure 1.1  WHATWG homepage at http://www.whatwg.org Anyone looking for help with learning or using HTML5 will find answers under FAQ, Help, and Forums. The Wiki, hidden behind the Volunteer button, is not quite as helpful yet, because it is geared more toward development issues and contains little documentation on the HTML5 language. The blog, accessible via the News button, seemed a little neglected in 2010 too, which was perhaps due to the fact that the main author, Mark Pilgrim of Google, was at that time busy writing his own online book, which is freely available at http://diveintohtml5.org in case you want to take a look. Fortunately, Anne van Kesteren resurrected the blog in 2011 with reports on developments of the standard—a valuable source for keeping track of recent changes. One of the most active areas is the Chat at irc://irc.freenode.org/whatwg, linked via the IRC button. Here, the WHATWG community meets up with browser developers and works with them to implement the specification. This is also the place to have heated debates on matters concerning HTML5, make politi- cal statements, or tell critics exactly what you think. An imaginary character, Mr. LastWeek, comments on the events with sometimes hefty blog entries at http://lastweekinhtml5.blogspot.com in reaction to the publicly accessible IRC protocols at http://krijnhoetmer.nl/irc-logs, which anyone can not only read, but also actively comment on. Just click on the yellow box at the end of a line you deem relevant, exciting, or important to color the line yellow. To scan the most recent topics, marking entries works quite well. Chapter 1—Overview of the New Web Standard4 Three public mailing lists, linked via the Contribute section, are the main instru- ments of communication—one for user questions, one for contributions to the specification, and one for all those working on implementing the specification. If you do not want to subscribe to the mailing list, you can also access the public archives where all news items are filed and can be searched or downloaded: zz help@whatwg.org http://lists.whatwg.org/listinfo.cgi/help-whatwg.org zz whatwg@whatwg.org http://lists.whatwg.org/listinfo.cgi/whatwg-whatwg.org zz implementors@whatwg.org http://lists.whatwg.org/listinfo.cgi/implementors-whatwg.org The specification is also being developed in a public and transparent manner— more on this topic in a moment; it is not as straightforward as it sounds. In real- ity, there is not just one specification but several versions of it. But for now, let’s get back to the history of HTML5. While the WHATWG was working on renewing HTML, the W3C’s XHTML2 Work- ing Group set about creating a completely new web. Unlike the WHATWG, which was aiming to achieve backward compatibility, the XHTML2 Working Group, led by Steven Pemberton, tried to further develop HTML in a different way. Instead of FORMS, XFORMS would be used; FRAMES would be replaced by XFRAMES; and new XML Events would take the place of DOM Events. Each element could have both a src and an href attribute, and the headers h1, h2, h3, h4, h5, h6 would be obsolete and be replaced by h in combination with a new section element. Manual line breaks with br would be realized with l elements; hr would be called separator; the new nl element would allow navigation lists; and to improve se- mantic options, you could assign a role attribute with predefined or namespace- extensible keywords to each element. A drop of bitterness and the final nail in the coffin of the XHTML2 project was the lack of support from the browser vendors. The attempted changes were too radi- cal and did not take existing web content into consideration. Soon, the W3C also came to realize that this development would not get far. In October 2006, Tim Berners-Lee, the director of W3C and inventor of the World Wide Web, finally relented and wrote in his blog: Some things are clearer with hindsight of several years. It is necessary to evolve HTML incrementally. The attempt to get the world to switch to XML, including quotes around attribute values and slashes in empty tags and namespaces all at once didn’t work. 1.1  How It All Started 5 Admitting that XHTML2 had failed to become the new web language, he an- nounced the creation of a new HTML working group—on a wider scale this time. The group would involve the browser vendors and would aim at further develop- ing both HTML and XHTML step by step. In the last paragraph of his blog entry he emphasizes his conviction that this is the right way to go: This is going to be a very major collaboration on a very important spec, one of the crown jewels of web technology. Even though hundreds of people will be involved, we are evolving the technology which millions going on billions will use in the future. There won’t seem like enough thankyous to go around some days. But we will be maintaining something very important and creat- ing something even better. In March 2007, the time had come: The new HTML Working Group was formed. Shortly after it had been announced to the W3C, all members of the WHATWG were invited to participate in the HTML WG—an offer the WHATWG gratefully accepted. A few months later, a vote was taken to decide if the specification drawn up by the WHATWG should become the basis of the new, joint HTML5 specification. In contrast to the vote taken during the Workshop in 2004, the result was in favor, with 43 voting for, 5 voting against, 4 people abstaining, and 1 explicitly reject- ing. After a delay of three years, the original idea of further developing HTML had prevailed. But this was just the beginning: New ways of cooperating had to be found—a task that proved to be anything but easy because the philosophies of WHATWG and W3C were only compatible to a limited extent. The fact that the two camps were not always in agreement was reflected not only in extensive discussion threads in the W3C’s own archived and publicly accessible public-html mailing list (http:// lists.w3.org/Archives/Public/public-html), but was also evident in the assess- ment of the HTML5 project’s road map. Although the W3C assumed in its Charter that HTML5 would reach Recommen- dation in Q3 of 2010, Ian Hickson of the WHATWG anticipated a much longer period. The year 2022 has often been suggested, but such a long time span is con- sidered completely unacceptable by many critics. Yet this time frame may seem more realistic if you take into account the ambitious aim of HTML5 to replace the three specifications—HTML4, DOM2 HTML, and XHTML1—and to expand them significantly, to create a test suite with thousands of tests, and to prescribe two faultless implementations of the standard as proof of concept. One look at the decision-policy rules of the HTML WG gives you an inkling of how complicated the decision-making process of the two groups involved in fur- ther developing the specification is (http://dev.w3.org/html5/decision-policy/ decision-policy.html). After the XHTML2 Working Group was disbanded in late 2009, the number of critics willing to fully exploit this decision policy increased. Chapter 1—Overview of the New Web Standard6 As a result, a constantly growing list of so-called Issues is being tracked by the W3C’s HTML WG (http://www.w3.org/html/wg/tracker/issues). These issues need to be resolved before declaring Last Call under moderation of the chairs Sam Ruby, Paul Cotton, and Maciej Stachowiak. On the part of the WHATWG, Ian Hickson took advantage of a calmer period and was able to temporarily re- duce his issues list (http://www.whatwg.org/issues/data.html) down to zero, leading him to announce HTML5 in Last Call to the WHATWG in October 2009. A visible sign of the complexity of the events is the status of the specification. With the WHATWG, the main specification is a compact document, whereas in early 2011 the W3C had eight parts, all counting as part of the HTML5 package. Two of them are generated directly from the WHATWG version and are marked with an asterisk; the others are supplements and are in turn not contained in the WHATWG version. WHATWG Specification: zz HTML—Living Standard: http://whatwg.org/html W3C HTML WG Specifications: zz HTML5 - A vocabulary and associated APIs for HTML and XHTML *: http://www.w3.org/TR/html5 zz HTML5 differences from HTML4: http://www.w3.org/TR/html5-diff zz HTML: The Markup Language Reference: http://www.w3.org/TR/html-markup zz HTML+RDFa 1.1: http://www.w3.org/TR/rdfa-in-html zz HTML Microdata: http://www.w3.org/TR/microdata zz HTML Canvas 2D Context *: http://www.w3.org/TR/2dcontext zz HTML5: Techniques for providing useful text alternatives: http://www.w3.org/TR/html-alt-techniques zz Polyglot Markup HTML-Compatible XHTML Documents: http://www.w3.org/TR/html-polyglot Another WHATWG document exists in which all the WHATWG sections are com- bined with additional specs for Web Workers, Web Storage, and the Web Sockets API. This document, Web Applications 1.0—Living Standard, is well suited to serve as an endurance test for HTML rendering: With more than 5MB of source code and JavaScript to display the implementation stage of each section, plus the option of adding direct comments to individual sections, it will stretch any browser to its limit: 1.2  Time Travel through Historic Events 7 If you want to go easy on your browser, you could either use the multipage version of that document at http://www.whatwg.org/C or add ?slow-browser at the end of the URL. That way, dynamic components will be skipped and you end up with a static, faster-loading version without interactive elements. If you want to keep track of the changes made to the specification, you have several options. The WHATWG offers a Subversion repository of the complete specification of which you can create a local copy: zz svn co http://svn.whatwg.org/webapps webapps You can also access Commit messages of the individual revisions via Twitter, a mailing list, or the web interface, the so-called web-apps-tracker: zz http://twitter.com/WHATWG zz http://lists.whatwg.org/listinfo.cgi/commit-watchers-whatwg.org zz http://html5.org/tools/web-apps-tracker Whereas the WHATWG specification changes continuously with each revision, the W3C drafts are subject to the so-called Heartbeat requirement, which means that new versions of the W3C specification must be published at regular intervals of three to four months as Working Drafts. By the time this book is published, the next heartbeat will probably have occurred, and who knows, maybe even a Last Call Working Draft will have been announced by the W3C. If you want to explore the history of HTML5, the Time Travel section offers a selection of links as portals to milestones and historic events. The article “Why Apple is betting on HTML 5: a web history” offers a very good summary of the entire HTML history. It is available at AppleInsider under the shortened URL, http://bit.ly/2qvA7s. 1.2  Time Travel through Historic Events Milestones in the development of HTML in selected links include the following: zz W3C Workshop on Web Applications and Compound Documents (June 2004): http://www.w3.org/2004/04/webapps-cdf-ws/index zz Position paper by Opera and Mozilla on further development of HTML: http://www.w3.org/2004/04/webapps-cdf-ws/papers/opera.html TIP http://www.whatwg.org/specs/web-apps/current-work/complete.html Chapter 1—Overview of the New Web Standard8 zz Ian Hickson’s assessment of the workshop in three blog posts: http://ln.hixie.ch/?start=1086387609&order=1&count=3 zz Creation of the WHATWG is announced two days after the workshop: http://www.whatwg.org/news/start zz Blog entry “Reinventing HTML” by Tim Berners-Lee (October 2006): http://dig.csail.mit.edu/breadcrumbs/node/166 zz Relaunch of the W3C HTML Working Group (March 2007): http://www.w3.org/2007/03/html-pressrelease zz Ian Hickson informs the WHATWG community of the relaunch: http:// lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2007-March/009887.html zz Official invitation to the WHATWG to sign up for the HTML WG: http:// lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2007-March/009908.html zz Ian Hickson congratulates the W3C on the initiative on behalf of the WHATWG: http://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2007- March/009909.html zz HTML Design Principles as basis of HTML5 (November 2007): http://www.w3.org/TR/html-design-principles/ zz First official HTML5 Working Draft at W3C (January 2008): http://www.w3.org/2008/02/html5-pressrelease zz Announcement that the XHTML2 Working Group will be disbanded (July 2009): http://www.w3.org/News/2009#entry-6601 zz WHATWG declares HTML5 at Last Call (October 2009): http://blog.whatwg.org/html5-at-last-call zz W3C publishes eight Working Drafts, two of them new (June 2010): http://www.w3.org/News/2010#entry-8843 zz W3C announces Timeline to Last Call, expecting to reach Last Call end of May 2011 (September 2010): http://lists.w3.org/Archives/Public/public-html/2010Sep/0074.html zz W3C Introduces an HTML5 Logo (January 2011), causing controversy: http://www.w3.org/News/2011#entry-8992 zz Ian Hickson declares that the WHATWG HTML specification will henceforth just be known as “HTML” and can be considered a “living standard” (January 2011): http://blog.whatwg.org/html-is-the-new-html5 1.3  In Medias Res 9 1.3  In Medias Res After the preceding brief trip through the history of HTML5, the time has come to finally tackle the elements and attributes of HTML5 directly. What could be more appropriate than the classic Hello world! example? This is what it looks like in HTML5:             Hello world! in HTML5           

Hello world!

   Every HTML5 document begins with the document type declaration , and it does not matter if you write it in uppercase or lowercase. The sec- ond innovation you will notice is the shortened way of specifying the encoding— . The rest, like html, head, title, or body, you will be fa- miliar with from HTML4, which leads us to the question: What is really new in HTML5? 1.3.1  What Is New? The W3C provides the answer with the specification HTML5 differences from HTML4, moderated by Anne van Kesteren. In addition to lists of new and ob- solete elements and attributes, we can also find tips on new or changed APIs, external parts of the specification, and finally the HTML5 Changelog, which logs in chronological order how and when individual features have found their way into or out of the specification: http://www.w3.org/TR/html5-diff/. The tables contain a lot of detail, but do not give us a very clear overview. Four wordles are therefore going to guide us through this chapter. They were all cre- ated using Jonathan Feinberg’s Wordle Applet, which is available free of charge at http://www.wordle.net. The frequency of the relevant terms is reflected by the size of the letters for new elements and attributes, and determined by the number of cross-references connected to the relevant feature in the HTML5 specification. For obsolete elements and attributes, the font size corresponds to the frequency of online use, as researched by Opera within the MAMA project What is the Web made of? (http://dev.opera.com/articles/view/mama). Let’s first take a look at the new elements in the wordle in Figure 1.2. Highlights are definitely the media types video, audio, and canvas—the latter is, simply put, Chapter 1—Overview of the New Web Standard10 a picture you can program with JavaScript. Many innovations concern struc- turing elements, for example, article, section, header, hgroup, footer, nav, or aside. For figures, you have figure with figcaption, and you can show or hide additional information with details in combination with summary. You can in- dicate progress with progress, any kind of measurements with meter, and time and date with time. We are not likely to come across the elements ruby, rt, and rp in English- speaking countries very often; they are a typographical annotation system used mainly in Chinese and Japanese to give guidance on pronunciation. More use- ful for us is mark for emphasizing terms or wbr to show that a line break could be inserted at a certain point if necessary. Some elements tend toward web applications, such as keygen for generating key pairs for encryption or digital signatures, command for executing commands, or output as a result of calculations in forms or other parts of a document. As a con- tainer for option elements, datalist offers nonvisible select lists for form fields. For listing alternative resources for video and audio elements, there is source— the browser picks the first known format from this list to play the file. And last but not least is the frequently used embed element introduced by Netscape, now in an amended version. Figure 1.2  New HTML5 elements 1.3  In Medias Res 11 The input element also entails many changes. Here is a brief summary of new types: You now have several new input types for specifying the date with date- time, date, month, week, time, and datetime-local. Also, there are types for search fields (search) and for entering URLs (url), e-mail addresses (email), telephone numbers (tel), numbers (number) or numeric ranges (range), or colors (color). As you can see in Figure 1.3, many of the new attributes relate to forms. Thanks to the form attribute, input elements can be external to the form in question and be, as it were, linked to the desired form. Attributes, such as min, max, step, required, pattern, multiple, or autocomplete determine restrictions or conditions for in- put elements, influence the validation of the entered data with formnovalidate and novalidate, and offer practical help for filling in forms with placeholder or autofocus. What happens when the form is submitted can be overwritten in in- put and button elements with formmethod, formenctype, formtarget, and formac- tion. The list attribute serves to assign selection lists created with datalist to the relevant input component. As security features for iframes, we have sandbox, srcdoc, and seamless. These isolate the embedded content from the rest of the document. If you want to load scripts asynchronously, you can use async, and ping opens the list of URLs speci- fied in the ping attribute in the background whenever you click on a hyperlink. Figure 1.3  New HTML5 attributes Chapter 1—Overview of the New Web Standard12 The manifest attribute of the html element seems inconspicuous but has far- reaching consequences: It paves the way for offline web applications by referring to the configuration file determining which parts of the page should be made available offline. The style elements with the attribute scoped can also be useful, limiting the validity of the specified styles to the area of the superordinate DOM node and all its child elements. For menu elements, type and label determine the type of menu (for example, context menu or toolbar), plus its label. Small but sweet improvements include using the charset attribute in the meta tag to simplify specifying the encoding; having the option of using li elements via value to assign explicit list values; specifying a starting point for ol with start; and finally being able to sort lists in reverse order with reversed. Some of the global attributes that are valid for all elements have been changed significantly. This does not apply so much to class, dir, id, lang, style, tab- index, and title, which are now global in contrast to HTML4, but mainly to the new attributes that have been added. With contenteditable you can now edit elements directly; contextmenu enables assigning your own menus, defined as menu; draggable marks the relevant element as a potential candidate for drag- and-drop actions; and spellcheck prepares for checking the relevant section for spelling errors. Contents that are not or no longer relevant at the time of display can be hid- den; the attribute role or aria-* can be used to offer additional help for assistive technologies, such as Screenreader; and the reserved prefix data-* enables you to define as many of your own attributes as you like. Another important part of HTML5 is that of new programming APIs, for exam- ple, the canvas element API, an API for playing audio and video contents, and an interface for programming offline web applications. Further APIs are devoted to the topics drag-and-drop, editing documents, or governing the browser history. The specification even contains some initially exotic-seeming APIs for register- ing and applying your own protocols or MIME types. We should also mention that in HTML5 all event handlers are global attributes and that certain changes were made to the objects HTMLDocument and HTMLEle- ment. With getElementsByClassName(), you can find all elements with a particular class attribute; you can manipulate class attributes with the classList API; and you can now use the method innerHTML with XML documents, too. You can de- termine which element in the document is currently in focus with activeElement and hasFocus—both as attributes of the HTMLDocument object, just as with the method getSelection(), which returns the text currently selected by the user. 1.3  In Medias Res 13 1.3.2  What Has Become Obsolete? When discussing the innovations in HTML5, we should also determine which features we should no longer use. The term deprecated is frequently used in oth- er W3C specifications in this context, but this term is not appropriate in the case of HTML5. Because HTML5 is backward compatible, such features also have to be displayed correctly by the browser. For the author of a web page, however, the specification of differences from HTML4 offers a list of elements and attributes that should or may no longer be used. The term absent now replaces the term deprecated. If you look at the wordle in Figure 1.4, you can see that the elements font and center are definitely out. They are replaced by more up-to-date CSS solutions, and the same applies to the elements u, big, strike, basefont, and tt. Now, iframes replaces frame, frameset, and noframes; instead of acronym you should now use abbr, instead of dir you should use ul, and isindex is abandoned in fa- vor of the better options offered by forms. If you are wondering why some of the elements mentioned do not appear in the wordle, this is due to the fact that they were used very infrequently and are therefore no longer part of HTML5. For obsolete attributes, the picture is equally clear. Dominant in the wordle in Figure 1.5 are width, height, alignment (align, valign), spacing (cellpadding, cellspacing) , and coloration (bgcolor). They appear mostly in combination with table, td, or body and are now replaced by CSS, like many of the obsolete elements. Figure 1.4  Elements no longer used in HTML5 Chapter 1—Overview of the New Web Standard14 Figure 1.5  Attributes no longer used in HTML5 How do we know in detail which elements and attributes should no longer be used? It would be very time-consuming to have to keep searching through the HTML5 differences. A better solution is offered by the HTML5 validator at http://html5.validator.nu: The validator knows exactly what is right and wrong. Let’s give it a try: We select Text Field as input mode and replace the line

in the preset HTML basic frame with the following wrong markup:
WHATWG
The error messages this returns look like this—at least at the time of this writing: 1. Error: The center element is obsolete. Use CSS instead. 2. Error: The acronym element is obsolete. Use the abbr element instead. The link in Use CSS instead leads us directly to the WHATWG Wiki, to the page Presentational elements and attributes, where we can read details regarding cor- rect use. The validator also shows syntax errors directly, as you can see in the next test. Let’s try the following source code: 1.3  In Medias Res 15 We get another error message in answer—this time with the comment that the document is not yet complete and therefore invalid: 1. Error: End of file seen when expecting text or an end tag. If we fix this error by adding the end tag , this error message disappears as well and we have created the shortest possible HTML5 document: Error recognition in the validator is based on one of the key features of HTML5, the HTML parser. Unlike all previous specifications, it was formulated to the last detail, and with its 90 pages is about as exciting to read as the local phone book. From a technical point of view, however, this chapter is essential, because it de- fines how the HTML5 markup should be parsed and how the document’s DOM tree should be structured. Our preceding mini example generates in reality a complete HTML5 DOM tree, including html, head, and body elements. You can prove this with another tool, the HTML5 Live DOM Viewer, at http://livedom.validator.nu. Give it a go! 1.3.3  And What About XHTML? The HTML5 specification basically defines an abstract language for describing documents and web applications with APIs for interaction, which are represent- able in an in-memory DOM tree. It does not matter which syntax is used as the basis for creating this DOM tree—HTML is one of them, and XHTML is another. What matters is always the result after parsing, which is a valid DOM-HTML tree in both cases. So the decision whether to use HTML or XHTML when creating documents is up to the author. HTML is more widely used, easier to write, more forgiving with small syntax errors, and requires the MIME type text/html for output. XHTML follows the strict XML rules (keyword well-formedness) and always has to use an XML MIME type, such as text/xml or application/xhtml+xml, which was not the case previously with XHTML 1.1. The Hello world! example in XHTML5 manages without DOCTYPE but does require a valid XML declaration instead, which can be wrapped up in the encoding, and of course it has to be well-formed: Hello world! in HTML5 Chapter 1—Overview of the New Web Standard16

Hello world!

You probably cannot see much difference between this and the HTML version. That is due to the fact that we have not made full use of the permitted level of simplification in HTML code for the first Hello world! example. In lazy HTML5, this markup would have been sufficient: Hello World! in HTML5

Hello world! We can leave out quotation marks for attributes if the attribute value does not contain any spaces or any of the symbols " ' > / =. Tags can be written in up- percase or lowercase; sometimes they can even be omitted as in the preceding example. If you are not sure, the validator can once again help you out. Regard- ing implementation of the new HTML5 parser, Mozilla has taken the lead. Henri Sivonen’s Parser, which is also the basis of http://validator.nu, is included with Firefox 4. 1.4  Can I Start Using HTML5 Now? Yes and no. HTML5 is not finished yet by any stretch of the imagination, but un- like previous practice, the development of the HTML5 standard is taking place hand in hand with its implementation. Who would have thought that Internet Explorer 9 (IE9) would offer SVG and Canvas, or that Google would start offering HTML5 videos on YouTube? Many of the new features can be used now, provid- ed you can choose your browser. HTML5 can be used in a company’s internal in- tranet as well as on your private homepage that only selected friends can access. With Firefox, Chrome, Opera, and Safari, four great browsers are already sup- porting a wide range of HTML5, and IE9 has finally ended Microsoft’s long hesi- tation in supporting web standards in 2011. Browser manufacturers and their developers are now actively participating in forming the standard. They imple- ment new specification drafts first in test versions as proof of concept and then post their feedback and suggestions for improvements in the WHATWG or the W3C. This makes them important parts of the development cycle. Anything that cannot be implemented is removed from the specification, whereas other com- ponents are adapted and finally implemented. 1.4  Can I Start Using HTML5 Now? 17 Early adopters of HTML5 are well advised to familiarize themselves with the in- dividual browser’s release notes, as trends in response to the question What will come next? will most likely emerge here: zz https://developer.mozilla.org/en/HTML/HTML5 zz http://www.opera.com/docs/changelogs zz http://webkit.org/blog zz http://googlechromereleases.blogspot.com zz http://ie.microsoft.com/testdrive/info/ReleaseNotes The timeline of the development of HTML5-relevant specifications in combi- nation with the milestones of browser releases indicate with their shorter and shorter release intervals that standardization and implementation are closely linked (see Figure 1.6). It will be interesting to see how the two areas continue to develop. You can find an up-to-date version of the timeline at the following URL: http://html5.komplett.cc/code/chap_intro/timeline.html?lang=en Figure 1.6  Timeline of specifications and browser releases Chapter 1—Overview of the New Web Standard18 Summary This chapter begins with a bit of historical background and then provides a high- level overview of the changes the HTML5 specification brings to web develop- ment. In addition to a look behind the scenes of the specification development, our main focus is on the long list of new elements, attributes, and APIs. Two brief Hello world! examples demonstrate the basic frame of a website encoded in HTML5 and XHTML5, and last but not least we address the question: Can I start using HTML5 now? The answer is yes, albeit with minor reservations. But now we will move on to the practical application of HTML5. Let’s first start with a big chunk of innovations: more structure and semantics for documents! 2 Structure and Semantics for Documents Both the previously mentioned MAMA survey conducted by Opera and Google’s study of Web Authoring Statistics of 2005 (http://code.google.com/webstats) conclude that it was common practice at that time to determine the page struc- ture of web sites with the class or id attribute. Frequently used attribute val- ues were footer, content, menu, title, header, top, main, and nav, and it therefore made sense to factor the current practice into the new HTML5 specification and to create new elements for structuring pages. The result is a compact set of new structural elements—for example, header, hgroup, article, section, aside, footer, and nav—that facilitate a clear page structure without detours via class or id. To illustrate this, we will use a fictitious and not entirely serious HTML5 blog entry to risk a look ahead to the year 2022 (see Figure 2.1). But please concentrate less on the content of the post and focus instead on the document structure. 19 Chapter 2—Structure and Semantics for Documents20 Figure 2.1  The fictitious HTML5 blog Before analyzing the source code of the HTML5 blog in detail, here are a few important links, for example, to the specification HTML: The Markup Language Reference—subsequently shortened and referred to as markup specification at http://www.w3.org/TR/html-markup. Here, Mike Smith, the editor and team contact of W3C HTML WG, lists each ele- ment’s definition, any existing limitations, valid attributes or DOM interfaces, plus formatting rules in CSS notation (if to be applied)—a valuable help that we will use repeatedly. The HTML5 specification also contains the new structural elements in the following chapter: http://www.whatwg.org/specs/web-apps/ current-work/multipage/sections.html The .html and .css files to go with the HTML5 blog are of course also available online at: zz http://html5.komplett.cc/code/chap_structure/blog_en.html zz http://html5.komplett.cc/code/chap_structure/blog.css At first glance, you can see four different sections in Figure 2.1—a header, the article, the footer, and a sidebar. All the new structural elements are used in these four sections. In combination with short CSS instructions in the stylesheet blog. css, they determine the page structure and layout. 2.1  Header with “header” and “hgroup” 21 2.1  Header with “header” and “hgroup” In the header we encounter the first two new elements: header and hgroup. Fig- ure 2.2 shows the markup and the presentation of the header:

Figure 2.2  The basic structure of the HTML5 blog header The term header as used in the markup specification refers to a container for headlines and additional introductory contents or navigational aids. Headers are not only the headers at the top of the page, but can also be used elsewhere in the document. Not allowed are nested headers or a header within an address or footer element. In our case the headline of the HTML5 blog is defined by header in combination with the logo as an img element and two headings (h1 and h2) surrounded by an hgroup element containing the blog title and a subtitle. Whereas it was common practice until now to write the h1 and h2 elements di- rectly below one another to indicate title and subtitle, this is no longer allowed Chapter 2—Structure and Semantics for Documents22 in HTML5. We now have to use hgroup for grouping such elements. The overall position of the hgroup element is determined by the topmost heading. Other ele- ments can occur within hgroup, but as a general rule, we usually have a combina- tion of tags from h1 to h6. We can glimpse a small but important detail from the markup specification: The guideline is to format header elements as display: block in CSS, like all other structural elements. This ensures that even browsers that do not know what to do with the new tags can be persuaded to display the element concerned cor- rectly. We only need a few lines of code to teach Internet Explorer 8 our new header element, for example: Of course there is also a detailed JavaScript library on this workaround, and it contains not only header, but also many other new HTML5 elements. Remy Sharp makes it available for Internet Explorer at http://code.google.com/p/ html5shim. In computer language, the term shim describes a compatibility workaround for an application. Often, the term shiv is wrongly used instead. The word shiv was coined by John Resig, the creator of jQuery, in a post of that title (http://ejohn. org/blog/html5-shiv). It remains unknown whether he may in fact have meant shim. As far as CSS is concerned, the header does not contain anything special. The logo is integrated with float:left, the vertical distance between the two head- ings h1 and h2 is shortened slightly, and the subtitle is italicized. 2.2  Content with “article” The article element represents an independent area within a web page, for ex- ample, news, blog entries, or similar content. In our case the content of the blog entry consists of such an article element combined with an img element to liven things up, an h2 heading for the headline, a time and address element for the NOTE 2.2  Content with “article” 23 date it was created and the copyright, plus three paragraphs in which you can also see q and cite elements for quotations of the protagonists. Because the content element is now lacking, although it ranked right at the top in web page analyses by Google and Opera, it did not make it into HTML5 for some reason. Our blog entry is embedded in a surrounding div (see Figure 2.3). So nothing stands in the way of adding further articles:

Figure 2.3  The basic structure of the HTML5 blog content By definition, the address element contains contact information, which inciden- tally does not, as is often wrongly assumed, refer only to the postal address, but simply means information about the contact, such as name, company, and posi- tion. For addresses, the specification recommends using p. The address element applies to the closest article element; if there is none, it applies to the whole document. The time element behaves in a similar way in relation to its attributes pubdate and datetime, which form the timestamp for our document. You will find details on this in section 2.7.2, The “time” Element. Chapter 2—Structure and Semantics for Documents24 If article elements are nested within each other, the inner article should in prin- ciple have a theme similar to that of the outer article. One example of this kind of nesting would be, in our case, adding a subarticle to our blog with comments on the post concerned. Regarding styling via CSS, we should mention that article once again requires display: block, that the content width is reduced to 79% via the surrounding div, and that this div also neutralizes the logo’s float: left with clear: left. The italicized author information is the result of the default format of address and is not created via em. The picture is anchored on the left with float: left, the text is justified with align: justify, and quotations are integrated using the q element. One interesting detail is that the quotation marks are not part of the markup but are automatically added by the browser via the CSS pseudo-elements :before and :after in accordance with the style rules for the q element. The syntax in CSS notation once more reflects the markup specification: /* Style rule for the q-element: */ q { display: inline; } q:before { content: '"'; } q:after { content: '"'; } 2.3  Footer with “footer” and “nav” In the footer of our HTML blog, we find two other new structural elements: foot- er and nav (see Figure 2.4). The former creates the frame, and the latter provides navigation to other areas of the web page. footer contains additional info on the relevant section, such as who wrote it (as address of course); are there other, related pages; what do we need to look out for (copyright, disclaimer); and so on. Unlike the human body, where the head is usually at the top and the foot at the bottom, a footer in a document does not always have to be at the end of the document, but can, for example, also be part of an article element. Not allowed, however, are nested footer elements or a footer within a header or address element. If you want to create navigation blocks to allow page navigation via jump labels within a document or to external related pages, you can use nav. Just as with footer, nav can appear in other areas of the document as well, as you will see in the section 2.4, Sidebar with “aside” and “section”—the only exception being that you cannot have nav within the address element:

Figure 2.4  The basic structure of the HTML blog footer As for CSS, our HTML5 blog’s footer has a few special features. For example, the entire footer is colored in the same light gray as the page background, and only the links are formatted with background-color: white. The copyright in the first p requires float: left, and the navigation text-align: right plus the h3 heading in the nav block are hidden with display: none. Just why there is an h3 element in there at all will become clear in section 2.5, The Outline Algorithm. To improve the style of the links, they are surrounded by div tags. And of course we have display: block for header and nav, plus a reduction of the width in the footer element to 79%. 2.4  Sidebar with “aside” and “section” For areas of a page that are only loosely related to the main content and can there- fore be seen as rather separate entities, we can use the aside element. In our exam- ple, it creates a classical sidebar on the right with three blocks for Questionnaire, Chapter 2—Structure and Semantics for Documents26 Login, and Quick Links. If the link list is implemented as nav, as is to be expected, the two first blocks are embedded in another new element: section. The section element contains sections of a document that are thematically con- nected, for example, chapters of an essay or individual tabs of a page constructed from tabs, typically with a heading. If section is used within footer, it is usually used for appendices, indices, license agreements, or the like. Generally, it makes sense to use section if it belonged in a table of contents as well. In our example, as shown in Figure 2.5, the Questionnaire and the Login are tagged with section, and the links are tagged as nav as mentioned earlier: Figure 2.5  The basic structure of the HMTL5 blog sidebar 2.5  The Outline Algorithm 27 NOTE For the same reason as with the nav block in the footer (see the following sec- tion), the sidebar contains a heading h2 directly before the first Questionnaire block, hidden via CSS with display: none. The sidebar format is float: right with width: 20% and font-size: 0.9em. The striking feature of the sidebar is the rounded bottom-right corner, which means it’s time to admit that the HTML5 blog also uses CSS3: The rounded corner is only one of two features used. The CSS syntax for the class rounded-bottom-right looks like this: .rounded-bottom-right { -moz-border-radius: 0px 0px 20px 0px; -webkit-border-radius: 0px 0px 20px 0px; border-radius: 0px 0px 20px 0px; } The second feature is responsible for the subtle shadow of the four areas and is defined as follows in the CSS file: .shadow { -moz-box-shadow: 4px 0px 10px -3px silver; -webkit-box-shadow: 4px 0px 10px -3px silver; box-shadow: 4px 0px 10px -3px silver; } The tripling of the CSS command through the prefixes -moz-* and -webkit-* is conspicuous; it is caused by the fact that CSS3 is not yet in the Candidate Rec- ommendation phase. Once it enters this stage of the standardization process, only then will it be ensured that border-radius and box-shadow will no longer be changed. Until then, the prefixes are maintained to show that the implementa- tion could still contain small deviations from the standard. If you want to learn more about these two eagerly awaited features of the CSS3 specification, you will find further information here: zz http://www.w3.org/TR/css3-background/#the-border-radius zz http://www.w3.org/TR/css3-background/#box-shadow 2.5  The Outline Algorithm Even if the details for outlining a document sound rather complicated in the specification, there is a simple idea behind outlining, which is a machine-read- able summary of the underlying document structure. This structure is deter- mined by a combination of so-called sectioning content—for example, body, Chapter 2—Structure and Semantics for Documents28 article, aside, nav, and section—and heading content, such as h1 to h6 or hgroup, which provides the proper entries of the outline. If we check our HTML5 blog with Geoffrey Sneddon’s online HTML5 Outliner (http://gsnedders.html5.org/outliner), we see the following structure: 1. The HLML5 blog! 1. Link Block 1. Questionnaire 2. Login 3. Quick Links 2. Tug of war between W3C and WHATWG enters ... 3. Navigation With the italicized entries Link Block and Navigation, we get back exactly those two headings that were hidden in the layout with display: none. If we had omit- ted these headings completely, we would have seen the text Untitled Section in their place. But this way, the structure is complete and the outline is much easier to read. Regarding the choice of headings h1 to h6, we should note the following: In prin- ciple, any sectioning content can start with the heading rank h1, but it does not have to. In our case the heading ranks reflect the hierarchy in the outline: h1 for the blog header; h2 for the article title, the link block, and the footer navigation; and h3 for the other headers. If we tagged everything with h1, we would get the same outline, but the layout would suffer somewhat and we would need to sort it out manually in the CSS file. When using hgroup, you need to remember that the outline only includes the highest level in the hgroup. That is why you cannot see the subtitle Tips, tricks & tidbits for today’s web developers in the outline. Even if there is as yet no browser that directly uses the outline algorithm in any form, this does not mean that it could not play a more important role in the future. Automatically generated navigation bars would be a possibility, or the creation of short, concise summaries, or perhaps improvements for crawlers ex- tracting relevant content for search engines. Until then it definitely does not hurt to do some serious thinking about the structure of your document. It is easy to check the structure, so why not go ahead and do it? 2.6  Figures with “figure” and “figcaption” The elements figure and figcaption do not really count among the structural elements, but they are still a welcome addition to our options in structuring the integration of independent pictures, graphics, diagrams, and code lists. Each 2.7  Text-Level Semantics—More New Tags 29 figure element can have only one figcaption element. It is up to the author whether this is placed before or after the figure in question. A brief example with markup and its browser implementation (see Figure 2.6) could look like this:
XXI: The World VI: The Choice XVIII: The Moon
Three magical sculptures in Niki de Saint Phalles Giardino dei Tarocchi near Capalbio in the Tuscany region of Italy. The tarot cards from left to right: The World (XXI), The Choice (VI), and The Moon (XVIII)
Figure 2.6  Example of “figure” with “figcaption” 2.7  Text-Level Semantics—More New Tags Apart from focusing on clear structures, the HTML5 specification also attaches importance to semantics and tries to assign each element a certain meaning on the text level. At the same time, the HTML5 specification determines in which context the tag concerned can be used and in which it cannot. There are some new elements and some that have disappeared completely (such as font, center, and big), and the definitions of others have changed slightly. The fol- lowing chapter will introduce new and changed elements. Later, in Table 2.2 we will show you the classical applications of all elements that appear in the Chapter 2—Structure and Semantics for Documents30 specification’s Text-level semantics chapter. Let’s start with the most exotic of the new elements—ruby. 2.7.1  The Elements “ruby,” “rt,” and “rp” The term ruby refers to a typographic annotation system, meaning “short runs of text alongside the base text, typically used in East Asian documents to indicate pronunciation or to provide a short annotation” (www.w3.org/TR/ruby). Ruby annotation is used in Chinese and Japanese to show the pronunciation of char- acters, as you can see in the example on the left in Figure 2.7. Figure 2.7  Two examples of ruby annotation The markup for ruby annotations contains the elements ruby, rt, and rp. First, the expression that will be explained is specified within a ruby element. The ex- planation is then provided by the following rt element, and in browsers with ruby support the content of this rt element is positioned above the expression described. As you can see in the Beijing example, several words in a row can be annotated this way. Browsers without ruby support (such as Firefox and Opera) display the individual components consecutively, which can make the words more difficult to read. Be- cause it is not necessarily clear that the second word is the explanation of the first word, a visual separation of the two components is required. That is what the rp element is for: It enables adding optional parentheses that will only be displayed if a browser does not know ruby. As you can see in Figure 2.7, Google Chrome can 2.7  Text-Level Semantics—More New Tags 31 interpret ruby and visually separate it. A browser without ruby support would display the examples as 北 běi 京 jīng and HTML N°5 (Web Standard). 2.7.2  The “time” Element The time element represents either a time in the 24-hour-format or a date in the Gregorian calendar with optional time and time-zone components. Its purpose is to give modern date and time specifications in a machine-readable format within an HTML5 document. Vague time references, such in the spring of 2011 or five minutes before the turn of the millennium, are therefore not allowed. To ensure machine readability, we can use the attribute datetime, and its attri- bute value can be specified either as time, date, or a combination of both. The syntax for specifying the time components is clearly defined in the specification and is described in Table 2.1. Table 2.1  The Rules for Timestamps for the “time” Element’s “datetime” Attribute Component Syntax Example Date YYYY-MM-DD 2011-07-13 Time with hours hh:mm 18:28 Time with seconds hh:mm:ss 18:28:05 Time with milliseconds hh:mm:ss.f 18:28:05.2318 Date and time T to join date and time 2011-07-13T18:28 With time zone GMT Z at the end 2011-07-13T18:28:05Z With time zone as offset +mm:hh / -mm:hh 2011-07-13T18:28:05+02:00 The pubdate attribute is a boolean attribute and indicates that the specified date applies to the next level article in the hierarchy, and—if there is none—should be understood as the publication date of the document. If you are using pubdate, there has to be a datetime element as well. If this is not the case, the section be- tween the time element’s start tag and end tag must contain a valid date. Chapter 2—Structure and Semantics for Documents32 NOTE Be careful when writing boolean attributes in HTML5: true or false are not valid attribute values! As soon as the parser discovers the attribute name in boolean attributes, it switches to true. So there are three valid notations for setting a boolean attribute to true:
drinks page. em Stress emphasis I must say I adore lemonade. strong Importance This tea is very hot. small Side comments These grapes are made into wine. Alcohol is addictive. s Inaccurate text Price: £4.50 £2.00! cite Titles of works The case Hugo v. Danielle is relevant here. q Quotations The judge said You can drink water from the fish tank but advised against it. dfn Defining instance The term organic food refers to food produced without synthetic chemicals. abbr Abbreviations Organic food in Ireland is certified by the IOFGA. Chapter 2—Structure and Semantics for Documents34 Table 2.2  Usage of Semantic Text Elements (Contd.) Element Purpose Example code Computer code The fruitdb program can be used for tracking fruit production. var Variables If there are n fruit in the bowl, at least n÷2 will be ripe. samp Computer output The computer said Unknown error -3. kbd User input Hit F1 to continue. sub Subscripts Water is H2O. sup Superscripts The hydrogen in heavy water is usually 2 H. i Alternative voice Lemonade consists primarily of Citrus limon. b Keywords Take a lemon and squeeze it with a juicer. mark Highlight Elderflower cordial, with one part cordial to ten parts water, stands apart from the rest. ruby, rt, rp Ruby annotations OJ (Orange Juice) bdi Text directional- ity isolation The recommended restaurant is My Juice Café (At The Beach). bdo Text directional- ity formatting The proposal is to write English but in reverse order. “Juice” would become “Juice» span Other In French we call it sirop de sureau. br Line break Simply Orange Juice Company
Apopka, FL 32703
U.S.A. wbr Line breaking opportunity www.simplyorangejuice.com 2.7  Text-Level Semantics—More New Tags 35 Summary HTML5 offers a wealth of new structural elements, such as header, hgroup, ar- ticle, section, aside, footer, and nav. The detailed example at the beginning of this chapter, the creation of a fictitious blog entry, demonstrates how easily and intuitively these elements can be used. Instead of anonymous div elements, which only make sense in combination with the class attributes, we now find speaking elements—a concept continued with figure and figcaption for inte- grating images and graphics. From the comprehensive list of HTML5 semantic text elements plus examples of their usage in Table 2.2, we briefly introduced the most interesting new elements, such as ruby, rt, and rp for ruby annotations; time for specifying the time; mark for marking text passages; and wbr for optional line breaks. This page intentionally left blank 3 Intelligent Forms Whether you want to book a flight, take care of your online banking, or enter a search term in Google, without forms, none of these services would be usa- ble. Most of the elements for interactive forms have remained unchanged since HTML 2.0 arrived in 1995. On one hand this indicates that Tim Berners-Lee’s design showed great foresight; on the other hand there is now a huge need to catch up. The HTML5 specification devotes a large section to the topic of forms and will greatly facilitate any web designer’s work. Even though browser support is not yet overwhelming at the time of this writing (so far, it’s only offered by Opera and the developer release of Google Chrome), the backward compatible syntax means that we can safely use the new form ele- ments now. 37 Chapter 3—Intelligent Forms 38 3.1  New Input Types The HTML5 specification enhances the input element by allowing several more values for the type attribute. The new types, for example, date, color, and range, enable browser manufacturers to make user-friendly input elements available and also make it possible for the browser to ensure that the input is of the de- sired type. If a browser does not recognize the type of the input element, it will fall back on type=text and display a text field, which is useful in any case. Even older browsers show this behavior, so there is nothing to stop us from using the new types right away. The types for date and time will probably be the most useful. Currently, there are countless different versions of more or less successful JavaScript calendars avail- able on the Internet. Entering a date comfortably, be it for booking a flight or a hotel room, or registering for a conference, is a problem that until now required manual work. Of course, JavaScript libraries, such as jQuery, offer ready-made calendars, but this function should really be supported by the browser directly. At the time of this writing, there is only one desktop browser that includes a graphic input element for entering the date: Opera. In Figure 3.1 you can see the open calendar that will be displayed if you click on an input element with the type date. But let’s tackle things in order: Table 3.1 provides an overview of the new types; then you can see what they look like in the Opera browser in Figure 3.1. Table 3.1  New Input Types in HTML5 Type Description Example tel Text without line breaks +1 234 567890 search Text without line breaks search term url An absolute URL http://www.example.com email A valid e-mail address user@host.com datetime Date and time (always in UTC time zone) 2010-08-11T11:58Z date Date without time zone 2010-08-11 month Month without time zone 2010-08 week Year and week in the year without time zone 2010-W32 time Time without time zone 11:58:00 3.1  New Input Types 39 Type Description Example datetime- local Date and time without timezone 2010-08-11T11:58:22.5 number Number 9999 or 99.2 range Numerical value within a range 33 or 2.99792458E8 color Hexadecimal representation of RGB values in sRGB color space #eeeeee 3.1.1  The Input Types “tel” and “search” tel and search are not significantly different from normal text fields. Both can contain character chains without line breaks. Even telephone numbers are not limited to numbers, because phone numbers often contain brackets or the plus symbol. For tel, the browser could offer suggestions from the local address book, a situation that is particularly useful with cell phones. The search type was intro- duced to allow the browser to make the search input consistent with the layout of the relevant platform. Mac OS X users, for example, are used to seeing search fields with rounded corners. Figure 3.1  Opera is already far ahead regarding implementation of new form input types Chapter 3—Intelligent Forms 40 3.1.2  The Input Types “url” and “email” In addition to suggesting options, the browser can also check the syntax for url and email. Because there are concrete rules for e-mail addresses and Internet addresses in the form of URLs, the browser can already provide feedback on pos- sible mistakes during input (more on this topic in section 3.4, Client-side Form Validation). 3.1.3  Date and Time with “datetime”, “date”, “month”, “week”, “time”, and “datetime-local” Let’s take a closer look at the date and time formats. datetime contains date and time information; the time zone is always set to UTC. The specification states that the browser can allow the user to select another time zone, but the value of the input element has to be converted to UTC. The rules for time in- formation in the datetime attribute of the time element, which we discussed in section 2.7.2, The “time” Element, apply here as well—with the only exception that the string always has to end in a Z, the identifier of UTC. With date and month, the time and time zone are omitted. As defined in the speci- fication, the date must be a valid day within the selected month, also taking into account leap years. Year, month, and day must be separated by a minus charac- ter; the year has to be at least four digits long and greater than 0. So dates before Christ (b.c.) cannot be represented in HTML5, in contrast to the somewhat more extensive international standard ISO 8601. The type week is represented as a week in a year, and it is mandatory that the week be preceded by the year. Year and week are once again separated by a mi- nus character. To ensure that there is no confusion with month, the week must be preceded by the character W. datetime-local works the same way as the already described datetime; the only difference is that there is no timezone specified. Opera uses a calendar window for selecting the date; the time can be entered manually or changed via arrow keys (refer to Figure 3.1). 3.1.4  The Input Types “number” and “range” The types number and range require input that can be converted to a numeri- cal value; the notation of floating-point numbers (for example, 2.99792458E8) is valid. Regarding the type range, the specification states that the exact value is not relevant; this type indicates a range of numbers, not an exact number, and the user can easily enter it with a slider bar. Both Opera and WebKit-based browsers, such as Safari or Google Chrome, use a slider bar to represent this type (refer to Figure 3.1 and see Figure 3.2). 3.1  New Input Types 41 Figure 3.2  The input type “range” in Safari 3.1.5  The Input Type “color” Once again the developers of Opera lead the way by being the first to program a graphical input option for the color element. As you can see in Figure 3.1, Opera (version 11 and later) offers a rectangular field with a choice of frequently used colors. You can also bring up a color picker along the lines of those you see in image-editing programs. Sadly, this input element is still not implemented in the other browsers. The value of the input element must contain the 8-bit RGB values in hexadeci- mal notation preceded by a # character. The color blue, for example, would be written as #0000ff. 3.1.6  The New Input Types in Action Enough with the theory: Our first example shows you the new elements, one below the other. Because that’s not very challenging, we will also test each ele- ment’s function. The trick is that the browser will set the type of an unknown ele- ment to text, and we can then evaluate those properties in JavaScript: Chapter 3—Intelligent Forms 42 As soon as the web page has finished loading, a loop runs over all input elements to analyze their type attributes. If the type attribute corresponds to the standard type text, its value is set to not available. The HTML code for the new input ele- ments looks like this:
New input types

... In Figure 3.3 you can see what the result of this test looks like on an Android cell phone. The system’s WebKit-based browser (left) pretends to know the types tel, search, url, and email but does not really help when it comes to entering the telephone number via the keyboard (center). Opera Mobile in version 10.1 beta (right) supports url and email, plus the date and time types. Figure 3.3  Support of new form input types on an Android 2.1 phone with browsers WebKit (left, center) and Opera (right) That is a rather disappointing result for the otherwise so modern Android brows- er. Results look slightly better on the iPhone: At least the smartphone adapts the software keyboard, displaying a numeric keyboard when you try to enter a phone number and adding the @ character on the keyboard for the input type email. 3.2  Useful Attributes for Forms 43 This test works even better with BlackBerry, the operating system of the popular line of smartphones produced by the Canadian manufacturer Research in Mo- tion (RIM). As you can see in Figure 3.4, the BlackBerry supports both tel and number plus date types, and the latter in particular are represented in very at- tractive graphics. Under the hood we find WebKit at work: The software was ex- panded to include these functions. Figure 3.4  The new input types on a BlackBerry smartphone (BlackBerry 9800 simulator) 3.2  Useful Attributes for Forms Apart from new elements and many new types for the input element, HTML5 also offers several new attributes for form elements. 3.2.1  Focusing with “autofocus” Years ago, Google surprised many users with a simple trick that made searching much more convenient: When the page was loaded, the cursor was automati- cally positioned in the search field. The user was able to enter the search term directly without having to first activate the input box by clicking with the mouse. Previously, this was done with a short snippet of JavaScript; in HTML5 you can now do it with the autofocus attribute: As with all boolean attributes, you can write this attribute as autofocus="autofocus" (see Chapter 2, section 2.7.2, The “time” Element). The specification states that only one element in a web page can contain the autofocus attribute. Chapter 3—Intelligent Forms 44 Older browsers do not have a problem with autofocus, because they simply ig- nore the unknown attribute. Of course, you only get the benefit of user friendli- ness with new browsers. 3.2.2  Placeholder Text with “placeholder” Usability of HTML forms can be further improved with the new placeholder attribute:

The value of placeholder can give the user a quick hint about how to fill in the field, but it should not be used as an alternative to the label element. It is partic- ularly useful for fields where a certain data entry format is expected. The browser displays the hint text within an inactive input field. As soon as the field is acti- vated and is focused, the text is no longer displayed (see Figure 3.5). Figure 3.5  The “placeholder” attribute in Google Chrome 3.2.3  Compulsory Fields with “required” required is a boolean attribute, and its name already says everything about its function: A form element that this attribute is assigned to must be filled in. If a required field remains blank when the form is sent, it does not fulfill the require- ments and the browser must react accordingly. You will find more information on this in section 3.4, Client-side Form Validation. 3.2  Useful Attributes for Forms 45 3.2.4  Even More Attributes for the “input” Element The input element has not only been enhanced with new types (section 3.1, New Input Types), but also with new attributes that enable easier handling of forms (see Table 3.2). Table 3.2  New Attributes for the “input” Element Type Description Attribute liststring Refers to the ID of a datalist element with suggestions (see section 3.3.3, Lists of op- tions with “datalist”) list numeric/date Minimum value of numeric fields and date fields min numeric/date Maximum value of numeric fields and date fields max numeric Step size of numeric fields and date fields step boolean Multiple selection possible multiple enumerated (on/off/default) Automatically inserts saved data into form fields autocomplete string Regular expression for validating the value pattern We will come across the list attribute again in section 3.3.3, Lists of Options with “datalist”. It refers to the datalist element, which offers possible entries as suggestions. min, max, and step are not only suitable for numeric fields, but these attributes can also be used for entering the date and time:

In browsers that support the input type number, the first input element (id=minMax) is increased each time by a value of 0.1. This works by clicking the arrow keys at the end of the text field or by pressing the arrow keys on the keyboard. The ele- Chapter 3—Intelligent Forms 46 ment with the ID minMaxDate jumps forward seven days each time. Opera only displays those days in the calendar as active that correspond to the week cycle. For setting this element, Google Chrome offers the same navigation as with the input type number: two arrow keys that set the date forward or backward seven days. In the third input element in this example, the step size is set to 3600; this causes the time to be set one hour forward or one hour backward. Although the specification states that the input elements for time usually work in minutes, both Opera and Google Chrome interpret this data as seconds. We are all familiar with multiple selection from copying files; now this option ex- ists for browsers as well. If you wanted to load several files on a website at once, you previously had to provide an input field for each file. The multiple attribute allows for the marking of several files in the file dialog. The multiple option was always intended for the select element; using it for input fields of the type email is new. But as yet (at the time of this writing), none of the commonly used desk- top browsers can implement this function for email types. Modern browsers have a function that allows them to save form data to help the user fill in forms when the form is revisited. This prefilling can be very useful but would be undesirable for security-sensitive input fields (the specification men- tions the activation codes for nuclear weapons as an example). The autocomplete attribute was introduced to allow web developers to govern this behavior. If an element has the attribute autocomplete="off" assigned to it, that means the in- formation to be entered is confidential and should not be saved in the browser. If the form element does not state if autocomplete should be switched on or off, the default setting is to display suggestions. The autocomplete attribute can also be applied to the whole form by assigning it to the form element. The new pattern attribute allows for very flexible input verification. You can specify a regular expression against which the form field will be checked for a match. Regular expressions are very powerful but unfortunately not a very easy method of parsing strings. Imagine you are looking for a character string start- ing with an uppercase character followed by any number of lowercase letters or numbers and ending in .txt. Finding it is no problem at all with a regexp (short for regular expression): [A-Z]{1}[a-z,0-9]+\.txt An introduction to regular expressions would be far beyond the scope of this chapter, so let’s assume for now that you have basic knowledge of regular expressions when you read the following section. If you are looking for a brief online introduction to regular expressions, Wikipedia is a good starting point: Browse to http://en.wikipedia.org/wiki/Regular_expression. The website http://www.regexe.com gives you the chance to try regular expressions online. NOTE 3.3  New Elements 47 When using regular expressions with the pattern attribute you need to remem- ber that the search pattern always has to apply to the field’s entire content. The specification also suggests using the title attribute to give the user a hint re- garding the input format. Opera and Google Chrome display this kind of infor- mation as a tool tip as soon as the mouse pointer hovers over the field. After all this theory, here is a brief example:

The guideline for the pattern attribute specifies that the character string can only contain characters between a and z (in lowercase,[a-z]) and that there are at least 3 and at most 32 characters. Special characters or umlauts are not allowed, which can be useful for a user name as in the preceding example. If you want to include certain special characters, for example, the umlauts in the German lan- guage, you need to include them in the group: [a-zäöüß]. In section 3.4, Client- side Form Validation, you can find out what happens if the validation fails. 3.3  New Elements In addition to the new input types and the new attributes mentioned earlier, the specification also includes new elements for forms. We will discuss these in the next section. The elements meter and progress create graphical objects that previously could only be achieved with more or less complicated tricks. Sugges- tions for text input are offered by datalist, and output provides a placeholder for the results of calculations. The keygen element has been circulating through the World Wide Web for a long time but has only reached standardization with HTML5. 3.3.1  Displaying Measurements with “meter” The meter element is used to graphically represent a scalar measurement within a known range. Think, for example, of the fuel gauge in your car: The needle shows the current level of fuel in your tank as somewhere between 0 and 100 percent. Previously, such graphic representations were usually coded in HTML with nested div elements, a rather inelegant solution for which the div element was probably not intended. A status display can also be displayed graphically, as a picture, through free web services, such as the Google Chart API. You can see all of these options in the example that follows. Chapter 3—Intelligent Forms 48 Using the meter element is very simple: You set the desired value via the value attribute; all other attributes are optional. If you do not set a min and max value, the browser will use 0 and 1 for these attributes. So, the following meter element shows a half-full element: Apart from value, min, and max are also the attributes low, high, and optimum— values that the browser can incorporate into the display. Google Chrome (at the time of this writing, the only browser apart from Opera that is able to represent the meter element), for example, displays the normally green bar in yellow if the optimum value is exceeded. In the following example you can see a graphic representation, showing the per- centage of the current year that has already passed. The website presents a vi- sualization of the output in four different ways: as text with a value in percent, using the new meter element, via nested div elements, and as graphics produced by the online service of Google’s Chart API. You can see the result in Figure 3.6. Figure 3.6  The “meter” element and similar options for representing a state 3.3  New Elements 49 The HTML code for this example contains the still empty elements, which are filled via JavaScript:

Text

% of the year has passed.

The new meter element

Nested div elements

 

Google Chart API

For the text output, we use the output element introduced in section 3.3.5, Cal- culations with “output”. But first the current date is generated in JavaScript, and the meter element is initialized: var today = new Date(); var m = document.getElementById("m"); m.min = new Date(today.getFullYear(), 0, 1); m.max = new Date(today.getFullYear(), 11, 31); // m.optimum = m.min-m.max/2; m.value = today; The variable today contains the number of milliseconds since the start of the UNIX epoch (on 1.1.1970). To make sure our meter element gets a sensible scale, we set the min value to January 1 of the current year and the max value accordingly to December 31. The value of the meter element is set in the last line of the listing; now the graphical representation is complete. If you activate the optimum value (in this case the middle of the year), which we left out, you will see the display change depending on whether you call the script in the first or second half of the year. The new element is wonderfully simple to use. Let’s now move on to the other elements on our HTML web page. We want to assign the percentage of days passed to the output element tagged with the ID op. With Math.round(), we round up the percentage to the nearest number before the comma, which is plenty accurate enough for our example: var op = document.getElementById("op"); op.value = Math.round(100/(m.max-m.min)*(m.value-m.min)); var innerDIV = document.getElementById("innerDIV"); innerDIV.style.width=op.value+"%"; innerDIV.style.background = "green"; Chapter 3—Intelligent Forms 50 The rest of our example has nothing to do with new HTML5 techniques, but we still want to explain it for the sake of completeness. The nested div elements should also be filled with the percentage value. The idea behind this is simple: A first div area is defined in HTML with a fixed width (here, 150px). Nested into this element, another div element is displayed as filled with a green background color along the width of the calculated percentage value—a simple yet very effec- tive trick. To round things off, we also want to include the Google Chart API. To use the online service, you have to specify the chart size (chs, in our case 200×125 pixels), the chart type (cht, here, gom, Google-O-Meter), and the chart data (chd, here, the percentage value op.value): var google = document.getElementById("google"); google.src = "http://chart.apis.google.com/chart?chs=200x125&cht=gom&chd=t:"+op. value; var gSrc = document.getElementById("googleSrc"); gSrc.innerHTML = google.src; 3.3.2  Displaying the Progress of a Task with “progress” progress works in a similar way as the meter element discussed previously ex- cept that it represents the completion progress of a task. Such tasks could, for example, be file uploads by the user or downloads of external libraries required by an application. To give you a quick example, we do not really want to upload any files or down- load a lot of data; it is sufficient to set ourselves a task and fulfill it 100 percent. Our following example defines ten input elements of the type checkbox, and as soon as they are all activated, we want the progress bar to show 100 %:

Please activate all the checkboxes

Progress:

The progress element is initialized with a value of 0 and a maximum value of 10. As soon as an input element is activated, it calls the function updateProgress(), which looks like this: function updateProgress() { var pb = document.getElementById("pb"); var ip = document.getElementsByTagName("input"); 3.3  New Elements 51 var cnt = 0; for(var i=0; i

http:// If you want to equip older browsers with a selection list without duplicating the HTML code, you can fall back on the following trick. Because browsers support- ing the datalist element ignore an enclosed select element, they display the new HTML5 select element. Older browsers, however, display a selection list for the text field with predefined links, which will be inserted into the text field when the selection is changed. As you can see in Listing 3.2, we need to add a text node to the option elements because the “old” select element does not show the content of the value attri- bute but instead shows the text: Listing 3.2  A “datalist” with the fallback for older browsers 3.3  New Elements 53 The onchange event within the select element inserts the current text of the se- lection menu into the text box (see Figure 3.8). Figure 3.8  A combination of “input” and “select” elements as fallback for older browsers (here, Internet Explorer 8) 3.3.4  Cryptographic Keys with “keygen” The keygen element has a long history in the Mozilla Firefox browser (included since version 1.0), but Microsoft still expressed great concern regarding the im- plementation in HTML5. keygen is used to generate cryptographic keys, which sounds complicated, and unfortunately, it is just as complicated as it sounds. Simply put, the idea behind this element is this: The browser creates a pair of keys, one a public key and the other a private key. The public key is sent off with the other form data and is then available to the server application, whereas the private key remains saved in the browser. After this exchange of keys, the serv- er and browser can communicate in encryption without SSL certificates. This sounds like a practical solution for those pesky self-signed certificates, which browsers keep complaining about, but sadly it is not, because the identity of the server can only be verified through a certificate that has been signed by a trust- worthy authority, the Certificate Authority (CA). So if keygen cannot replace SSL, what should the new element be used for? As ex- plained in the Mozilla documentation, the keygen element helps create a certifi- cate that the server can sign (signed certificate). To make this step totally secure, it is usually necessary for the applicant to appear personally before the authority. Because the issuing of signed certificates is a task for experts, we will briefly de- scribe this element and its attributes. Chapter 3—Intelligent Forms 54 The following short HTML document creates a keygen button: keygen Demo

In addition to the familiar attributes, such as autofocus, disabled, name, and form, the keygen element has two special attributes: keytype and challenge. keytype in particular is interesting because the browser uses this entry to decide if it sup- ports this element’s function. Currently, there is only one valid keytype, which is rsa, a cryptographic system developed in 1977 at the Massachusetts Institute of Technology (MIT). If no keytype is specified (as in the preceding example), rsa is used as the default value. The specification also states that a browser does not have to support any keytype at all, which is probably because of Microsoft’s veto against this element. The optional challenge attribute increases security during the key exchange. For further information, please refer to the links in the note at the end of this section. If the browser supports the RSA key generation, it can offer a selection list to al- low the user to select the length, and consequently the security, of the key (see Figure 3.9). Figure 3.9  Selecting the key length in Google Chrome Figure 3.10 shows the result after the form has been sent: The POST variable kg contains the public key required for encryption (here, rendered in the extremely useful Firefox add-on Firebug). 3.3  New Elements 55 Figure 3.10  The public key of the “keygen” element, represented in Firebug If you have not had much previous experience with cryptography but would   like to find out more, Wikipedia is always a good starting point. Check out http://en.wikipedia.org/wiki/Public_key_infrastructure and http:// en.wikipedia.org/wiki/Challenge-response_authentication. 3.3.5  Calculations with “output” “The output element represents the result of a calculation.” That is the very short explanation in the HTML5 specification, and you will find exactly the same text on most websites describing the new element. It all sounds very sensible, but what kind of calculations are we dealing with? Why do we need a special element for them? As a general rule, these are calculations resulting from input fields on a web- site. An example familiar to most people would be an electronic shopping cart where the quantity for each product can be entered in an input field. Via the optional for attribute, you can determine which fields to include in the calcu- lation. One or more id attributes of other fields in the document are referenced in the process. NOTE Chapter 3—Intelligent Forms 56 To test the output element, we will program one of these little shopping carts for three different products. The quantity of each of these products can be changed via an input field. At the same time, the total number of items and the total price are displayed under the shopping cart. Figure 3.11 shows a shopping basket with five items. Figure 3.11  Two “output” elements show the number of products and the price in total The code for our example can be explained quickly and simply: To update the output elements for each change in quantity, we use the form’s oninput event:
ProductPrice (US$)Item number
Keyboard39.50
Mouse26.30 The output elements are defined after the table with the products and refer to the IDs of the input fields via the for attribute:

Your shopping cart contains items. Total price: US$. In the JavaScript code, a loop runs over all input elements, adding the quantities and calculating the total price: 3.4  Client-Side Form Validation 57 function updateSum() { var ips = document.getElementsByTagName("input"); var sum = 0; var prods = 0; for (var i=0; i 0) { sum += cnt * Number(document.getElementById( ips[i].name+"Price").innerHTML); prods += cnt; } } document.getElementById("sumProd").value = prods; document.getElementById("sum").value = sum; } We get the product price directly from the table by using the innerHTML value of the relevant table column and converting it to a number with the JavaScript function Number(). The same applies to the value in the input field (ips[i]. value), because without this conversion, JavaScript would add up the character strings, which would not produce the desired results. The calculated values are then inserted into the value attributes of the output elements. 3.4  Client-Side Form Validation One of the advantages of the new elements and attributes in forms is that the user can now enter data much more easily (for example, choose the date from a calendar). Another great advantage is the option of checking the form contents before the form is submitted and alerting the user of any mistakes. You might say that kind of checking is rather old hat because it has been around for years. That is true, but until now this step always had to be done via JavaScript code that you had to program. Thanks to jQuery and similar libraries, this task has become much easier and the code is more manageable, but you still must depend on an external library. With HTML5, this situation changes fundamentally: You define the parameters of the input fields in HTML, and the browser checks whether the fields have been filled in correctly. That is a big step forward and makes many lines of JavaScript code redundant. This tiny example will convince you:

Chapter 3—Intelligent Forms 58 Figure 3.12 shows what will happen if you submit the form in the preceding list- ing without specifying an e-mail address. Opera displays the error message: This is a required field. If you have set the Opera user interface to another language, the error message appears in the relevant language. Of course, you can also adapt these error messages with JavaScript; more on this in section 3.4.3. Figure 3.12  Error message for a blank input field with the “required” attribute (Opera) But that is not all: The field is defined as the type email, so Opera also returns an error message if an invalid e-mail address is entered; for example, Please enter a valid email address (see Figure 3.13). Figure 3.13  Error message in Opera after entering an invalid e-mail address 3.4  Client-Side Form Validation 59 WebKit-based browsers, such as Google Chrome or Safari, currently support the validation but do not display an error message. They place a border around the invalid field and position the cursor in the field to at least provide some indica- tion that something is not quite right. Despite all the euphoria about client-side validation of form input, you should not forget that this step cannot replace server-side control. A potential attacker can bypass these mechanisms with very little technical effort. 3.4.1  The “invalid” Event During form validation, elements with an invalid content trigger the event in- valid. We can use this to react individually to incorrect values: window.onload = function() { var inputs = document.getElementsByTagName("input"); for (var i=0; i If you enter an invalid e-mail address and move away from the input field (either with the Tab key or by clicking elsewhere in the browser), the browser (currently, at least in Opera) returns an error message right away (refer to Figure 3.13). Error handling becomes even more elegant if we attach a function for checking input to the onchange event of all input elements: window.onload = function() { var inputs = document.getElementsByTagName("input"); for (var i=0; i This means you forgo changing the borders and background color, but you sig- nificantly shorten the source code. An immediate reaction to each keystroke can be very helpful in some cases, but when filling in a form field, it is usually enough if the content is checked after the field has been fully completed. 3.4.3  Error Handling with “setCustomValidity()” If you feel that all the error handling methods introduced earlier are still not quite enough, you can also program your own function for checking content. In the following example, we define an input field with the type email, which Chapter 3—Intelligent Forms 62 ensures that the browser will check for a valid e-mail address. Additionally, we want to specifically exclude three e-mail domains: var invalidMailDomains = [ 'hotmail.com', 'gmx.com', 'gmail.com' ]; function checkMailDomain(item) { for (var i=0; i The following example will fully illustrate the idea of the support form. 3.5  Example: A Support Form In this example, the previously introduced new elements and attributes are used in a form. A form of this kind could, in an expanded state, be used on the website of an electronics dealer. Initially, the client is asked to supply personal details (in this example just the name, an e-mail address, and a telephone and fax number). The second part of the form concerns the product’s technical data and defect. The bottom part of the webpage shows a progress bar that is meant to encourage the user to com- plete the form (see Figure 3.16). Figure 3.16  The almost completed support form 3.5  Example: A Support Form 65 The HTML code for the form starts by loading an external JavaScript file and the already familiar call window.onload: The initEventListener function runs through all input elements and assigns an anonymous function to the onchange event, checking the corresponding element for its validity: function initEventListener() { var inputs = document.getElementsByTagName("input"); for (var i=0; i

Now the code gets more exciting with the textarea fields. HTML5 does not make many changes to this type. But as you can see in Figure 3.16, each text field now has a small graphic display above it, showing how many characters you can still type into this field. You probably realized it right away: It’s done with the new meter element, which you already know from section 3.3.1, Displaying Measure- ments with “meter”:

The meter element is initialized with a maximum value of 200, exactly the value specified as maximum in the title attribute of the textarea. If a user enters more characters than the maximum allowed, the meter element turns red, indi- cating that the text entered is too long. The browser will still submit all the text, because we have not limited the textarea. So this is more a hint rather than a strict requirement. The JavaScript function for updating the meter elements is updateTAMeters() and is executed for all textareas: function updateTAMeters() { var textfs = document.getElementsByTagName(“textarea”); for(var i=0; iProgress: We assign to the progress element an id, a starting value of 0 (value), and a nega- tive tabindex, which means that the element is never accessed with the Tab key. The JavaScript function updateProgress() updates the progress element: function updateProgress() { var req = document.querySelectorAll(":required"); count = 0; for(var i=0; i Keyboard shortcuts are not new in HTML5, but they have not been used much so far. One problem with keyboard shortcuts is that they are activated by differ- ent key combinations on different platforms, so you never quite know which key you are supposed to press for a particular shortcut. The HTML5 specification has a suggestion to solve this: The value of the accessKeyLabel should return a character string that corresponds to the correct value on the platform you are using. You could then use this value in the button’s label or in its title attribute. Unfortunately, at the time of this writing, not a single browser was capable of outputting this character string. Summary The information we supply in this chapter explains many of the new options provided in HTML5 for forms. Better times are ahead for web developers, be- cause they will no longer need to grapple with JavaScript libraries for common input elements, such as date and time. In particular, the new form functions will be of great help when working with mobile devices where text input is usually much more difficult than on the computer. Form validation in the browser will also contribute significantly to making the code more transparent and therefore more manageable. But do not forget that client-side validation does not make the server application more secure; potential attackers can easily circumvent these checks. If this chapter has whet your appetite and you want to try out your freshly ac- quired knowledge of forms on your own website, go right ahead. The syntax of the new elements and attributes is built in such a way that even older browsers will not produce errors. Users of such browsers will not be able to enjoy the full benefit of the new input elements, but text input is always possible. 4 Video and Audio The introduction of YouTube was a quantum leap for displaying videos online. Before the video platform came along, it was practically impossible for computer novices to make a video file available to others via the Internet: The files were usually too big to send via e-mail, and if they did arrive, the likelihood was great that they could not be played on the recipient’s computer. YouTube on the other hand offers online storage, allowing you to save the video files. It also converts the different video formats, so they can be played with the Adobe Flash Player. Adobe supports Flash on many operating systems, offering plug-ins for all com- mon browsers. Browser plug-ins are generally a great idea, but the communica- tion between plug-in and browser can sometimes be difficult if not impossible. Also, closed-source plug-ins, such as the Adobe Flash Player, are not very popular 69 Chapter 4—Video and Audio 70 with the browser manufacturers, because they make it much harder to find the error in case of a crash. HTML5 wanted to remedy this situation. The necessary new HTML element was easily found: video. But that was not enough to solve the problem. 4.1  A First Example We will give you a short example to demonstrate how easy the new HTML5 video element is to use: Simple Video You can play a video in the browser with remarkably little effort. In Figure 4.1 you can see the result in Mozilla Firefox. The HTML syntax is almost self-explanatory, but we will investigate it in more detail in the next section. Figure 4.1  A video in WebM format in Mozilla Firefox 4.2  The “video” Element and Its Attributes 71 4.2  The “video” Element and Its Attributes In the preceding example, two attributes are assigned to the video element: con- trols and autoplay. The attribute controls tells the browser to display control elements for the video (see Figure 4.1), and autoplay tells the browser to start playing the video as soon as this is possible. Like the canvas element (see Chapter 5, Canvas), the video element belongs to the category embedded content; in other words it is one of the contents that is not directly connected to HTML. Within the embedded content, you can include an alternative solution (fallback) in case the browser does not support the video element. If this happens in our example in section 4.1, A First Example, the text Sorry, your browser is unable to play this video appears. Additionally, you could display a still image from the video. But let’s look at the possible attributes of the video element in more detail (see Table 4.1). Table 4.1  Attributes of the “video” element Attribute Value Information src url The URL for the video to be played. This attribute is optional and can be replaced with one or more source elements, as in our example. poster url The URL for a picture that the browser displays while the video is loading. preload none The browser is not supposed to try loading the video before the Play button is clicked. This saves band- width. preload metadata Only the metadata for the video is loaded (for exam- ple, length of video, author, copyright). preload auto In this case the entire video is loaded even before the user clicks the Play button. autoplay boolean The browser begins playing the video as soon as enough data has been received. controls boolean Displays simple control elements for the video. This does not determine what these elements should look like; that is mostly up to the browser manufacturers. The specification suggests several elements, such as controls for playback and pausing the video, setting the volume, an option to skip to another point in the video (provided the content supports it), switching to full screen, and possible buttons for subtitles. loop boolean Tells the browser to repeat playback after reaching the end of the video. Chapter 4—Video and Audio 72 Table 4.1  Attributes of the “video” element (Contd.) Attribute Value Information width in CSS pixels Width of video display height in CSS pixels Height of video display audio muted Causes the user agent to override the user’s prefer- ences, if any, and always defaults the video to muted. If the video element does not have a src attribute, the browser processes one or more of the source elements contained within the video element. The attributes src, type, and media are intended for this purpose (see Table 4.2). In turn, if there is a source element, you must not specify a src attribute for video. Table 4.2  Attributes of the ”source” element Attribute Value Information src url The URL for the video to be played type mime-type MIME type of the video. You can add a specifi- cation of the audio and video codec, for exam- ple, type='video/webm; codecs="vorbis,vp8"'. If there are several source elements, the brows- er uses this attribute (among others) to decide which video is displayed. media CSS Media Query The output medium for which the video is intended The browser uses two criteria to decide which of the existing source elements will be displayed: the video’s MIME type and, if present, the media attribute in which you can specify additional limitations in the form of a CSS media query. For CSS3, media queries were significantly expanded, so you can now have more complex instructions in addition to familiar keywords like print, screen, hand- held, or projection. Here is an example: media="screen and (min-width: 800px)" This is where it gets interesting for video output, because depending on the brows- er size, the video can then be offered at different resolutions. Thanks to this trick, even mobile devices with smaller display screens and slower Internet connections 4.3  Video Codecs 73 can manage perfectly. A complete example for displaying a video in reduced size based on media queries looks like this: Simple Video Browsers with less than 500 pixels in width for displaying the video will auto- matically display the smaller video format mvi_2170_qvga.webm. The specification of CSS3 Media Queries is currently in the Editors Draft stage. Some details are therefore likely to change. You can look up the current stage of the specification on the W3C website at http://dev.w3.org/csswg/css3-mediaqueries. The second criterion for determining which video will be displayed is the MIME type. The optional addition of the codecs used lets the browser recognize, even before loading, whether the video can be decoded. But what are these codecs about? The following section attempts to shed light on the codec jungle. 4.3  Video Codecs Modern video formats use a container file where audio and video contents can be saved separately. This flexible approach has several advantages. For example, several audio tracks can be saved in one file, allowing the user to switch between languages (as you would on a video DVD). Figure 4.2 shows the schematic rep- resentation of a video container file. The way in which audio and video are com- pressed within this container file is referred to as codec. NOTE Chapter 4—Video and Audio 74 Figure 4.2  Schematic representation of a video container format One bone of contention during the creation of the HTML5 specification was the definition of allowed audio and video codecs. These debates were caused on one hand by commercial interests of companies holding patents for certain coding processes and on the other by the desire to choose a capable and high-quality format. More precisely, the camp was divided into a group that supported the patent-protected video codec H.264 and another group (led by the Mozilla team) calling for the open-source format Ogg Theora. When Ian Hickson realized that this conflict could endanger the important video element, he decided to take the definition of the format out of the specification. It is now up to the browser manufacturers to decide which formats they support and for which formats they are willing to pay license fees. Although Mozilla fought vehemently to avoid repeating the same mistake that was made in the case of the image format GIF for which CompuServe later de- manded license fees, H.264 seemed to be the favorite in the race for the new, online video format. But Google did not want to passively await the misery of potential patent infringements and decided to take care of the problem. By pur- chasing the video specialist On2 Technologies, which had already developed im- portant video formats, Google came to own the as yet unpublished codec VP8. During the Google developer conference, Google-IO 2010, the software giant fi- nally let the cat out of the bag: The new project WebM, based on the video codec VP8 and the audio format Ogg Vorbis, was published as an open-source project on the Internet at http://www.webmproject.org, and was soon after implement- ed in Firefox and Opera. In early 2011, Google even went one step further, announcing that support for the H.264 codec would be removed from future versions of its Chrome browser. The justification for this surprising step was that Google wants to enable open 4.3  Video Codecs 75 innovation, believing that the core techniques of the World Wide Web need to be based on open standards, which H.264 is not. After this brief history we will now explain a little more about the individual for- mats. Don’t worry; we will not discuss the technical details of video compression at great length. We will just introduce the common formats for the Internet. 4.3.1  Ogg: Theora and Vorbis When the Fraunhofer society began to demand license fees for the popular MP3 format at the end of the last millennium, the Xiph.Org Foundation developed the free audio codec Vorbis. Based on the video codec VP3.2, which was released in 2002 (developed by the aforementioned company On2), Xiph also created the video format Theora. Video and audio are combined in a container format, Ogg, and the container can contain one or more audio and video tracks. The MIME type for Ogg video files is video/ogg, and the corresponding filename extension is .ogv. (The file extension .ogg also works, but according to Xiph.org, we should avoid it and instead use the more explicit file extension .ogv for Ogg video and .oga for Ogg audio.) Do not confuse the Ogg Media container format (file extension .ogm) with the Ogg container discussed here. The Ogg Media (OGM) container is an extension that supports a large number of additional video codecs. Initially, this sounds very useful, but it does lead to some problems: Xiph insists that Ogg should be men- tioned only in the context of free formats, but this is not the case with Ogg Media, which can also use patented formats. 4.3.2 MPEG-4: H.264 and AAC The MPEG-4 (MP4) container is a derivation of the multimedia format Quick- Time commonly used in Apple operating systems. Like the Ogg container, MP4 can have audio and video tracks; it even goes one step further and can embed images and text. The most common codecs in MP4 are the patented video codec H.264 and the audio codec Advanced Audio Coding (AAC). The file extension is .mp4, and common media types are video/mp4, audio/mp4, and application/mp4. Apple created some confusion when files with the extension .m4a started to appear on iPods and other Apple devices. These are MP4 files, but Apple wanted the file extension to indicate that it is a pure audio file. Other file extensions used are .m4b for audio books and .m4r for iPhone ringtones. NOTE Chapter 4—Video and Audio 76 It was mostly the huge success of Apple’s mobile devices (iPod, iPhone, iPad) that contributed to the rapid spreading of the MP4 file format. To achieve an acceptable performance when playing back videos on devices with weak pro- cessors (such as cell phones), the computer-intensive process is transferred to a separate chip. This hardware acceleration saves energy and prolongs battery life. The patent problem regarding the H.264 codec should not be under- estimated. The type of encoding is patent protected until at least 2028—a veri- table sword of Damocles hanging over the software manufacturers who could be required at any time to pay fees for the encoding process. 4.3.3  WebM: VP8 and Vorbis As mentioned at the beginning of this section, Google caused some excitement and euphoria by founding the WebM project. The video codec VP8 received very good feedback in general, and the audio codec Vorbis had already proven suc- cessful. Google decided to use the open-source format Matroska as a container, which was already tried and tested as well. But although the Matroska format supports a number of different codecs, the WebM container only allows for the video codec VP8 and the audio codec Vorbis. The standard file extension for WebM videos is .webm, and the corresponding MIME type is video/webm. Immediately after Google’s announcement, the browser manufacturers of Mozil- la Firefox, Opera, and even Microsoft for Internet Explorer announced that they would support the WebM format. It goes without saying that Google’s browser Chrome offers support for WebM, so there is only one browser without support for the new codec (at least at the time of this writing): Apple’s Safari. 4.4  Tools for Video Conversion Because most peoples’ digital cameras usually do not produce videos in WebM or Ogg format, the next section introduces different tools for converting videos. They are all open-source products that run on Windows, Mac OS, and Linux, except for the Miro Video Converter. 4.4.1  FFmpeg FFmpeg is sometimes referred to as the Swiss army knife of video conversion. And rightly so, because the list of audio and video formats that FFmpeg can read and write is remarkably long. It can also split multimedia files into their compo- nents; for example, it can strip out only the audio track of a film and then convert 4.4  Tools for Video Conversion 77 it. If you are thinking of adding converted YouTube videos to your MP3 collec- tion, be warned: The quality of the audio track on YouTube is usually rather dis- appointing. Because the developers of FFmpeg did not bother with such trivialities as the programming of a graphic user interface, the user is expected to be none too shy about using the command line. If you do not change the FFmpeg default set- tings, you only need the following function call to convert an existing Flash Video (FLV) to the WebM format: $> ffmpeg -i myflashvideo.flv myflashvideo.webm FFmpeg is also excellent for finding out the format of a video: $> ffmpeg -i myflashvideo.flv ... Input #0, flv, from '/tmp/myflashvideo.flv': Duration: 00:05:12.19, start: 24.8450, bitrate: 716 kb/s Stream #0.0: Video: h264, yuv420p, 480x360 [PAR 1:1 DAR 4:3], 601 kb/s, 25 tbr, 1k tbn, 49.99 tbc Stream #0.1: Audio: aac, 44100 Hz, stereo, s16, 115 kb/s In this example, we are dealing with an approximately five-minute long video in a Flash container in which the video track is saved using the H.264 codec, and the audio track is in AAC. Since version 0.6, FFmpeg has supported WebM videos. But the developers were not satisfied with using the libvpx library available through Google: They reim- plemented VP8 based on the existing FFmpeg code, hoping to achieve consider- ably better performance in converting videos. A significant part of the FFmpeg project is the libavcodec library where support- ed audio and video formats are saved. Players like vlc, mplayer, or xine use this library to play or re-encode videos. The list of parameters for FFmpeg is practically endless and cannot be reproduced in detail within the scope of this book. If you are interested in finding out more, please refer to the excellent FFmpeg Documentation available online at http://www.ffmpeg.org/ffmpeg-doc.html. Table 4.3 shows some important parameters for encoding with FFmpeg. NOTE Chapter 4—Video and Audio 78 Table 4.3  Some important FFmpeg parameters Parameter Effect -h Help for all parameters (very long list) -formats List of all supported file formats -codecs List of all supported audio and video codecs -i file Sets file as input file / stream -f fmt Sets fmt as output format (for example, webm, ogg, or mp4) -ss start Searches the input medium up to the point start (in seconds) -t duration Records for duration seconds -b bitrate Video quality (bitrate, default: 200 kilobits/s) -r fps Frames per second (default: 25) -s widthxheight Video size (in pixels, specified in width times height, or spec- ifications such as vga) -ab bitrate Audio quality (bitrate, default: 64 kilobits/s) Thanks to the option of letting FFmpeg work without user interaction, it is par- ticularly suitable for automatic video conversion. 4.4.2  VLC For many years, the VideoLan project has been developing the popular media player VLC, available for various operating systems (Windows, Mac OS, Linux, and other UNIX variations) with a simple graphic interface. The media player uses, among others, the libavcodec library of the FFmpeg project and therefore also supports the WebM format. VLC does not just play videos of different formats and sources; you also have the option to convert multimedia content via the menu item Convert / Save. As you can see in Figure 4.3, you can use predefined profiles for converting to common formats—a very useful feature. 4.4  Tools for Video Conversion 79 Figure 4.3  Dialog for converting videos in VLC If you want to set quality and size of the video more precisely, you can open an- other dialog via Tools. If you examine VLC more closely, you will discover further interesting functions. For example, you have the option of capturing the screen as a video (screencast) so you can record your current work or the option of streaming videos to the Net via different protocols. Of course, FFmpeg can do that, too, but VLC even has a GUI on top of that. You can download VLC at http://www.videolan.org for all common platforms. 4.4.3  Firefogg If you are not completely comfortable using the command line and you do not want to install VLC, you can use the Firefox extension Firefogg. After installation, you can go to http://firefogg.org/make to easily select a video on your computer and convert it to the Ogg or WebM video format. Firefogg.org only offers the GUI buttons in this case; the conversion takes place on the local computer. An adapt- ed version of FFmpeg, downloaded during the Firefogg installation, is working in the background. In the menu item Preset you will find defaults for Ogg and WebM video in high and low quality (see Figure 4.4). You can also conveniently set metadata, such as title, author, recording date, and copyright, via the user interface. Chapter 4—Video and Audio 80 Figure 4.4  Settings for video conversion in Firefogg But Firefogg is more than just a graphic interface for FFmpeg. The extension comes with a JavaScript library, which makes it very easy for web developers to implement video uploads for users. The advantage is obvious: Instead of upload- ing a video format in low compression and then converting it on the server, the conversion takes place on the client side before the upload. This saves band- width and computing power on the web server’s side. Wikipedia is also betting on this concept, so we can hope that the development of Firefogg will continue. The website http://firefogg.org/dev/chunk_post_example.html shows in a few lines of source code how the Firefogg JavaScript library works. Firefogg divides the upload into 1MB chunks, which means that if the Internet connection fails, you do not need to upload the entire video again. NOTE 4.4  Tools for Video Conversion 81 4.4.4  Miro Video Converter The Miro Video Converter was developed as an offshoot of the Miro Media Player (http://www.getmiro.com), an innovative open-source audio and video player available for all common operating systems. The Miro Video Converter is only available for Windows and Mac OS. Figure 4.5 shows the simple user interface, which offers selection not only by video codec but also by device (iPad, iPhone, PlayStation, and Android phones). Figure 4.5  Video conversion with Miro Video Converter Load the video file via drag and drop, and FFmpeg starts the conversion. If FFm- peg should fail for any reason (which can occasionally happen), the FFmpeg Output button can help: Apart from the exact commands, it also shows all con- version status messages (see Figure 4.6). A quick Google search for the relevant error message will usually help you. Chapter 4—Video and Audio 82 Figure 4.6  Troubleshooting during conversion with Miro 4.5  Which Format for Which Browser? If you want to make videos available online for as many different browsers as possible, you will currently have to resort to a fallback solution for the video ele- ment. As shown in Table 4.4, there is no single video format at the moment that can be displayed by all common browsers. For the correlation of browser ver- sions and release dates, please refer to the end of the Introduction chapter or look at the timeline shown on the website at http://html5.komplett.cc/code/chap_intro/timeline.html?lang=en 4.6  Interim Solutions for Older Browsers 83 Table 4.4  Codec support in current browsers Codec Firefox Opera Chrome Safari IE iOS* Android OGG 3.5 10.50 3.0 MP4 3.0 3.0 2.0 WebM 4.0 10.60 6.0 9** Flash Plug-In Plug-In Plug-In Plug-In Plug-In 2.2 * Apple’s operating system for mobile devices, such as iPhone, iPad, iPod (since June 2010 iOS, previously iPhone OS). ** According to Microsoft, the WebM codec must be installed in the operating system, unlike with other browsers. 4.6  Interim Solutions for Older Browsers Fortunately, not every web developer who wants to cater to different platforms or browsers has to completely reinvent the wheel. There are several free libraries online focusing on this problem. Currently, Kaltura’s JavaScript library mwEm- bed has reached a very good stage of development. Wikipedia uses it to make video and audio elements available for most platforms. The main focus of this library is on the Ogg format. If you want to offer WebM and MP4 as well, use of the html5media library is a good solution. 4.6.1  mwEmbed The mwEmbed library gained wider recognition mainly through the integra- tion in Wikipedia. Kaltura, the company behind mwEmbed, offers integration not only for MediaWiki, the free encyclopedia’s wiki software, but also for ready- made plug-ins for common CMS and blog software like Drupal or WordPress. To ensure that even older browsers do not choke on the new HTML5 syntax, this example adds the elements head and body: mwEmbed fallback

mwEmbed fallback

The JavaScript library mwEmbed is downloaded directly from the project web- site (http://html5.kaltura.org/js) and then sorts out how the video can be played. In any case, a small control bar appears at the bottom edge of the video. Fig- ure 4.7 shows the reaction of Internet Explorer 8, which does not yet know the HTML5 video element: To play the Ogg video, it loads the Java applet Cortado. Figure 4.7  Internet Explorer 8 with Kaltura’s fallback library mwEmbed If you are not happy with Java applets as replacements for native video in the browser, you can use the html5media library instead. 4.6  Interim Solutions for Older Browsers 85 4.6.2  html5media The JavaScript library html5media works even more reservedly than mwEmbed and only takes action if the browser cannot play any of the specified video for- mats. In that case, it loads the open-source Flash Video Player Flowplayer and expects an MP4 (H.264) video as input. Unfortunately, the library contains a bug in the current version, which means that older browsers return a JavaScript error and output nothing if several source elements are specified: html5media fallback

html5media fallback

In this case it is important to specify the width and height; otherwise, the Flow- player will be displayed with a height of only a few pixels. Figure 4.8 provides an example. Figure 4.8  A video in Internet Explorer 8 playing on the free Flowplayer (Flash fallback) Chapter 4—Video and Audio 86 4.7  Video and Scripting—A Simple Video Player Not only can you display videos in the browser, you can also control them di- rectly with JavaScript via the HTMLMediaElement interface. This section shows you how this works. We will implement a simple JavaScript HTML5 video player with the following features: zz Start and stop the video zz Display and set the playback position on a control bar zz Fast forward and backward zz Select specific scenes in the movie zz Switch volume between high, low, and mute A suitable video for our video player is easily found: Big Buck Bunny—a roughly ten-minute long computer-animated cartoon, which is the result of a free film project, as its URL http://bigbuckbunny.org indicates. The project was initiated by the Blender Foundation. From October 2007 to April 2008, seven 3D anima- tion specialists used free software, like Blender, Gimp, Inkscape, or Python, all running on Ubuntu, to create this film and made it available online under an open license. A summary of the action, based on the motto funny and furry, can be found on Wikipedia at http://en.wikipedia.org/wiki/Big_Buck_Bunny. But our main concern is the video player. Figure 4.9 shows what it will look like. Figure 4.9  Screen shot of the JavaScript HTML5 video player 4.7  Video and Scripting—A Simple Video Player 87 The video player’s HTML page with JavaScript library and CSS styles can be found on this book’s companion website at the following links: zz http://html5.komplett.cc/code/chap_video/js_videoPlayer_en.html zz http://html5.komplett.cc/code/chap_video/js_videoPlayer.js zz http://html5.komplett.cc/code/chap_video/js_videoPlayer.css 4.7.1  Integrating the Video Most likely, you are already familiar with the HTML code for integrating video. Apart from the two event handler attributes oncanplay and ontimeupdate, which will play an important role later on, there is not much new here: With preload=metadata, we first load only so much of the film that the film du- ration and at least the first frame are available. During loading, we display the picture specified in the poster attribute and then the first frame, which, unfortu- nately, is completely black in our case. The width and height is specified for demo purposes to reenlarge the original video—reduced from 854 x 480 to 428 x 240 after downloading—back to 854 x 480 pixels. Why? Well, the reduced version is 39MB and is easier to test than the origi- nal video at 160MB. Also, explicitly specifying the attributes width and height can help explain 80% of the short HTMLVideoElement interface. This interface consists of only four attributes for the video dimensions; an attribute for the poster frame’s URL, if there is one; and the audio attribute that reflects whether the audio track is muted or not. Provided that the variable video contains a reference to our video element, we have the following attribute values: zz video.width = 854 (specified width) zz video.height = 480 (specified height) NOTE Chapter 4—Video and Audio 88 zz video.videoWidth = 428 (original width) zz video.videoHeight = 240 (original height) zz video.poster = URL for bbb_poster.jpg (poster frame) These few attributes are of course not enough to implement our video player. And indeed they are only additional elements of the HTMLVideoElement, which also represents an HTMLMediaElement—the object that contains all the neces- sary methods and attributes. If you are curious, you can look it up in the speci- fication at http://www.w3.org/TR/html5/video.html#htmlmediaelement. The real work starts with oncanplay, because it refers to the JavaScript function to be executed as soon as the browser can play the video. In our example this function is initControls() where a reference to the video is created and saved in the global variable video. In the course of implementing our video player, we will have to add entries to initControls() a few more times, but for now we only need the following code: var video; var initControls = function() { video = document.querySelector("VIDEO"); }; The method document.querySelector() is part of the CSS Selectors API. In the vid- eo variable it provides a reference to the first video element in the document. This gives us access to the HTMLMediaElement interface, and we can now start imple- menting our first feature—starting and stopping playback. 4.7.2  Starting and Stopping the Video To start and stop playback, we first need a button in the HTML document that can react to a user clicking it: id="playButton" ▶ is a character reference to the Unicode symbol BLACK RIGHT-POINT- ING TRIANGLE, which we can conveniently use as Play button. The function of starting and stopping playback is contained in playPause(), a callback function called with every click, which gets passed the button object in the argument this: 4.7  Video and Scripting—A Simple Video Player 89 var playPause = function(ctrl) { if (video.paused) { video.play(); ctrl.value = String.fromCharCode('0x25AE','0x25AE'); } else { video.pause(); ctrl.value = String.fromCharCode('0x25B6'); } }; The attribute video.paused tells us if the film is playing or not. It returns true if the film is paused and false if it is playing. This makes starting and stopping playback easy. video.start() and video.pause() are the suitable methods that in turn set video.paused to false or true accordingly. The button object passed in the argument ctrl is used to change the button to a Pause or Play button via ctrl.value, depending on the current state. If we were to assign ▶ directly, this would not have the desired result; instead, the character string ▶ would be displayed literally as text written on the but- ton. The correct method of creating Unicode symbols in JavaScript is via String. fromCharCode(). To this, we pass the desired UTF 16 hexadecimal codes as strings, separated by commas. Incidentally, the label text on the Pause button is made up of two BLACK VERTICAL RECTANGLE symbols (▮). We will need the playButton ID again later on. 4.7.3  Displaying and Setting the Playback Position To display the current playback position, we use the new input type range, previ- ously mentioned in Chapter 3, Intelligent Forms: The attributes min and max set the permitted value range, and step determines the interval by which the value will be changed when the user drags the slider. Applied to our video, min specifies the start and max the end of our film, which means that we have to set the value max to the total length of the video in seconds. The right place to do this is initControls(), the right attribute to do it with is video.duration. So we add the following lines to our initControls() function: Chapter 4—Video and Audio 90 curPos = document.getElementById("currentPosition"); curPos.max = video.duration; This now gives max the value 596.468017578125, which means the video is about ten-minutes long. Setting the playback position directly is done in the onchange event handler callback updateProgress()when the slider is dragged or clicked: var updateProgress = function(ctrl) { video.currentTime = ctrl.value; }; A single instruction is sufficient here; the attribute video.currentTime not only reflects the current playback position, but can also be set directly. We get the suitable value from the slider’s value attribute. To implement the display of the current playback position in the format MM:SS, we still need the following steps: 1. Add a span element in connection with the slider: 2. Save a reference to the span in the initControls() function and initialize this variable curTime with the value 0:00: curTime = document.getElementById("timePlayed"); curTime.innerHTML = '0:00'; 3. Update the timestamp curTime at each call of updateProgress(): mm = Math.floor(video.currentTime / 60.0); ss = parseInt(video.currentTime) % 60; ss = (ss < 10) ? '0'+ss : ss; curTime.innerHTML = mm+':'+ss; We are nearly finished. Only one essential slider feature is still missing: While the video is playing, it has to stay synchronized with the running time. The solution lies in the HTML code for integrating the video: ontimeupdate. The specification states that a timeupdate event should be triggered at intervals of at least 15 and up to 250 milliseconds during media stream playback. The event handler attri- bute ontimeupdate determines which callback function is called. If we set it to updateProgress(), we have found the perfect timer for synchronizing our slider. Compared to setting the position manually by clicking or dragging the slider, we now must not change the playback position but instead set the slider and the time display to the value of video.currentTime. The slightly adapted and thus final version of our updateProgress() function is shown in Listing 4.1: 4.7  Video and Scripting—A Simple Video Player 91 Listing 4.1  Change and update playback position var updateProgress = function(ctrl) { if (ctrl) { video.currentTime = ctrl.value; } else { curPos.value = video.currentTime; } // Setting the time in format MM:SS mm = Math.floor(video.currentTime / 60.0); ss = parseInt(video.currentTime) % 60; ss = (ss < 10) ? '0'+ss : ss; curTime.innerHTML = mm+’:’+ss; }; The purpose of the if/else block is to find out if updateProgress() was called with the slider or with ontimeupdate. In the former case, the passed slider object is assigned to ctrl, and we need to set the playback position to the slider value. In the latter case, a timeupdate event is present, and we need to set the slider to the current playback time in the variable curPos. Now that the playback and controlling the playback position are sorted out, you have some time to sit back and relax. Take ten minutes off and go explore Big Buck Bunny with your very own, homemade, and almost finished video player! 4.7.4  Fast Forward and Backward For these two features, we first need buttons in the HTML document. Their la- bels will again be Unicode symbols, this time guillemets—angle quotation marks. The Unicode name describes what they look like: LEFT-POINTING DOUBLE AN- GLE QUOTATION MARK («) and RIGHT-POINTING DOUBLE ANGLE QUO- TATION MARK (»). Two event listener attributes start and stop the quick search, which starts onmousedown and ends onmouseup: Chapter 4—Video and Audio 92 The JavaScript callback fastFwdBwb() is rather short and looks like this: var fastFwdBwd = function(direct) { _pause(); _play(); if (direct) { video.playbackRate = 5.0 * direct; } }; Two attributes play an important role in speeding up a video. One of them we can see in our callback function with video.playbackRate. It represents the cur- rent playback rate. The second one is video.defaultPlaybackRate, a default value that determines the film’s normal speed as 1.0. For faster playback, we need to change the playback rate; for example, 2.0 would mean twice as fast, 4.0 would be four times as fast, and so on. The number and where applicable the minus sign determines the direction of playback—positive values fast forward, negative ones rewind. According to the definition in the specification, the attribute video.playbackRate must be set to the value of video.defaultPlaybackRate each time video.play() is called. So as long as we do not crank up the defaultPlaybackRate, we can be sure that the original speed applies at each restart. To increase the speed, we therefore only need to change the video.playbackRate. This makes the implementation of fastFwdBwd() very easy: The video is first stopped briefly. Then it is played again, and if 1 or -1 is assigned to the variable direct, the video.playbackRate is set accordingly and the speed is increased. The functions _pause() and _play() contain code blocks for starting and stopping the video, previously found in the callback playPause(). With these functions, we can now not only control playback and pausing by clicking the Play button, but also directly via the script. To detach the functionality from the Play button, we need to define a reference to the button in initControl() via getElementById() and make it available as variable pButton. The split version of playPause() is shown in Listing 4.2: Listing 4.2  Starting and stopping the video var _play = function() { video.play(); pButton.value = String.fromCharCode('0x25AE','0x25AE'); }; var _pause = function() { video.pause(); pButton.value = String.fromCharCode('0x25B6'); }; 4.7  Video and Scripting—A Simple Video Player 93 var playPause = function() { if (video.paused) { _play(); } else { _pause(); } }; 4.7.5  Selecting Specific Scenes in the Film To select individual scenes, we first need a list with timestamps and titles. A pull- down menu provides the basis: The rest is simple and taken care of by the callback selectScene(). We pass it the selected entry as the argument. Then we convert its timestamp to seconds and set video.currentTime to the resulting value. The method _play() serves us well once again and starts playing the video at the desired point: var selectScene = function(ctrl) { arr = ctrl.value.split(":"); video.currentTime = parseFloat((arr[0]*60)+(arr[1]*1)); updateProgress(); _play(); }; 4.7.6 Set Volume to High, Low, or Mute All that’s left is the volume control. Let’s start with a simple exercise—on/off. Once more, we need a button in the HTML code with a label formed from a Uni- code symbol, this time BEAMED EIGHTH NOTES (♫): Chapter 4—Video and Audio 94 The mute() function uses the read/write attribute video.muted to switch to mute or loud, depending on the initial setting. To give the user optical feedback, the button label is displayed in the CSS color silver when the tone is muted and in black when the volume is switched on: var mute = function(ctrl) { if (video.muted) { video.muted = false; ctrl.style.color = 'black'; } else { video.muted = true; ctrl.style.color = 'silver'; } }; Setting the volume is not complicated, either. In addition to the slider as input type range, we also need to control the label in a span. The basic HTML structure then looks like this: We define a reference to the span element in initControls(), as before, and use video.volume to initialize the volume with 100 %: curVol = document.getElementById("currentVolume"); curVol.innerHTML = "100 %"; video.volume = 1; The callback function adjustVolume() reacts if the slider is changed. The slider reflects with min=0 and max=1 the exact value range of video.volume and changes the volume via step=0.1 in 10% steps if the slider is dragged: var adjustVolume = function(ctrl) { video.volume = ctrl.value; curVol.innerHTML = (Math.round(ctrl.value*100))+'%'; }; Our video player is now complete. This practical example has given you the chance to explore about half of the attributes and methods of the HTMLMediaEle- ment interface. A few interesting attributes and methods are still missing; we will look at those next. 4.7  Video and Scripting—A Simple Video Player 95 4.7.8  Other Attributes and Methods of the “HTMLMediaElement” Interface All media elements (including not only video, but also audio) have five attributes in common, which are shown in the HTMLMediaElement interface. Apart from src as source of the media stream, there are the boolean attributes autoplay, loop, and controls, plus preload with its three values none, metadata, and auto. The code for dynamically creating a video could then look like this: var video = document.createElement("VIDEO"); video.src = 'videos/bbb_240p_stereo.ogv'; video.autoplay = false; video.loop = true; video.controls = true; video.preload = 'metadata'; But this video is not loaded yet. The loading process only starts with the next method of the HTMLMediaElement interface, video.load(). To be able to see the video in the browser, we need to append it to the DOM tree. So we add two lines to our listing: video.load(); document.documentElement.appendChild(video); The dynamic counterpart of the oncanplay attribute of our video player’s video element is an event listener with event type, callback function, and a flag that determines if the event should become active in the capture phase or not. Con- fused? Just use false for the third argument, which activates the event listener in the bubbling phase instead. If you want to know the details of how the event order works, look online at http://www.quirksmode.org/js/events_order.html. Our event listener listens for the event canplay and then immediately starts play- ing the film: video.addEventListener("canplay", function() { video.play(); }, false); The HTML version of our brief code example can of course be found online at http://html5.komplett.cc/code/chap_video/js_dynamicVideo_en.html. NOTE Chapter 4—Video and Audio 96 As simple as this example may seem, the processes during loading a media stream are actually rather complicated. The specification distinguishes between network state and ready state, devoting two readonly attributes to these two states in the HTMLMediaElement interface, with several constants for describing the relevant state. The attribute networkState is for monitoring the network state. It can be queried at any time and returns the possible values listed in Table 4.5. Table 4.5  Constants of the “networkState” attribute Value Constant Description 0 NETWORK_EMPTY The video/audio has not yet been initialized. 1 NETWORK_IDLE The video/audio source is selected but is not cur- rently being loaded. 2 NETWORK_LOADING The browser is actively loading the video/audio. 3 NETWORK_NO_SOURCE No suitable source for the video/audio can be found. When selecting a suitable source, you need to remember that there are two op- tions for doing this: either via the src attribute of the relevant element or via sev- eral source elements from which the browser can choose the most suitable one. If we are working with several source elements for a video, the question arises as to how we know which of the offered elements was in fact chosen by the browser. The answer is in the readonly attribute video.currentSrc. In the screen shot of the video player, you can see it at the bottom left before the copyright. Actively asking if media types are supported by the relevant browser or not can be done not only by the browser when selecting the suitable source ele- ment, but also by the programmer with a script. The method we use for this is canPlayType(type) and requires a corresponding media type as an argument. The answer is probably if the browser is fairly sure that it can play the format, maybe if the browser is rather skeptical, or '' as an empty character chain if it can definitely not deal with it. See for yourself what selection of common types canPlayType(type) returns for your browser at http://html5.komplett.cc/code/chap_video/js_canPlayType. html. NOTE 4.7  Video and Scripting—A Simple Video Player 97 The attribute readyState describes which state a media element is currently in. It has the possible values listed in Table 4.6. Table 4.6  Constants of the “readyState” attribute Value Constant Description 0 HAVE_NOTHING No data is available on the current playback position. 1 HAVE_METADATA Metadata, such as length and dimension, are pres- ent, but no data can be played yet. 2 HAVE_CURRENT_DATA Data for the current position is available but is not really enough to begin playback. 3 HAVE_FUTURE_DATA Sufficient data for current and future playback po- sitions is available to start playback. 4 HAVE_ENOUGH_DATA The browser is sure that it can keep playing the media stream without interruption if the network state remains the same. If anything should really go wrong during loading or playback, an error event is fired, narrowing down the relevant error in its code attribute: video.addEventListener("error", function(e) { alert(e.code); }, false); This callback function therefore returns one of the possible values shown in Ta- ble 4.7 in e.code. Table 4.7  Constants in the “code” attribute of the “MediaError” interface Value Constant Description 1 MEDIA_ERR_ABORTED Loading was aborted by the user. 2 MEDIA_ERR_NETWORK A network error has occurred. 3 MEDIA_ERR_DECODE An error occurred while decoding the media stream. 4 MEDIA_ERR_SRC_NOT_SUPPORTED The media format is not supported. Chapter 4—Video and Audio 98 We have nearly reached the end of our journey through the HTMLMediaElement inter- face. The remaining attributes are: zz Two boolean attributes for displaying if the browser is currently searching for other data (seeking) or if the end of the stream has been reached (ended) zz An attribute for giving information on the start time of the stream (initialTime) zz An attribute that represents the current timeline offset as a Date object (startOffsetTime) zz Three attributes for implementing the TimeRanges interface—buffered, played, and seekable. The basic idea of TimeRanges is, as its name indicates, recording periods of time: interface TimeRanges { readonly attribute unsigned long length; float start(in unsigned long index); float end(in unsigned long index); }; Using the example of played helps you understand how this works: If we are play- ing the intro of the Big Buck Bunny video and then click Pause, we get a first time range consisting of a start and an end time. The corresponding attributes are played.start(0) and played.end(0), and the number of existing time ranges in played.length is 1. If we then switch to the eighth chapter and continue playback there for a bit, we create the next time range with played.start(1) and played. end(1), and the played.length becomes 2. If two time ranges should overlap, they are combined into one. All ranges are sorted in the TimeRanges object. This way we can track which areas of a media stream are buffered, played, or marked as seekable. A little online example helps visualize the individual TimeRanges while playing the Big Buck Bunny video—take a look at http:// html5.komplett.cc/code/chap_video/js_timeRanges.html. 4.7.9  The Long List of Media Events The list of events fired on loading or playing of a media stream at certain times is long and basically reflects the three main status conditions of the HTMLMedia- Element interface. 4.8  And What About Audio? 99 In the network state, we encounter loadstart, progress, suspend, abort, error, emptied, and stalled, and their names indicate in which network scenarios they appear. In the ready state are loadedmetadata, loadeddata, waiting, play- ing, canplay, or canplaythrough, all relating directly to the availability of data for the current or future playback position. In the playback state are play, pause, timeupdate, ended, ratechange, and durationchange, and again their names are as self-explanatory as is the last element we need to mention, volumechange. When and how each event is used depends entirely on the purpose of your script. For our video player, we needed only two, oncanplay and ontimeupdate. But if we wanted to refine the details, we would almost certainly need many others as well. If you want to read details on the various events, you should refer to the very helpful Event summary in the specification. There you will find not only a description of each event, but also indications as to when it is actually fired. Browse to http://www.w3.org/TR/html5/video.html#mediaevents. If you want to see media events live in action, go to Philippe Le Hégaret’s HTML5 Video, Media Events, and Media Properties test page at W3C: http://www. w3.org/2010/05/video/mediaevents.html. 4.8  And What About Audio? There is not much new to announce about audio in HTML5. Conveniently, video and audio share the HTMLMediaElement interface, which means that everything we have told you about scripting and video is also applicable to audio elements. Understandably, the additional video attributes for width, height, audio, and poster frame of the HTMLVideoElement interface are omitted. audio elements can be easily created via a constructor and have a src attribute assigned to them at the same time: var audio = new Audio(src); Following the pattern of our video player, let’s program an audio player for the Big Buck Bunny soundtrack. Slider, time display, and starting or stopping work in the same way as in the video example. A new feature is the menu for select- ing the track: Different audio files are involved plus two buttons for jumping ahead or backward on the track list. Additionally, we implement looping at the end of all tracks plus random selection of the next track. You can see the result in Figure 4.10. Chapter 4—Video and Audio 100 Figure 4.10  Screen shot of the JavaScript HTML5 audio player The individual tracks were extracted from the video’s soundtrack using the free, cross-platform, sound editor Audacity (http://audacity.sourceforge.net). For private use, you can also download the soundtrack without background noises for free from the homepage of the score’s composer, Jan Morgenstern, at http:// www.wavemage.com/category/music. The screen shot of the audio player will look familiar, because the new buttons once more use certain Unicode symbols for their labels. To be specific, you can see the symbols listed in Table 4.8. Table 4.8  Unicode symbols for audio player buttons Button Entity Unicode Name Skip back ◃ WHITE LEFT-POINTING SMALL TRIANGLE Skip forward ▹ WHITE RIGHT-POINTING SMALL TRIANGLE Loop ↺ ANTICLOCKWISE OPEN CIRCLE ARROW Shuffle ↝ RIGHTWARDS WAVE ARROW The pull-down menu also looks familiar, but this time we do not jump to certain points in the playback time as in the video player; instead, we switch between whole tracks. The menu and the Skip backward, forward, Loop, and Shuffle but- tons have this effect of changing from one track to the next, so the script logic becomes a bit more complicated. NOTE 4.8  And What About Audio? 101 Let’s start with the audio element: On loading the page, we set the src attribute to the first track and define three callbacks. You have already encountered the updateProgress()function, which moves the slider along and updates the time display (see Listing 4.1). The two new callbacks are canPlay(), which is called when a track is ready to play, and continueOrStop(), which decides what to do next at the end of a track. The on- canplay callback canPlay() is rather short and looks like this: canPlay = function() { curPos.max = audio.duration; if (pbStatus.keepPlaying == true) { _play(); } }; Obviously, curPos.max adapts the slider’s max attribute, just as in the video player, but what is the subsequent if block all about? The answer is simple: We try to take the current playback status into account and only keep playing if the player was already in play mode. So the status of the Play button determines if the audio player starts playing after switching to another track. If it is playing, it should keep playing after every track change, but if it is paused, it should only switch tracks and stay paused. This may sound complicated, but the implementation in the play button’s callback is easy; we just add the following code: pbStatus.keepPlaying = (pbStatus.keepPlaying == true) ? false : true; This alternates the status variable pbStatus.keepPlaying between true and false with every click, and the correct decision is reached in canPlay(). Chapter 4—Video and Audio 102 To gain a better understanding of the audio player’s structure and functionality, look at the HTML, JavaScript, and CSS source code. You can find them online at these URLs: zz http://html5.komplett.cc/code/chap_video/js_audioPlayer_en.html zz http://html5.komplett.cc/code/chap_video/js_audioPlayer.js zz http://html5.komplett.cc/code/chap_video/js_audioPlayer.css Back to our example. With canPlay()and pbStatus.keepPlaying, we now have control of the situation if the track is ready to play. But how do we manage switching from one track to the next? As mentioned earlier, there are several op- tions for this: We can choose via the menu, click the Skip back and Skip forward buttons, or let the audio player do it automatically at the end of a track as a result of the settings for the Loop and Shuffle buttons. All of these options have one thing in common: They need to load a new track, and that is done via the method loadTrack(): var loadTrack = function(idx) { audio.src = 'music/'+tracks.options[idx].value; audio.load(); }; Two details need explaining: 1. What is hiding behind the argument idx? Hiding behind idx is the index of the track to be loaded from the pull-down menu in the variable tracks, from which we can extract file names. 2. What does the call audio.load() do? As you may have guessed, it starts loading the new track, which can be played as soon as it has reached the status canplay. To keep things simple, we use only Ogg Vorbis audio files in our example. If we wanted to offer several versions, we would first need to find the suitable format via the method canPlayType() and then load it. Try to add this function to the script when you have reached the end of this chapter! NOTE NOTE 4.8  And What About Audio? 103 loadTrack() is called in various ways. First, when changing tracks directly in the menu via the onchange event handler changeTrack(this): changeTrack = function(ctrl) { loadTrack(ctrl.options.selectedIndex); }; Of course it is also called by the Skip forward and Skip backward buttons; their respective onclick event handler calls the callback function advanceTrack(n) and passes it the step value in the argument n as well as the desired direction via the positive or negative sign. The step value is the same in both cases, which means -1 is skip backward and 1 is skip forward: advanceTrack = function(n) { var idx = tracks.options.selectedIndex + n; if (idx < 0) { idx = idx + tracks.options.length; } if (idx > tracks.options.length-1) { idx = idx - tracks.options.length; } tracks.options.selectedIndex = idx; loadTrack(idx); }; The algorithm for determining the new track is simple and consists of two phases. We first add n to the index of the selected track, and then we deal with two special cases that may arise from this: If we are currently in the first track and click Skip backward, the index becomes negative and we therefore have to keep playing the last track. If we are in the last track and click Skip forward, this also does not work, so we have to make sure the player selects the first track as next track. The advantage of the method advanceTrack() is that we can use it even for the last two features—looping at the end of the track and random track selection. First, we quickly need to discuss exactly how the two buttons signal inactive and active. Switching between the two modes is done via onclick event handlers, which trigger the callback toggleOnOff(node) and assign the appropriate button in the argument node: toggleOnOff = function(node) { var cls = node.getAttribute("class"); node.setAttribute("class", (cls == 'off') ? 'on' : 'off' ); pbStatus[node.id] = node.getAttribute("class"); }; Chapter 4—Video and Audio 104 As the first line of the function indicates, the status is determined by the button element’s class attribute, defining the appearance via CSS. The formats for on and off can be found in the stylesheet js_audioPlayer.css: .off { opacity: 0.2; } .on { opacity: 1.0; } Additionally, the current status of the relevant button is specified in the sta- tus variable pbStatus[node.id] where the node.id indicates loop or shuffle and therefore pbStatus.loop or pbStatus.shuffle is assigned on or off. The correct moment for reacting to this status is always at the end of a track. Now the call- back function continueOrStop() takes effect: continueOrStop = function() { if (pbStatus.shuffle == 'on') { advanceTrack( Math.round(Math.random()*tracks.options.length) ); } else if (tracks.options.selectedIndex == tracks.options.length-1) { if (pbStatus.loop == 'on') { advanceTrack(1); } else { pbStatus.keepPlaying = false; } } else { advanceTrack(1); } }; If we are in shuffle mode, rounding the result of Math.random(), multiplied by the number of all tracks, generates a random number between 0 and the total number of tracks. We then advance by this value in advanceTrack(), and it does not matter by how much we overshoot the target: If we are, for example, in the second-last track and want to skip forward five positions, the algorithm in advanceTrack() ensures that the fourth item on the menu is played. The question “To loop or not to loop?” only ever arises in the last track. If the corresponding button is set to on mode, we start again from the beginning with advanceTrack(1); if it is in off mode, we stop here and set pbStatus.keepPlaying to false. In all other cases we simply go to the next track and start playing it. Summary 105 At this point we have not only completed our audio player, but also reached the end of the chapter on video and audio. Many of the features we programmed manually in the video and audio player are of course also implemented by the browser and can be activated more easily via the controls attribute. But it still makes sense to look behind the scenes to discover the options available when scripting video and audio. Summary With video and audio, two important functions that previously required plug-ins become part of the HTML specification. It is difficult to predict which video co- dec will eventually prevail, although in light of Google’s commitment in favor of WebM, we can hope for a patent-free open format. As the second part of the chapter shows, the HTMLMediaElement Interface makes video and audio accessible for scripting. Using JavaScript allows for an interaction that was not possible previously with the available plug-in solutions. As for every HTML5 topic, there are many more impressive examples to be found online. Take some time to search and discover them for yourself! By reading this chapter you have laid the foundation for understanding these new and fascinat- ing HTML5 features. This page intentionally left blank 5 Canvas One of the most interesting and at the same time one of the oldest new HTML5 elements is Canvas. In July 2004, just one month after the WHATWG was formed, Apple’s David Hyatt presented a proprietary HTML extension named Canvas, an announcement that caused an uproar among the still young HTML5 movement. “The real solution is to bring these proposals to the table,” was Ian Hickson’s first reaction, and after a brief debate, Apple submitted its idea to the WHATWG. This paved the way for including Canvas in the HTML5 specification, and a first draft was published in August 2004. 107 Chapter 5—Canvas 108 You can find Apple’s Canvas announcement and Ian Hickson’s reaction at: zz http://weblogs.mozillazine.org/hyatt/archives/2004_07.html#005913 zz http://ln.hixie.ch/?start=1089635050&count=1 5.1  A First Example Canvas is, simply put, a programmable picture on which you can draw via a Ja- vaScript API. In addition to the canvas via the canvas element, we also need a script element for the drawing commands. Let’s start with the canvas element:   alternative content for browsers without canvas support The attributes width and height determine the dimension of the canvas element in pixels and reserve the corresponding amount of space on the HTML page. If one or both attributes are missing, default values come into effect: 300 pixels for width and 150 pixels for height. The area between the start and end tag is re- served for alternative content, which will be displayed if a browser does not sup- port Canvas. Similar to the alt tag for pictures, this alternative content should describe the content of the Canvas application or show a suitable screen shot. Phrases like Your browser does not support Canvas without any further informa- tion are not very helpful and should be avoided. Our canvas is now finished. In the next step, we can add the drawing commands in a script element. A few lines of code are enough to turn our first, and admit- tedly quite trivial, Canvas example into reality: Even if we do not yet know anything about the syntax of the Canvas drawing com- mands, the result in Figure 5.1 will not come as a surprise if you look closely at the code. We now have a red and a light yellow rectangle with 50% opacity, resulting in an orange tone where the two rectangles overlap. NOTE 5.1  A First Example 109 Figure 5.1  Two overlapping rectangles All figures in this chapter were created as HTML pages using Canvas and can be found online either at the URL visible in the screen shot or via the Index page of the companion website at http://html5.komplett.cc/code/chap_canvas/ index_en.html. Take a look at the source code! Before we can draw on the canvas, we need to create a reference to it. The first line in the script does exactly that. In the variable canvas and using the W3C CSS Selectors API method document.querySelector(), it saves a reference to the first canvas element found in the document: var canvas = document.querySelector("canvas"); Apart from the attributes canvas.width and canvas.height, this object, also called HTMLCanvasElement, has the method getContext(). It allows us to get to the heart of Canvas, the CanvasRenderingContext2D, by passing 2d as context parameter: var context = canvas.getContext('2d'); TIP Chapter 5—Canvas 110 Now we have defined the drawing context and can start drawing the two rect- angles. Without going into details of the attribute fillStyle or the method fill- Rect(), the basic procedure for both is the same: Define the fill color and then add the rectangle: context.fillStyle = 'red'; context.fillRect(0,0,800,600); context.fillStyle = 'rgba(255,255,0,0.5)'; context.fillRect(400,200,800,600); The current Canvas specification only defines a 2D context (see HTML Canvas 2D Context specification at http://www.w3.org/TR/2dcontext) but does not rule out that others, for example 3D, could follow at a later stage. First initiatives in this direction have already been launched by the Khronos group: In coopera- tion with Mozilla, Google, and Opera, they are working on a JavaScript interface called WebGL based on OpenGL ES 2.0 (http://www.khronos.org/webgl). First implementations of this emerging standard are present in Firefox, WebKit, and Chrome. But back to the 2D context: The possibilities of the CanvasRenderingContext2D in- terface are manifold and certainly well-suited for creating sophisticated applica- tions. Figure 5.2 shows a simple bar chart, which will accompany us through an explanation of the first three features of the drawing context: rectangles, colors, and shadows. Figure 5.2  Bar chart with ten horizontal bars 5.2  Rectangles 111 5.2  Rectangles Canvas has four methods for creating rectangles. Three of these we will discuss now, the fourth we will encounter later in connection to paths: context.fillRect(x, y, w, h) context.strokeRect(x, y, w, h) context.clearRect(x, y, w, h) The names of these methods are self-explanatory: fillRect()creates a filled rectangle, strokeRect() a rectangle with border and no filling, and clearRect() a rectangle that clears existing content like an eraser. The rectangle’s dimensions are determined by four numerical parameters: origin x/y, width w, and height h. In Canvas, the coordinate origin is at the top left, which means the x coordi- nates increase toward the right and the y coordinates toward the bottom (see Figure 5.3). Figure 5.3  The Canvas coordinate system In parallel to the first example, we first define a reference to the canvas element in our bar chart and then the drawing context. The function drawBars()is re- sponsible for doing the main job, drawing the horizontal bars. We pass the de- sired number of bars we want to draw to this function: Chapter 5—Canvas 112 Calling this function with drawBars(10) deletes any existing content with clear- Rect() and then draws the ten filled rectangle outlines in the for loop with fill- Rect() and strokeRect(). The width w of the bars varies between 0 pixels and the full width of the canvas element, and is determined randomly via the JavaScript function Math.random(). The function Math.random() generates a number be- tween 0.0 and 1.0, and is therefore ideal for producing random values for width, height, and the position, depending on the canvas dimension. Multiplying with the corresponding attribute value does the job. The equally spaced, horizontal arrangement of the bars follows the canvas height. The spaces between the bars result from multiplying the calculated maximal bar height h by the factor 0.8. The canvas width and height can be easily seen in the attributes canvas.width and canvas.height as mentioned in the first example. Just as easily, we can ac- cess the HTMLCanvasElement from the drawing context via its attribute context. canvas and use it to generate new bars with each click on the canvas. Three lines of code added after the drawBars(10) call are enough: context.canvas.onclick = function() {   drawBars(10); }; We have clarified how the ten bars are drawn, but how do we make them light gray with black outlines? We will find the answer by looking at the options of as- signing color in Canvas. 5.3  Colors and Shadows 113 5.3  Colors and Shadows The attributes fillStyle and strokeStyle serve to specify colors for fills and lines. The color specification follows the rules for CSS color values and can have a number of different formats. Table 5.1 shows the available options, using the color red as an example. Table 5.1  Valid CSS color values for the color red Method Color Value Hexadecimal #FF0000 Hexadecimal (short) #F00 RGB rgb(255,0,0) RGB (percent) rgb(100%,0%,0%) RGBA rgba(255,0,0,1.0) RGBA (percent) rgba(100%,0%,0%,1.0) HSL hsl(0,100%,50%) HSLA hsla(0,100%,50%,1.0) SVG (named color) red To specify the current fill and stroke color in Canvas, you just need to enter the appropriate color values as a character string for fillStyle and strokeStyle. In the bar chart example, we will choose the SVG named color silver as fill and a semitransparent black outline in RGBA notation. We want all bars to look the same, so we define the styles before the drawBars() function: context.fillStyle = 'silver'; context.strokeStyle = 'rgba(0,0,0,0.5)'; var drawBars = function(bars) {   // code for drawing bars }; Valid opacity values range from 0.0 (transparent) to 1.0 (opaque) and can be used as a fourth component in RGB and HSL color space. The latter defines colors not via their red, green, and blue components, but via a combination of hue, satura- tion, and lightness. Chapter 5—Canvas 114 You can find more information on the topic CSS colors with HSL color palettes and a list of all valid SVG color names in the CSS Color Module Level 3 specification at http://www.w3.org/TR/css3-color. If you look closely, you can see shadows behind the bars. These are created by four additional drawing context attributes: context.shadowOffsetX = 2.0; context.shadowOffsetY = 2.0; context.shadowColor = "rgba(50%,50%,50%,0.75)"; context.shadowBlur = 2.0; The first two lines determine the shadow offset with shadowOffsetX and shadowOffsetY, shadowColor assigns its color and opacity, and shadowBlur causes the shadow to be blurred. As a general rule, the higher the value of shadowBlur, the stronger the blur effect. Before moving on to color gradients in the next section, we need to clarify how the dotted border in the bar chart and the subsequent graphics is achieved. The answer is very simple: with CSS. Every canvas element can of course also be for- matted with CSS. You can specify spacing, position, and z-index just as easily as background color and border. In our example, the following style attribute cre- ates the dotted border: 5.4  Gradients In addition to solid colors for fills and lines, Canvas offers two kinds of gradi- ents: linear and radial gradients. The basic principle of creating gradients in Canvas is easily demonstrated using the example of a simple gradient from red to yellow and orange and then to purple (see Figure 5.4). NOTE 5.4  Gradients 115 Figure 5.4  Linear gradient with four colors First, context.createLinearGradient(x0, y0, x1, y1) creates a CanvasGradient object and determines the direction of the gradient via the parameters x0, y0, x1, y1. We still need to specify the color offsets in another step, so we save this object in the variable linGrad: var linGrad = context.createLinearGradient(   0,450,1000,450 ); The method addColorStop(offset, color)of the CanvasGradient object is the next step and selects the desired colors and offsets on our imaginary gradient line. Offset 0.0 represents the color at the point x0/y0 and offset 1.0 the color at the end point x1/y1. All colors in between are divided up according to their offset, and transitions between the individual stops are interpolated by the browser in RGBA color space: linGrad.addColorStop(0.0, 'red'); linGrad.addColorStop(0.5, 'yellow'); Chapter 5—Canvas 116 linGrad.addColorStop(0.7, 'orange'); linGrad.addColorStop(1.0, 'purple'); Colors are specified following the rules for CSS color values and are identified as SVG named colors in our examples to make it more readable. Our linear gradient is now finished and can be assigned via fillStyle or strokeStyle: context.fillStyle = linGrad; context.fillRect(0,450,1000,450); Unlike linear gradients, the start and end points of radial gradients are not points, but circles. So to define a radial gradient, we now need to use the method con- text.createRadialGradient(x0, y0, r0, x1, y1, r1) (see Figure 5.5). Figure 5.5  Components of a radial gradient On the left side of the graphic, you can see the start and end circle, in the middle the three color stops with offset values, and on the right the final result: a sphere that appears to glow. A very appealing result is generated by a bit of clear and simple source code: 5.5  Paths 117 var radGrad = context.createRadialGradient(   260,320,40,200,400,200 ); radGrad.addColorStop(0.0,'yellow'); radGrad.addColorStop(0.9,'orange'); radGrad.addColorStop(1.0,'rgba(0,0,0,0)'); context.fillStyle = radGrad; context.fillRect(0,200,400,400); The shadow effect around the sphere is incidentally created by the last two color stops, interpolating from orange to transparent black, which means the visible part of the gradient ends directly at the outer circle. After this quick trip through the world of colors and gradients, we now move on to other geometric forms: paths. 5.5  Paths The process of creating paths in Canvas is comparable to drawing on a piece of paper: You put the pencil on the paper at one point, draw, lift the pencil off again, and continue drawing at another point on the paper. The content you draw can range from simple lines to complex curves or even polygons formed from these. An initial example illustrates the concept, translating each step of writing the let- ter A into Canvas path commands: context.beginPath(); context.moveTo(300,700); context.lineTo(600,100); context.lineTo(900,700); context.moveTo(350,400); context.lineTo(850,400); context.stroke(); The results are shown in Figure 5.6. Chapter 5—Canvas 118 Figure 5.6  The letter A as a path Let’s look closer at the source code for this example. We can see the three phases of creating the path: 1. Initialize a new path with beginPath() 2. Define the path geometry with moveTo() and lineTo() calls 3. Draw the lines with stroke() Each path must be initialized with beginPath() and can then contain any num- ber of segments. In our example, we have two segments that reproduce the hand movements when writing through combinations of moveTo() and line- To(). This creates first the roof shape and then the horizontal line of the letter A. With stroke(), we then draw the defined path onto the canvas. The decision whether and when segments of a path will be separated into several individual paths is entirely dependent on the layout. Each path can only be for- matted in its entirety. So, if we wanted the horizontal line of the letter A to have a different color, we would need to define two separate paths. Let’s look at the main path drawing methods in more detail. 5.5  Paths 119 5.5.1  Lines To create lines as in our example of the letter A, Canvas offers the method lineTo(): context.lineTo(x, y) The effect of the method is shown in Figure 5.7. Figure 5.7  The path method “lineTo()” Expressed in words, this means line to point x/y, which means we have to already have defined a starting point with moveTo() or still have an end point from the previous drawing step. After drawing the line, the coordinate x/y becomes the new current point. In all graphics used to demonstrate the path drawing methods, we have marked the starting point x0/y0 in light gray and the new current point in bold type. NOTE Chapter 5—Canvas 120 5.5.2  Bézier Curves Canvas knows two kinds of Bézier curves: quadratic and cubic, the latter incor- rectly referred to only as bezierCurveTo(). Figure 5.8 illustrates the former, and Figure 5.9 illustrates the latter. context.quadraticCurveTo(cpx, cpy, x, y) context.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y) Figure 5.8  The path method “quadraticCurveTo()” 5.5  Paths 121 Figure 5.9  The path method “bezierCurveTo()” To create Bézier curves, we need the current point as a starting coordinate plus a target coordinate and, depending on the type of curve, one or two control points. In both cases, the coordinate x/y becomes the new current point after drawing the curve. 5.5.3  Arcs Methods for creating arcs are not quite as straightforward. The first method is defined by two coordinates and a radius: context.arcTo(x1, y1, x2, y2, radius) As shown in Figure 5.10, arcTo() creates the new path as follows: A circle with a given radius is added to the line from x0/y0 to x1/y1 and then to x2/y2, so that the circle touches the line in exactly two points, the start tangent t1 and the end tangent t2. The arc between these two points becomes part of the path, and the end tangent t2 becomes the new current point. Chapter 5—Canvas 122 Figure 5.10  The path method “arcTo()” In practice, this method is very useful for rectangles with rounded corners. A re- usable function will come in handy to do the job shown in Figure 5.11. 5.5  Paths 123 Figure 5.11  Four different rectangles with rounded corners; the circle is an extreme example of a rounded rectangle var roundedRect = function(x,y,w,h,r) {   context.beginPath();   context.moveTo(x,y+r);   context.arcTo(x,y,x+w,y,r);   context.arcTo(x+w,y,x+w,y+h,r);   context.arcTo(x+w,y+h,x,y+h,r);   context.arcTo(x,y+h,x,y,r);   context.closePath();   context.stroke(); }; roundedRect(100,100,700,500,60); roundedRect(900,150,160,160,80); roundedRect(700,400,400,300,40); roundedRect(150,650,400,80,10); The function roundedRect() requires the basic values for the rectangle plus the radius for rounding. It then draws the desired rectangle with a moveTo() method, four arcTo() methods, and a closePath() method. You have not yet encountered the method closePath(): It closes the rectangle by joining the last point back up to the start point. Chapter 5—Canvas 124 The second option for creating arcs—the method arc()—seems even more com- plicated at first glance. In addition to center and radius, we now have to specify two angles and the direction of rotation: context.arc(x, y, radius, startAngle, endAngle, anticlockwise) The center point of the arc in Figure 5.12 is the center of a circle with a given ra- dius. Originating from this point, the angles startAngle and endAngle create two handles, intersecting the circle in two points. The direction of the arc between these two coordinates is determined by the parameter anticlockwise, where 0 means clockwise and 1 counterclockwise. Figure 5.12  The path method “arc()” The resulting arc begins in the center of the circle at the point x0/y0, joins this point in a straight line to the first intersection point spx/spy, and from there draws an arc to the end point epx/epy, which now becomes the new current point. The biggest drawback in creating arcs is that all angles must be specified in radi- ans instead of degrees. So here’s a quick helper to refresh your memory on how to convert: 5.5  Paths 125 var deg2rad = function(deg) {   return deg*(Math.PI/180.0); }; Talking of helper functions, let’s use two more to facilitate drawing circles and sectors. For circles, we really only need center and radius, the rest will be taken care of by the function circle(): var circle = function(cx,cy,r) {   context.moveTo(cx+r,cy);   context.arc(cx,cy,r,0,Math.PI*2.0,0); }; Especially for circle diagrams, also called pie charts, specifying the angles in radians seems hardly intuitive. Our function sector() does the tedious conver- sion chore for us and allows us to specify start and end angles in degrees: var sector = function(cx,cy,r,     startAngle,endAngle, anticlockwise   ) {   context.moveTo(cx,cy);   context.arc(     cx,cy,r,     startAngle*(Math.PI/180.0),     endAngle*(Math.PI/180.0),     anticlockwise   );   context.closePath(); }; Now, just a few lines of code are enough to draw circles and pie charts without losing track: context.beginPath(); circle(300,400,250); circle(300,400,160); circle(300,400,60); sector(905,400,250,-90,30,0); sector(900,410,280,30,150,0); sector(895,400,230,150,270,0); context.stroke(); Figure 5.13 shows the result. Chapter 5—Canvas 126 Figure 5.13  Circles and sectors 5.5.4  Rectangles The method rect() handles a bit like our helpers, unlike the other methods: context.rect(x, y, w, h) In contrast to the previous path drawing methods, the current point x0/y0 is ig- nored altogether when drawing with rect(); instead, the rectangle is defined via the parameters x, y, width w, and height h. The origin point x/y then becomes the new current point after drawing (see Figure 5.14). 5.5  Paths 127 Figure 5.14  The path method “rect()” 5.5.5 Outlines, Fills, and Clipping Masks If we think back to the three stages of creating a path with initialization—deter- mining path, geometry, and drawing—we have now reached the third and last stage: the drawing. Here we decide what the path should look like. In all previ- ous examples, we chose a simple outline at this point, created via the following method: context.stroke() The line color is determined by the attribute strokeStyle. You can also define the width of the line (lineWidth), what the ends of the line should look like (lineCap), and the join between lines (lineJoin) using three other Canvas attributes (the asterisk indicates default values; we will encounter it repeatedly from now on): context.lineWidth = [ Pixel ] context.lineCap = [ *butt, round, square ] context.lineJoin = [ bevel, round, *miter ] Figure 5.15 provides examples of the width, end, and join attributes. Chapter 5—Canvas 128 Figure 5.15  Attributes for determining line styles The lineWidth is specified in pixels; the default setting is 1.0. As with the two other line attributes, the line width applies not only to lines and polygons, but also to rectangles created with strokeRect(). If we want to add a cap to a line with lineCap, we can choose butt, round, or square; butt is the default value. If we use round, the line gets a round cap by adding a semicircle at the end of the line with half the lineWidth as a radius. For square, the semicircle is replaced by a rectangle with a height of half the line width. To create beveled line joins, we use the attribute lineJoin with bevel; we can also round the corners and create mitered joins with miter, which is the default value. To stop the angle of miter lines from becoming too acute, the specification provides the attribute miterLimit with a default value of 10.0. This is the ratio of the length of the tapered point (the distance between the intersection of lines and point) to half the line width. If the miterLimit is exceeded, the point will be trimmed, creating the same effect as in bevel. To fill paths with a color or gradient, we first need to set the appropriate style at- tribute with fillStyle and then call the following path method: context.fill() 5.5  Paths 129 This may sound simple but can get very complicated if paths self-intersect or are nested. In such cases, the so-called non-zero winding number rule takes ef- fect: It decides whether to fill or not depending on the winding direction of the subpaths involved. Figure 5.16 shows the non-zero rule in action. On the left, both circles were drawn in clockwise direction; on the right, the inner circle was drawn counterclockwise, leading to the hole in the center. Figure 5.16  The non-zero fill rule for paths To help us draw the directional circles, we used the helper from the arc()section, this time slightly modified: The desired direction is now passed as an argument. Valid settings for anticlockwise are 0 and 1: var circle = function(cx,cy,r,anticlockwise) {   context.moveTo(cx+r,cy);   context.arc(cx,cy,r,0,Math.PI*2.0,anticlockwise); }; The code for the circle on the right with the hole in it looks like this: context.beginPath(); context.fillStyle = 'yellow'; Chapter 5—Canvas 130 circle(900,400,240,0); circle(900,400,120,1); context.fill(); context.stroke(); After stroke() and fill(), we need only one other method for drawing paths— the method context.clip(). The explanation is as short as its name: clip() ensures that the defined path is not drawn but used as a cutout for all other drawing elements. Anything within the mask remains visible; the rest is hidden. You can reset the mask by creating another clipping mask using the entire canvas area as geometry. We will encoun- ter a more elegant method later on, in section 5.13, with save() and restore(). Let’s now move on to the topic of text, a topic to which the specification devotes only four pages. Could it be that text support in Canvas is not exactly great? 5.6  Text At first glance, it is probably true that text support in Canvas is not great, because the options for using text in Canvas are meager and limited to formatting and po- sitioning simple character strings. There is no running text with automatic line breaks, nor paragraph formats or the option to select already existing texts. We are left with three attributes for determining text attributes, two methods for drawing text, and one method for determining text length of a character string while taking into account the current format. This does not seem like much, but if we look more closely, it becomes clear that those four pages of specification are based on well-thought-out details. 5.6.1  Fonts The definition of the font attribute simply refers to the CSS specification and states that context.font is subject to the same syntax as the CCS font shorthand notation: context.font = [ CSS font property ] In this manner, all font properties can be easily specified in a single string. Table 5.2 lists the individual components and their possible values. 5.6  Text 131 Table 5.2  The components of the CSS “font” property Property Values font-style *normal, italic, oblique font-variant *normal, small-caps font-weight *normal, bold, bolder, lighter 100, 200, 300, 400, 500, 600, 700, 800, 900 font-size xx-small, x-small, small, *medium, large, x-large, xx-large, larger, smaller em, ex, px, in, cm, mm, pt, pc, % line-height *normal, , em, ex, px, in, cm, mm, pt, pc, % font-family Font family or generic font family, such as serif, sans- serif, cursive, fantasy, monospace When assembling the font attribute, only the properties font-size and font- family are required. All others are optional, and if omitted, default to the values marked with an asterisk as shown in Table 5.2. Because Canvas text does not recognize line breaks, the attribute line-height has no effect and is always ignored. The cleaned-up pattern for assembling the components is therefore: context.font = [   font-style font-variant font-weight font-size font-family ] Regarding the font-family, the same rules apply as for defining fonts in stylesheets: You can specify any combination of font families and/or generic font families. The browser then picks the first known font from that priority list. You can achieve complete independence from the browser or the relevant plat- form and its fonts by using webfonts. Once they are integrated into a stylesheet via @font-face, they are available as font-family in Canvas, too, via the font name assigned: @font-face {   font-family: Scriptina;   src: url('fonts/scriptina.ttf'); } Figure 5.17 shows brief examples of valid CSS font attributes and their render- ing in Canvas. The source of the webfont Scriptina in the preceding example is http://www.fontex.org—a well-organized collection of free fonts that are avail- able for download. Chapter 5—Canvas 132 Figure 5.17  Font formatting with the “font” attribute At the time of this writing, no browser supported @font-face without problems. In Firefox, for example, the webfont Scriptina in the last line only appears in Can- vas if it is used at least once in the HTML document. The correct implementation of small-caps is also missing in Firefox, which is why the second to last example is not displayed correctly either. 5.6.2  Horizontal Anchor Point The attribute textAlign determines the horizontal anchor point of Canvas texts: context.textAlign = [   left | right | center | *start | end ] The keywords left, right, and center are familiar from the CSS attribute text- align, whereas start and end are already CSS3 extensions that allow for text di- rection, depending on the appropriate language. Some languages are written not from left to right but sometimes from right to left, as for example, Arabic and Hebrew. 5.6  Text 133 Figure 5.18 presents the horizontal anchor points for writing with textflow ltr (left to right) and rtl (right to left), demonstrating the effect of directionality on the attributes start and end. In the browser, the directionality of a document can be changed via the global attribute document.dir: document.dir = [ *ltr | rtl ] NOTE Figure 5.18  Horizontal anchor points with “textAlign” 5.6.3  Vertical Anchor Point The vertical anchor point and therefore the baseline on which all glyphs are aligned is determined by the third and last text attribute, textBaseline: context.textBaseline = [   top | middle | *alphabetic | bottom | hanging | ideographic ] Chapter 5—Canvas 134 The first four textBaseline keywords, top, middle, alphabetic and bottom are self-explanatory. A hanging baseline is required by Devanagari, Gurmukhi, and Bengali, three Indian alphabets used for writing the languages Sanskrit, Hindi, Marathi, Nepali or Panjabi, and Bengali. The group of ideographic writing sys- tems includes Chinese, Japanese, Korean, and Vietnamese. Figure 5.19 illustrates the textBaseline vertical anchor points. Figure 5.19  Vertical anchor points with “textBaseline” 5.6.4  Drawing and Measuring Text Once font and anchor point have been determined, you only need to draw the text. Similar to rectangles, you can decide on a fill and/or outline, and you can even specify the maximum text width with an optional parameter, maxwidth: context.fillText(text, x, y, maxwidth) context.strokeText(text, x, y, maxwidth) Finally, you can measure the text dimension with the method measureText(), which can at least determine the width while taking into account the current for- mat. In our example in Figure 5.20, the bottom right value (759) was calculated using this method: TextWidth = context.measureText(text).width 5.7  Embedding Images 135 Figure 5.20  “fillText()”, “strokeText()”, and “measureText()” It is not currently possible to determine the height and origin point of the bound- ing box, but this may be implemented in a future version of the specification, together with multiline text layout. The final note in the text chapter of the Can- vas specification sounds promising: It indicates that in the future, fragments of documents (e.g., formatted paragraphs) might also find their way into Canvas via CSS. The Canvas API offers a multitude of options for working in Canvas with raster- based formats not only in the future, but right now. In addition to embedding images and videos, you also have optional reading and writing access to every pixel on the canvas area. You can read up on how to do this in section 5.8, Pixel Manipulation. 5.7  Embedding Images For embedding images, Canvas offers the method drawImage(),which we can in- voke with three different parameter sets (the method can take three, five, or nine arguments): Chapter 5—Canvas 136 context.drawImage(image, dx, dy) context.drawImage(image, dx, dy, dw, dh) context.drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh) In all three cases we need an image, canvas, or video element in the first parameter, which can be dynamically integrated via JavaScript or statically in the HTML code. Animated pictures or videos are not rendered in animation but displayed statically as the first frame or a poster frame if present. All other arguments of the method drawImage() affect position, size, or cropping the source image to render in the target canvas. Figure 5.21 shows the graphic interpretation of the possible position parameters; the prefix s stands for source and d for destination. Figure 5.21  Position parameters of the “drawImage()” method Let’s now compare the individual drawImage() methods using three simple ex- amples. The common setup is a picture measuring 1200 × 800 pixels, created dynamically as a JavaScript object (see Figure 5.22): var image = new Image(); image.src = 'images/yosemite.jpg'; 5.7  Embedding Images 137 Figure 5.22  The source image of all “drawImage()” examples In addition to pixel sizes, which we will encounter in the examples, Figure 5.22 shows the impressive 1000-meter-high rock face of El Capitan in Yosemite Na- tional Park: The photo was taken from Taft Point. This picture is now drawn onload onto the 600 × 400 pixel target canvas, using one of the three possible sets of arguments. The first and simplest option determines the top-left corner of the image in the target canvas with dx/dy. In our case, this is the position 0/0: image.onload = function() {   context.drawImage(image,0,0); }; Width and height are copied directly from the original image, and because our image is bigger than the target canvas, it will come as no surprise that we only see the top-left quarter of Taft Point on our canvas (see Figure 5.23). Chapter 5—Canvas 138 Figure 5.23  Taft Point in Yosemite National Park If we want to represent the whole image in the canvas, we also have to specify the desired width and height in the arguments dw/dh. The browser then takes care of scaling the image to 600 × 400 pixels. The result is shown in Figure 5.24: image.onload = function() {   context.drawImage(image,0,0,600,400); }; 5.7  Embedding Images 139 Figure 5.24  Taft Point with El Capitan in Yosemite National Park In contrast to the two previous variations of drawImage(), which could have been realized with CSS as well, the third variation offers completely new possibilities of working with images. We can now copy any section of the source image (sx, sy, sw, sh) into the defined area of the target canvas (dx, dy, dw, dh). So nothing stands in the way of image montage: image.onload = function() {   context.drawImage(image,0,0);   context.drawImage(     image, 620,300,300,375,390,10,200,250   ); }; The result is shown in Figure 5.25. Chapter 5—Canvas 140 Figure 5.25  Yosemite National Park postcard The first drawImage() call returns again the top-left quarter of Taft Point; the sec- ond extracts the area of El Capitan and draws it as icon into the top-right corner. Text with shadows completes the rudimentary layout of our postcard. If you would rather have El Capitan in the foreground and Taft Point as a stamp at the top right, you just need to slightly modify the drawImage() calls. In our ex- ample you can do this by clicking on the canvas: canvas.onclick = function() {   context.drawImage(     image,600,250,600,400,0,0,600,400   );   context.drawImage(     image,0,0,500,625,390,10,200,250   ); }; This yields the image shown in Figure 5.26. 5.8  Pixel Manipulation 141 Figure 5.26  Yosemite National Park postcard (alternative layout) This was a brief introduction to the topic drawImage(), using an image as a source. You will find a detailed example of using the video element as the first parameter of drawImage() in section 5.14.2, Playing a Video with “drawImage()”, but first we will discuss how you can get both read and write access to pixel values on the canvas area. 5.8  Pixel Manipulation As methods for reading and manipulating pixel values, we have three choices: getImageData(), putImageData(), and createImageData(). Because all three contain the term ImageData, we first need to define what this refers to. 5.8.1  Working with the “ImageData” Object Let’s approach the ImageData object with a 2 × 2 pixel-sized canvas, onto which we draw four rectangles 1 × 1 pixels big and filled with the named colors navy, teal, lime, and yellow: Chapter 5—Canvas 142 context.fillStyle = 'navy'; context.fillRect(0,0,1,1); context.fillStyle = 'teal'; context.fillRect(1,0,1,1); context.fillStyle = 'lime'; context.fillRect(0,1,1,1); context.fillStyle = 'yellow'; context.fillRect(1,1,1,1); In the next step, we use the method getImageData(sx, sy, sw, sh) to get the ImageData object. The four arguments determine the desired canvas section as a rectangle, as shown in Figure 5.27: ImageData = context.getImageData(   0,0,canvas.width,canvas.height ); Figure 5.27  The “ImageData” object The ImageData object has the attributes ImageData.width, ImageData.height, and ImageData.data. The latter hides the actual pixel values in the so-called CanvasPixelArray. This is a flat array with red, green, blue, and alpha values for each pixel in the selected section, starting at the top left, from left to right and 5.8  Pixel Manipulation 143 top to bottom. The number of all values is saved in the attribute ImageData. data.length. Using a simple for loop, we can now read the individual values of the CanvasPix- elArray and make them visible with alert(). Starting at 0, we work from pixel to pixel by increasing the counter by 4 after each loop. The RGBA values are the result of offsets from the current position. Red can be found at counter i, green at i+1, blue at i+2, and the alpha component at i+3: for (var i=0; i255) ? 255 : parseInt(rS),     (gS>255) ? 255 : parseInt(gS),     (bS>255) ? 255 : parseInt(bS),     a   ]; }; Adding up the multiplied components can lead to values larger than 255 in each of the three calculations; in this case, 255 is inserted as a new value. Inverting colors is very easy with the filter invertColor(): You simple deduct each RGB component from 255: var invertColor = function(r,g,b,a) {   return [     (255-r),     (255-g),     (255-b),     a   ]; }; The filter swapChannels() modifies the sequence of the color channels. We first need to define the desired order as the fourth parameter in an array, where 0 is red, 1 is green, 2 is blue, and 3 is the alpha channel. To swap channels, we use the array rgba with the corresponding starting values and then return it in the new order. So changing from RGBA to BRGA, as in our example, can be achieved via order=[2, 0, 1, 3]: Chapter 5—Canvas 148 var swapChannels = function(r,g,b,a,order) {   var rgba = [r,g,b,a];   return [     rgba[order[0]],     rgba[order[1]],     rgba[order[2]],     rgba[order[3]]   ]; }; The last method, monoColor(), sets each pixel’s RGB component to a particu- lar color, using the starting pixel’s gray value as an alpha component. When the function is called, the fourth parameter defines the desired color as an array of RGB values—in our case, blue with color= [0, 0, 255]: var monoColor = function(r,g,b,a,color) {   return [     color[0],     color[1],     color[2],     255-(parseInt((r+g+b)/3.0))   ]; }; The filters we have introduced here are still rather simple, changing the color values of individual pixels without taking into account the neighboring pixels. If you factor these into the calculation, you can achieve more complex methods, such as sharpen, unsharp mask, or edge detection. Discussing such filters in detail would go beyond the scope of this book. If you want to explore more, check out Jacob Seidelin’s Pixastic Image Processing Library (http://www.pixastic.com/lib). More than 30 JavaScript filters, available free under the Mozilla Public License, are just waiting to be discovered. In the meantime, let’s turn to Thomas Porter and Tom Duff, two Pixar Studios gurus who created a sensation back in 1984 with their article on alpha blending techniques. The digital compositing techniques they described not only earned them a prize at the Academy of Motion Picture Arts and Sciences, but also found their way into the Canvas specification. NOTE 5.9  Compositing 149 5.9  Compositing The possibilities of compositing in Canvas are many and varied, but you will only find a few good examples of their use on the Internet. Most are limited to presenting the methods per se, and to start with, that’s what we will do, too. Fig- ure 5.30 shows valid keywords of the globalCompositeOperation attribute, their Porter-Duff equivalent (in italics, with A,B), and the result after drawing. First, we draw the blue rectangle as background, then we set the desired com- posite method, and finally we add the red circle. So for the first method, source- over, which is also the default value of the globalCompositeOperation attribute, the code looks like this: context.beginPath(); context.fillStyle = 'cornflowerblue'; context.fillRect(0,0,50,50); context.globalCompositeOperation = 'source-over'; context.arc(50,50,30,0,2*Math.PI,0); context.fillStyle = 'crimson'; context.fill(); The image looks like that shown in Figure 5.30. Figure 5.30  Values of the “globalCompositeOperation” attribute Chapter 5—Canvas 150 The circle is the source (A); the rectangle is the destination (B). Let’s use the Porter- Duff terms to explain the different methods, because they are much more intui- tive and describe more precisely what is going on. With source-over, we draw A over B; with source-in, only that part of A that is in B; with source-out, only that part of A that is outside of B; and with source- atop, we draw both A and B but only the part of A that overlaps B. The second line reverses the whole thing, so we do not need to explain it again. The method lighter adds colors in the overlapping area, which makes it lighter. copy eliminates B and only draws A, and xor removes the intersection of A and B. The question mark indicates that vendor-specific composting operations are also allowed, similar to the getContext() method. Unfortunately, compositing is not yet fully implemented in any browser, which makes it difficult to sensibly present all methods. We will pick two and take a look at some examples for using the operations destination-in and lighter. If we use destination-in to combine image and text, we can achieve a cutout effect, as shown in Figure 5.31. First, we draw the image with drawImage(), set the compositing method, and then insert the text with a maximum width of 1080 pixels. The text formatting corresponds to a font-size of 600 px with a text an- chor point at the center top and a 60 pixel border with round line caps and joins: context.drawImage(image,0,0,1200,600); context.globalCompositeOperation = 'destination-in'; context.strokeText('HTML5',600,50,1080); 5.9  Compositing 151 Figure 5.31  Compositing operation “destination-in” with image and text The light gray text is again written with the default compositing method source- over and therefore not affected by the effect. Currently, it is not possible to define several texts as cutout at the same time because of the already mentioned short- fall in browser implementation. Our second example uses the method lighter, expanding the previously men- tioned options for color manipulation in images. With lighter, Figure 5.32 com- bines the Yosemite picture with 16 rectangles in the named standard colors, offering a CPU-friendly alternative to the color filter monoColor() mentioned in section 5.8.2, Color Manipulation with “getImageData()”, “createImageData()”, and “putImageData()”. So we could implement the example used in that section differently and achieve a similar result: context.drawImage(img,0,0,210,140); context.globalCompositeOperation = 'lighter'; context.fillStyle = 'blue'; context.fillRect(0,0,210,140); Chapter 5—Canvas 152 Figure 5.32  Compositing operation “lighter” with 16 base colors We will encounter the compositing operator destination-out once more in the mirror effect in Figure 5.37 in section 5.11, Transformations. Let’s first turn to user-defined patterns in Canvas. 5.10  Patterns To create user-defined patterns for fills and lines, the specification offers the method createPattern(). Similar to drawImage(), it accepts both image elements and canvas or video elements as input, defining the type of pattern repetition in the parameter repetition: context.createPattern(image, repetition) Permitted values of the repetition argument are, as with the CSS specification’s background-color attribute, repeat, repeat-x, repeat-y, and no-repeat. If we again use the 16 named basic colors, we can use a few lines of code to create checkered patterns, each with two pairs of colors (see Figure 5.33). 5.10  Patterns 153 Figure 5.33  Checkered pattern in eight color combinations The pattern is created as an in-memory canvas with a 20 × 20 pixel width and four 10 × 10 pixel squares. Illustrated using the example of the green pattern, this step looks as follows: var cvs = document.createElement("CANVAS"); cvs.width = 20; cvs.height = 20; var ctx = cvs.getContext('2d'); ctx.fillStyle = 'lime'; ctx.fillRect(0,0,10,10); ctx.fillRect(10,10,10,10); ctx.fillStyle = 'green'; ctx.fillRect(10,0,10,10); ctx.fillRect(0,10,10,10); We then define the canvas cvs as a repeating pattern using createPattern(), as- sign it to the attribute fillStyle, and use it to fill the square: context.fillStyle = context.createPattern(cvs,'repeat'); context.fillRect(0,0,220,220); Chapter 5—Canvas 154 Patterns are anchored to the coordinate origin and applied starting from that point. If we were to begin fillRect() in the preceding example ten pixels to the right, at 10/0 instead of at 0/0, the first color in the top-left corner would be green instead of lime. In addition to user-defined canvas elements, we can also use images as sources of patterns. Figure 5.34 shows an example using createPattern() to fill the back- ground, to create a pattern for the title text, and to cut out individual sections of the familiar Yosemite picture. The two other pictures, pattern_107.png and pattern_125.png, are part of the Squidfingers pattern library, where you have the choice of nearly 160 other appealing patterns to download: http://www. squidfingers.com/patterns. Figure 5.34  Pattern using images as a source Let’s first look at how the background is created: var bg = new Image(); bg.src = 'icons/pattern_125.png'; bg.onload = function() {   context.globalAlpha = 0.5;   context.fillStyle = context.createPattern(bg,'repeat');   context.fillRect(0,0,canvas.width,canvas.height); }; 5.10  Patterns 155 The first two lines create a new Image object, setting its src attribute to the image pattern_125.png in the folder icons. Just as with drawImage(), we need to make sure that the image is really loaded before defining the pattern. The function bg.onload() contains the real code for generating the repeating pattern, which we apply at 50% opacity to the whole canvas area. With the same procedure, we fill the title text Yosemite! with the image pattern_107.png. For the overlapping image sections, we simply enter the whole Yosemite photo yosemite.jpg as the pattern and then work in a for loop through the input array extents, which contains the x-, y-, width-, and height-values of the sections we want. By calling fillRect(), the relevant image area is shown as fill pattern and receives an additional border with strokeRect(): var extents = [   { x:20,y:50,width:120,height:550 } // and 7 others ... ]; var image = new Image(); image.src = 'images/yosemite.jpg'; image.onload = function() {   context.fillStyle = context.createPattern(     image,'no-repeat'   );   for (var i=0; i