<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>HTML5 Doctor</title>
	<atom:link href="http://html5doctor.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://html5doctor.com</link>
	<description>helping you implement HTML5 today</description>
	<lastBuildDate>Wed, 16 May 2012 11:31:21 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=</generator>
		<item>
		<title>HTML5 adaptive images: end of round one</title>
		<link>http://html5doctor.com/html5-adaptive-images-end-of-round-one/</link>
		<comments>http://html5doctor.com/html5-adaptive-images-end-of-round-one/#comments</comments>
		<pubDate>Wed, 16 May 2012 10:36:45 +0000</pubDate>
		<dc:creator>Bruce Lawson</dc:creator>
				<category><![CDATA[Attributes]]></category>
		<category><![CDATA[Elements]]></category>
		<category><![CDATA[Specification Changes]]></category>

		<guid isPermaLink="false">http://html5doctor.com/?p=4645</guid>
		<description><![CDATA[<p>After The Great Vendor Prefix Hullaballoo of April 2012 comes The Great Responsive Images Brouhaha of May 2012. We look at the main competing formats for adding adaptive images to HTML - the <code>&#60;picture&#62;</code> element, and the <code>&#60;img srcset=""&#62;</code> attribute.</p>]]></description>
			<content:encoded><![CDATA[<p>After <a href="http://dev.opera.com/articles/view/opera-mobile-emulator-experimental-webkit-prefix-support/">The Great Vendor Prefix Hullaballoo of April 2012</a> comes The Great Responsive Images Brouhaha of May 2012. </p>
<p>Adaptive images are the next unsolved mystery of Responsive Web Design. Do you send large high-res images suitable for retina dispays, which are scaled down on smaller, lower res devices and which therefore waste bandwidth? Or do you send low-res images, whch look grotty when scaled up to large screens or high-res displays? Authors have had to rely on <a href="http://css-tricks.com/which-responsive-images-solution-should-you-use/">elaborate hacks</a> to send different content images (that is <code>&lt;img&gt;</code> in HTML rather than CSS background images) to different types of devices.</p>
<p>By November 2011, I was so frustrated that no specification body was considering the problem that <a href="http://www.brucelawson.co.uk/2011/notes-on-adaptive-images-yet-again/">I proposed a strawman &lt;picture&gt; element</a> that re-used the mechanism of HTML5 &lt;video&gt; with its media queries to swap in different source files:</p>
<pre><code>
&lt;picture alt=&quot;angry pirate&quot;&gt;
   &lt;source src=hires.png media=&quot;min-width:800px&quot;&gt;
   &lt;source src=midres.png media=&quot;min-width:480px&quot;&gt;
   &lt;source src=lores.png&gt;
      &lt;!-- fallback for browsers without support --&gt;
      &lt;img src=midres.png alt=&quot;angry pirate&quot;&gt;
&lt;/picture&gt;</code>
</pre>
<p>Around the same time, others <a href="http://www.w3.org/community/respimg/2012/02/23/picture-for-existing-browsers/">independently came to the same idea</a> and were advised to set up a <a href="http://www.w3.org/community/respimg/">W3C community group</a> to discuss it which they did. However, in January, the HTML5 editor, <a href="http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2012-January/034490.html">Ian Hickson, had said</a></p>
<blockquote>What&#8217;s the use case for doing it for images in &lt;img&gt; elements? Typically &lt;img&gt; elements are for content images, where you don&#8217;t usually want to adapt anything.</blockquote>
<p>Those web authors in the W3C Resposive Images Community Group  soldiered on in frustration that they were they being ignored  because the problem itself wasn&#8217;t seen as a problem. Then this week, Edward O&#8217;Connor of Apple suggested another method, using a <a href="http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2012-May/035746.html">new <code>srcset</code> attribute</a> on the &lt;img&gt; element. This complemented a similar suggestion of his from February for <a href="http://lists.w3.org/Archives/Public/www-style/2012Feb/1103.html">img-set in CSS</a> that is already being added to WebKit:</p>
<pre><code>&lt;img src="foo-lores.jpg"
     srcset="foo-hires.jpg 2x, foo-superduperhires.jpg 6.5x"
     alt="decent alt text for foo."&gt;</code></pre>
     <p>The numbers &#8220;2&#8243; and &#8220;6.5x&#8221; tell the browser the relative resolutions; foo-hires.jpg is 2x the resolution of foo-lores.jpg.</p>
<p>Only a few days later, a variant of Apple&#8217;s suggestion was <a href="http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2012-May/035855.html">added to the spec</a>.</p>
<p>There are two major differences between &lt;picture&gt; and srcset. The most obvious is that srcset uses the &lt;img&gt; element, which is great because that&#8217;s the natural place for images, adaptive or not. (You can&#8217;t re-use the &lt;video&gt; + &lt;source&gt; pattern with &lt;img&gt; because it is an empty element so can&#8217;t have child elements. O&#8217;Connor&#8217;s solution uses attributes, which are fine.)</p>
<p>The other major difference is that it doesn&#8217;t use Media Queries. With Media Queries, the author is reponsible for thinking up every permuations of viewport size, orientation, dpi, colour depth, aspect ratio and the like, deciding how to cater for them (if at all), identifing the breakpoints and coding them up. This requires a lot of consideration by the author, and makes for verbose code; a page with 20 pictures, each with 5 Media Queries on 5 &lt;source&gt; elements quickly becomes a lot of code.</p><p>O&#8217;Connor wrote</p>
<blockquote>
<p>Why provide a scale factor and not a media query? Well, media queries are claims about UA state, whereas here we&#8217;re asserting something about the relationship between the image assets. Also, User Agents should be free to use whichever asset they deem best suited to their current situation, taking into account not just &#8220;media-queriable things&#8221; like device resolution but also any scaling applied to the &lt;img&gt; with CSS, its width=&#8221;" and height=&#8221;" attributes, or even things like the current page zoom level.</p>

</blockquote>
<p>I have a lot of sympathy with allowing the browser to make decisions about what it knows of the environment (network speed, latency, pixel density, orientation) to choose the best image for the job. The idea is that the author shouldn&#8217;t be expected to anticipate and cater for all those variables. What she can do is describe the things she knows about -the images, their size and pixel density- and the browser will make its choice.</p><p>That way, when we&#8217;re all living in space and looking a 3D holograms, the proximity to a black hole can be detected by the iDroid3000 device (black holes notoriously cause Web hologram negative timespace inversions) and the right image chosen; we don&#8217;t need to invent new media queries for event horizon proximity and retrospectively add it to our websites.</p>
<p>There are two problems with the srcset suggestion. The first is highly subjective, but many feel the same: as it exists in the <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/embedded-content-1.html#attr-img-srcset">current, first draft of the spec</a>, the syntax is revolting:</p>
<pre><code>&lt;img src="face-600-200-at-1.jpeg" alt=""
srcset="face-600-200-at-1.jpeg 600w 200h 1x,
face-600-200-at-2.jpeg 600w 200h 2x,
face-icon.png 200w 200h"&gt;</code></pre>
<p>Of course, this can be improved, and must be. This isn&#8217;t just about aesthetics. If the syntax is too weird, it will be used wrongly. As <a href="https://twitter.com/#!/rem/status/202306584880234496">Dr Remy wrote</a>, &#8220;Good to see authors have <em>another</em> microsyntax to learn. It&#8217;s not like they had any trouble with vendor-prefixes.&#8221;</p>
	
<p>The second problem is that authors don&#8217;t want to relinquish control. There are questions of art direction (see the section headed <a href="http://css-tricks.com/which-responsive-images-solution-should-you-use/">Do I care about art direction?</a>), and many remain unconvinced that the Apple suggestion addresses that; proponents of srcset are convinced that <a href="http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2012-May/035907.html">it does address those use cases</a>. </p> 
<p>Debate continues, with a <a href="http://www.cartoonstock.com/directory/e/exchange_of_views.asp">full and frank exchange of views</a>. There are understandably <a href="http://timkadlec.com/2012/05/wtfwg/">hurt feelings</a>, too, because some of those who laboured in the Community Group feel that <a href="http://www.alistapart.com/articles/responsive-images-and-web-standards-at-the-turning-point/">their wishes and work have been ignored</a>.</p> 
<p>As one of those who proposed &lt;picture&gt;, I have a degree of attachment to it. That&#8217;s ego. (In fact, I&#8217;d be delighted if it were called the &lt;yayBruce&gt; element, but I&#8217;m resigned to the unfairness of life.) But I don&#8217;t really care which syntax makes the spec, as long as it addresses the majority of use cases and it is usable by authors. I&#8217;m just glad we&#8217;re discussing the adaptive image problem at all.</p>
<p>So, get involved. Read the discussions and say your piece. And once the dust has settled and the specification is looking stable, we Doctors will write up our diagnosis.</p> <div id="crp_related"><h3>Related Posts:</h3><ul class="related"><li><a href="http://html5doctor.com/html5-briefing-notes-journalists-analysts/" rel="bookmark" class="crp_title">HTML5: briefing notes for journalists and analysts</a></li><li><a href="http://html5doctor.com/html5-simplequiz-6-zeldmans-fat-footer/" rel="bookmark" class="crp_title">HTML5 Simplequiz 6: Zeldman&#8217;s fat footer</a></li><li><a href="http://html5doctor.com/getusermedia/" rel="bookmark" class="crp_title">It&#8217;s Curtains for Marital Strife Thanks to getUserMedia</a></li><li><a href="http://html5doctor.com/why-designers-should-care-about-html5/" rel="bookmark" class="crp_title">Why designers should care about HTML5</a></li><li><a href="http://html5doctor.com/html5-simplequiz-4-figures-captions-and-alt-text/" rel="bookmark" class="crp_title">HTML5 Simplequiz #4: figures, captions and alt text</a></li></ul></div><p><a href="http://html5doctor.com/html5-adaptive-images-end-of-round-one/" rel="bookmark">HTML5 adaptive images: end of round one</a> originally appeared on <a href="http://html5doctor.com">HTML5 Doctor</a> on May 16, 2012.</p>
]]></content:encoded>
			<wfw:commentRss>http://html5doctor.com/html5-adaptive-images-end-of-round-one/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
		<item>
		<title>HTML5 Audio — The State of Play</title>
		<link>http://html5doctor.com/html5-audio-the-state-of-play/</link>
		<comments>http://html5doctor.com/html5-audio-the-state-of-play/#comments</comments>
		<pubDate>Tue, 08 May 2012 14:00:24 +0000</pubDate>
		<dc:creator>Mark Boas</dc:creator>
				<category><![CDATA[Elements]]></category>
		<category><![CDATA[JavaScript APIs]]></category>
		<category><![CDATA[multimedia]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[audio]]></category>
		<category><![CDATA[HTML 5]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[jplayer]]></category>

		<guid isPermaLink="false">http://html5doctor.com/?p=4628</guid>
		<description><![CDATA[<p>Guest doctor Mark Boas returns with a follow up to his 2009 article <cite>Native Audio in the Browser</cite>, which covers the basics of HTML5 audio. Read the original if you want to get a feel for the <code>&#60;audio&#62;</code> element and associated API. If not, get comfortable and dive deep to learn about the current state of play for HTML5 audio.</p>]]></description>
			<content:encoded><![CDATA[<p>This is a follow up to my 2009 article <a href="http://html5doctor.com/native-audio-in-the-browser/"><cite>Native Audio in the Browser</cite></a>, which covers the basics of HTML5 audio. It may well be worth reading if you want to get a feel for the <code>&lt;audio&gt;</code> element and associated API.</p>
<p>Now, two and a half years later, it&#8217;s time to see how things are progressing. With many new advanced audio APIs being actively worked on and plenty of improvements to the existing native audio we all know and love, it&#8217;s certainly an exciting time to revisit the heady world of <code>&lt;audio&gt;</code>.</p>
<p>A good way of understanding how the land lies is by going through a few use cases. That&#8217;s what I&#8217;ll attempt to do in this post.</p>
<p>So how do we get started? Well, there are a few things we need to do to prepare the ground. Let&#8217;s tackle MIME types first.</p>
<section id="mime-types">
<h2>MIME Types <a href="#mime-types" class="permalink">#</a></h2>
<p>MIME types (also known as <a href="http://en.wikipedia.org/wiki/Internet_media_type">Internet Media Types</a>) are a way of defining file formats so that your system knows how to handle them.</p>
<section id="mime-types-server-side">
<h3>Server Side <a href="#mime-types-server-side" class="permalink">#</a></h3>
<p>First things first: your media server should be configured to serve correct MIME types. In the case of the Apache web server, this means adding the following lines to your <code>.htaccess</code> file:</p>
<aside class="sidenote">
<p><strong>Tip:</strong> Do not apply gzip compression to your media files on the server. Most formats are already compressed, and there&#8217;s limited support for those that aren&#8217;t. Further, in the case of a fallback solution, Flash does not support gzipped media.</p>
</aside>
<pre><code># AddType TYPE/SUBTYPE EXTENSION
AddType audio/mpeg mp3
AddType audio/mp4 m4a
AddType audio/ogg ogg
AddType audio/ogg oga
AddType audio/webm webma
AddType audio/wav wav</code></pre>
</section>
<section id="mime-types-client-side">
<h3>Client Side <a href="#mime-types-client-side" class="permalink">#</a></h3>
<p>When defining sources in your code or markup, you can also specify the MIME type, which will help the browser identify the media correctly.</p>
<p>To set up HTML5 audio in the most robust manner, you could write something like this:</p>
<pre><code>&lt;audio&gt;
   &lt;source src="elvis.mp3" type='audio/mpeg; codecs="mp3"'&gt;
   &lt;source src="elvis.oga" type='audio/ogg; codecs="vorbis"'&gt;
   &lt;!-- add your fallback solution here --&gt;
&lt;/audio&gt;</code></pre>
<p>Here we define the element and the sources to use. The browser will only pick one. It won&#8217;t play both. In this code, we also place a fallback solution after the &lt;<code>source</code>&gt; elements.</p>
<aside class="sidenote">
<p>Note that you can omit the codecs portion of the <code>type</code> attribute, but for robustness and efficiency, I recommend you supply the browser with as much media information as possible.</p>
</aside>
<p>Along with the source, we specify a <code>type</code> attribute. Although not strictly necessary, this attribute allows the browser to know the MIME type and the codecs of the supplied media before it downloads it. If not, supplied the browser will guess and take a trial-and-error approach to detecting the media type.</p>
<p>Cool. So now we know how to define our audio sources, and the browser will happily pick the first source that it supports. But what if we want to supply the correct source in a more dynamic manner?</p>
</section>
</section>
<section id="canPlayType">
<h2>Knowing in Advance: <code>canPlayType</code> Can Help, Probably <a href="#canPlayType" class="permalink">#</a></h2>
<p>Fortunately the audio API provides us with a way to find out whether a certain format is supported by the browser. But first, here&#8217;s a quick recap on how we manipulate the audio element via the API.</p>
<div class="callout highlight-block">
<p>If you mark up your element in HTML as we did in our previous example, you can grab the <code>&lt;audio&gt;</code> element by doing the following:</p>
<pre><code>var audio = document.getElementByTagName('audio')[index];

// or, if you gave it an id attribute
var audio = document.getElementById('my-audio-id');</code></pre>
<p>Alternatively, you can also create your element entirely in JavaScript:</p>
<pre><code>var audio = new Audio();</code></pre>
</p></div>
<p>Once you have your audio element, you&#8217;re ready to access its methods and properties. To test format support, you can use the <code>canPlayType</code> method, which takes a MIME type as a parameter:</p>
<pre><code>audio.canPlayType('audio/ogg');</code></pre>
<p>You can even explicitly include the codec:</p>
<pre><code>audio.canPlayType('audio/ogg; codecs="vorbis"');</code></pre>
<p><code>canPlayType</code> returns one of three values:</p>
<ol>
<li><code>probably</code>,</li>
<li><code>maybe</code>, or</li>
<li>&#8220;&#8221; (the empty string).</li>
</ol>
<aside class="sidenote">
<p>Previously, <code>canPlayType</code> returned &#8220;no&#8221; instead of the empty string. Worth knowing for use with early audio enabled browsers such as Firefox 3.5, Chrome 4, and Safari 4, although these make up a very small percentage of active browsers.</p>
</aside>
<p>The reason we have these odd return types is because of the general weirdness surrounding codecs. The browser can only guess at whether a certain codec is playable without actually trying to play it.</p>
<p>So to test for support, you could do this:</p>
<pre><code>var audio = new Audio();
  var canPlayOgg = !!audio.canPlayType &amp;&amp; audio.canPlayType('audio/ogg; codecs="vorbis"') != "";</code></pre>
<p>All we&#8217;re doing here is checking that <code>canPlayType</code> is supported (<code>!!</code> effectively casts to a boolean) and then checking that <code>canPlayType</code> of our chosen format doesn&#8217;t return an empty string.</p>
</section>
<section id="support">
<h2>Current Browser Codec Support <a href="#support" class="permalink">#</a></h2>
<p>Let&#8217;s check the codec support in the current crop of modern browsers.</p>
<table>
<caption>Desktop browser audio codec support</caption>
<thead>
<tr>
<th>Desktop Browser</th>
<th>Version</th>
<th>Codec Support</th>
</tr>
</thead>
<tbody>
<tr>
<td>Internet Explorer</td>
<td>9.0+</td>
<td>MP3, AAC</td>
</tr>
<tr>
<td>Chrome</td>
<td>6.0+</td>
<td>Ogg Vorbis, MP3, WAV†</td>
</tr>
<tr>
<td>Firefox</td>
<td>3.6+</td>
<td>Ogg Vorbis, WAV</td>
</tr>
<tr>
<td>Safari</td>
<td>5.0+</td>
<td>MP3, AAC, WAV</td>
</tr>
<tr>
<td>Opera</td>
<td>10.0+</td>
<td>Ogg Vorbis, WAV</td>
</tr>
</tbody>
</table>
<p>  <small>† WAV since Chrome 9</small></p>
<table>
<caption>Mobile browser audio codec support</caption>
<thead>
<tr>
<th>Mobile Browser</th>
<th>Version</th>
<th>Codec Support</th>
</tr>
</thead>
<tbody>
<tr>
<td>Opera Mobile</td>
<td>11.0+</td>
<td>Device-dependent</td>
</tr>
<tr>
<td>Android</td>
<td>2.3+</td>
<td>Device-dependent</td>
</tr>
<tr>
<td>Mobile Safari (iPhone, iPad, iPod Touch)</td>
<td>iOS 3.0+</td>
<td>MP3, AAC</td>
</tr>
<tr>
<td>Blackberry</td>
<td>6.0+</td>
<td>MP3, AAC</td>
</tr>
</tbody>
</table>
<aside class="sidenote">
<p><strong>Fun fact:</strong> Android 2.2 supports the <code>&lt;video&gt;</code> element but not its <code>&lt;audio&gt;</code> counterpart. In order to play audio, you need to use the video element.</p>
</aside>
<p>The good news is that at the time of writing, it&#8217;s estimated that around 80% of browsers now support HTML5 audio.</p>
<p>The bad news is that there is still no consensus on which codec to support, so you&#8217;ll need to provide both MP3 <em>and</em> Ogg Vorbis sources in order to take full advantage of HTML5 audio.</p>
<section id="containers">
<h2>Containers, Formats, and File Extensions (oh, and MIME types again) <a href="#containers" class="permalink">#</a></h2>
<p>Above, I&#8217;ve referred to the audio formats as they&#8217;re commonly known, but technically we should refer to their container format. (A container can contain more than one format — e.g., MP4 can contain AAC or AAC+.)</p>
<aside class="sidenote">
<p><strong>Tip:</strong> To check the codec support of your browser, you can visit <a href="http://jplayer.org/HTML5.Audio.Support/">the jPlayer audio support tester</a> or, more comprehensively (for audio and video), <a href="http://www.baccano.com/video/support.htm">baccano.com</a>.</p>
</aside>
<table>
<thead>
<tr>
<th>Container</th>
<th>Format(s)</th>
<th>File Extensions</th>
<th>MIME Type</th>
<th>Codec String</th>
</tr>
</thead>
<tbody>
<tr>
<td>MP3</td>
<td>MP3</td>
<td>.mp3</td>
<td>audio/mpeg</td>
<td>mp3</td>
</tr>
<tr>
<td>MP4</td>
<td>AAC, AAC+</td>
<td>.mp4, .m4a, .aac</td>
<td>audio/mp4</td>
<td>mp4a.40.5</td>
</tr>
<tr>
<td>OGA/OGG</td>
<td>Ogg Vorbis</td>
<td>.oga, .ogg</td>
<td>audio/ogg</td>
<td>vorbis</td>
</tr>
<tr>
<td>WAV</td>
<td>PCM</td>
<td>.wav</td>
<td>audio/wav</td>
<td>1</td>
</tr>
</tbody>
</table>
</section>
<section id="properties">
<h2>We have <code>&lt;audio&gt;</code> and we&#8217;re not afraid to use it! <a href="#properties" class="permalink">#</a></h2>
<p>Okay, we&#8217;ve done the minimum amount of work to get our audio element set up and playable. What else can we do? At the moment, we&#8217;re relying on the browsers&#8217; default audio players, each of which looks and works a little bit differently than the rest. Perhaps we&#8217;d like to customise the experience and create our own. To help us do that, the <code>&lt;audio&gt;</code> element supports several different properties exposing its current state.</p>
<p>Some of the more commonly used properties:</p>
<table>
<thead>
<tr>
<th>Property</th>
<th>Description</th>
<th>Return Value</th>
</tr>
</thead>
<tbody>
<tr>
<td>currentTime</td>
<td>playhead position</td>
<td>double (seconds)</td>
</tr>
<tr>
<td>duration</td>
<td>media duration</td>
<td>double (seconds); read-only</td>
</tr>
<tr>
<td>muted</td>
<td>is volume muted?</td>
<td>boolean</td>
</tr>
<tr>
<td>paused</td>
<td>is media paused?</td>
<td>boolean</td>
</tr>
<tr>
<td>volume</td>
<td>volume level</td>
<td>double (between 0 and 1)</td>
</tr>
</tbody>
</table>
<aside class="sidenote">
<p>You may need to check the <code>durationchange</code> event as some durations could change while media downloads. Also, depending on whether metadata is available, you might need to wait until the audio starts playing to check its duration. In short, keep an eye on the <code>durationchange</code> event, and watch out for <code>NaN</code> values when the duration isn&#8217;t yet known!</p>
</aside>
<p>Using these properties is pretty straightforward. For example:</p>
<pre><code>var audio = new Audio();
var duration = audio.duration;</code></pre>
<p>The variable <code>duration</code> now holds the duration (in seconds) of the audio clip.</p>
</section>
</section>
<section id="buffering-seeking-and-time-ranges">
<h2>Buffering, Seeking, and Time Ranges <a href="#buffering-seeking-and-time-ranges" class="permalink">#</a></h2>
<p>The situation is improving in this area, as browser makers start to implement key parts of the spec.</p>
<p>The API provides attributes called <code>buffered</code> and <code>seekable</code> that can be used in situations where we want to ascertain which part of the media has been buffered, preloaded, or is ready to be played without delay.</p>
<p>Let&#8217;s first take a look at the <code>buffered</code> and <code>seekable</code> attributes. Both return a <a href="http://www.w3.org/TR/html5/video.html#timeranges">TimeRanges</a> object. The <code>TimeRanges</code> object is a list of time periods containing start and end times that can be referenced by their indexes.</p>
<section id="buffered-attribute">
<h3>The <code>buffered</code> Attribute <a href="#buffered-attribute" class="permalink">#</a></h3>
<p>The <code>buffered</code> attribute will return the time ranges that have been completely downloaded. A little bit of a code:</p>
<pre><code>// returns TimeRanges object of buffered media
var buffered = audio.buffered;

// returns time in seconds of the last buffered TimeRange
var bufferedEnd = audio.buffered.end();</code></pre>
</section>
<section id="time-ranges">
<h3>The <code>TimeRanges</code> Object <a href="#time-ranges" class="permalink">#</a></h3>
<p>The <code>TimeRanges</code> object contains data on the parts on buffered media in the form of one or more — you guessed it — time ranges. A <code>TimeRanges</code> object consists of these properties:</p>
<ol>
<li><code>length</code> — number of time ranges</li>
<li><code>start(index)</code> — start time in seconds of a particular time range</li>
<li><code>end(index)</code> — end time in seconds of a particular time range</li>
</ol>
<aside class="sidenote" style="clear: left; margin-top: 0.5em">
<p><strong>Fun fact:</strong> The default unit of time used by the JavaScript Audio API is seconds, while many traditional JavaScript functions, such as <code>setInterval</code>, use milliseconds.</p>
</aside>
<p>You may be wondering in what situation the <code>TimeRanges</code> object would contain more than one time range. Imagine the user clicks forward to a portion of unbuffered media. The idea is that the media would then start buffering from that point, and you&#8217;d have two time ranges:</p>
<pre>------------------------------------------------------
|=============|                    |===========|     |
------------------------------------------------------
0             5                    15          19    21</pre>
<p>So in this case:</p>
<ul>
<li><code>audio.buffered.length</code> returns 2</li>
<li><code>audio.buffered.start(0)</code> returns 0</li>
<li><code>audio.buffered.end(0)</code> returns 5</li>
<li><code>audio.buffered.start(1)</code> returns 15</li>
<li><code>audio.buffered.end(1)</code> returns 19</li>
<li><code>audio.buffered.end()</code> returns 19</li>
</ul>
<aside class="sidenote">
<p><strong>Tip:</strong> Most audio-capable browsers enable seeking to new file positions during a download. To allow this, you must enable range requests on your server. Although enabled by default on web servers such as Apache, you can verify by checking that your server responds with the <code>Accept-Ranges</code> header.</p>
</aside>
<p>Note that if the user is actively seeking through the media throughout the buffering process, a contiguous buffered progress bar actually makes little sense. Also consider that some browsers will read part of the end of the file to establish duration and so create two time ranges almost immediately. Now you&#8217;re starting to appreciate why making an accurate buffered progress bar is a little tricky!</p>
<p>You can check out <code>TimeRanges</code> in real-time using this handy <a href="http://jplayer.org/HTML5.Media.Event.Inspector/">HTML5 Media Event Inspector</a>.</p>
</section>
<section id="seeking-and-seekable">
<h3>Seeking and Seekable <a href="#seeking-and-seekable" class="permalink">#</a></h3>
<p>Seeking is the act of looking forward (or backward) in a media file. This usually happens when a section of media is requested before it&#8217;s finished loading.</p>
<p>The <code>seeking</code> attribute can be used to determine whether that part of the media is being actively &#8220;seeked&#8221;. When it returns true, the portion of the media the user requested is still being loaded.</p>
<aside class="sidenote">
<p><strong>Fun fact:</strong> All modern browsers, apart from Safari on Windows, enable the <code>seekable</code> attribute, which means the <code>seeking</code> event never seems to fire as the user can jump directly to the requested part. The <code>seeked</code> event does fire though, which annoys some people who think that <code>seeking</code> should always fire before <code>seeked</code>.</p>
</aside>
<p>To recap a little, the <code>buffered</code> property tells us what&#8217;s been downloaded and is often used as an indication of what part of the media can be directly played. If the browser supports it, however, it may make more sense to use the <code>seekable</code> attribute to determine which parts of the media can be jumped to and played immediately.</p>
<p><code>seekable</code> returns a <code>TimeRanges</code> object of time ranges that can be played immediately. This uses a technology known as byte-range requests, which allows part of the content to be requested over HTTP. In short, we don&#8217;t have to load all the data prior to the desired part in order to play it.</p>
<p>An example:</p>
<pre><code>// Is the player currently seeking?
var isSeeking = audio.seeking;

// Is the media seekable?
var isSeekable = audio.seekable &amp;&amp; audio.seekable.length &gt; 0;

// Time in seconds within which the media is seekable.
var seekableEnd = audio.seekable.end();</code></pre>
<div class="callout highlight-block">
<p>Time ranges can be confusing. <code>audio.seekable.end()</code> actually tells us the end point of the last time range (not the end point of all seekable media). In practice, though, this is good enough, as the browser either enables range requests or doesn&#8217;t. If it doesn&#8217;t, then <code>audio.seekable</code> will be equivalent to <code>audio.buffered</code>, which will give a valid indication of the end of seekable media.</p>
</p></div>
<p>Note that media being in a &#8220;seekable&#8221; state is different than media being in a &#8220;buffered&#8221; state. Media doesn&#8217;t have to be buffered to be seekable.</p>
<aside class="sidenote">
<p><strong>Fun fact:</strong> In practice only one seekable TimeRange object is created. Where browsers support range requests the TimeRange object spans zero to the media duration, where they don&#8217;t, the TimeRange object starts at zero and its end grows as the media downloads.</p>
</aside>
<p>Buffered and seekable data can be useful information, but it would be too easy if there weren&#8217;t a few gotchas.</p>
<ol>
<li>Preloading is not supported in all older audio-capable browsers (Opera 10/Firefox 3.6).</li>
<li>The <code>buffered</code> attribute is not always supported (Blackberry PlayBook).</li>
<li>Not all HTML5 browsers allow byte-range seeking — for example, Safari on Windows. In this case, you can still seek within the downloaded content. It downloads from the start until the end, as does Flash.</li>
</ol>
<p>If you want to deliver the best possible solution to your users, you&#8217;ll need to feature test.</p>
</section>
<section id="preloading">
<h3>A Note about Preloading <a href="#preloading" class="permalink">#</a></h3>
<p>I mentioned the <code>preload</code> attribute in the previous article. This attribute accepts three possible values:</p>
<ol>
<li><code>none</code> — Do not preload any media. Wait for a play event before downloading anything.</li>
<li><code>metadata</code> — Preload just the metadata. Grab the start and the end of the file via range-request and determine the duration.</li>
<li><code>auto</code> — Preload the whole file. Grab the start and the end of the file to determine duration, then seek back to the start again for the preload proper.</li>
</ol>
<aside class="sidenote">
<p><strong>Fun fact:</strong> Mobile Safari ignores the <code>preload</code> attribute, effectively always using <code>preload="none"</code>.</p>
</aside>
<p>When it comes to preloading, remember that it&#8217;s a request or hint to tell the browser how you&#8217;d like to preload the media. The browser is not under any obligation to fulfill that request. For this reason, certain browsers may handle these requests differently.</p>
</section>
</section>
<section id="played">
<h2>Well-Played <a href="#played" class="permalink">#</a></h2>
<aside class="sidenote">
<p><strong>Tip:</strong> If you loop through <code>audio.played</code>, sum the time ranges between starts and ends, and then compare it with the duration, you can determine the percentage of the audio that the user has listened to. This may be a useful metric.</p>
</aside>
<p>It&#8217;s worth mentioning the <code>played</code> property in passing. This property tells us which time ranges have been played within the media. For example:</p>
<pre><code>// returns a TimeRanges object
var played = audio.played;</code></pre>
</section>
<section id="events">
<h2>Media Events <a href="#events" class="permalink">#</a></h2>
<p>Underpinning both the native audio and video APIs is a comprehensive set of events. A full list can be found at the <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#mediaevents">WhatWG version of the spec</a>.</p>
<p>Attaching handlers to media events allows you to easily react to changes in state. For example, it might be useful to update the time info in a custom-built player each time the <code>timeupdate</code> event occurs.</p>
<p>A quick summary of the more commonly used media events:</p>
<table>
<thead>
<tr>
<th>Event</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>durationchange</td>
<td>The <code>duration</code> attribute has been updated.</td>
</tr>
<tr>
<td>ended</td>
<td>Playback has stopped as the end of the media was reached.</td>
</tr>
<tr>
<td>pause</td>
<td>The media playback has been paused. Note there is no <code>stop</code> event.</td>
</tr>
<tr>
<td>play</td>
<td>The media has started playing.</td>
</tr>
<tr>
<td>timeupdate</td>
<td>The current playback position changed (usually every 250ms).</td>
</tr>
<tr>
<td>volumechange</td>
<td>The volume changed.</td>
</tr>
</tbody>
</table>
<aside class="sidenote">
<p><strong>Tip:</strong> Android (at least 2.3) does not always fire the <code>ended</code> event. Well, it sometimes throws one out for good measure, but generally you need to create your own by capturing the <code>pause</code> event that is fired upon reaching the end of the media and comparing <code>audio.currentTime</code> with <code>audio.duration</code>. Alternatively, you can listen for the <code>pause</code> event and check that <code>audio.currentTime</code> is zero. To be absolutely certain, use a combination of both techniques.</p>
</aside>
<p>Other useful events:</p>
<table>
<thead>
<tr>
<th>Event</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>canplay</td>
<td>The media can be played but may need to pause while the file is downloaded.</td>
</tr>
<tr>
<td>canplaythrough</td>
<td>At current download rates, it is estimated that the media can be played from start to finish without pause.</td>
</tr>
<tr>
<td>progress</td>
<td>The browser is fetching the media data (usually every 250ms).</td>
</tr>
</tbody>
</table>
<p>Again, the <a href="http://jplayer.org/HTML5.Media.Event.Inspector/">HTML5 Media Event Inspector</a> is your friend.</p>
<p>Additionally, you can test browser support by using <a href="http://areweplayingyet.org/">areweplayingyet.org</a>. It&#8217;s worth checking out the code behind the tests to understand the goings-on under the hood.</p>
</section>
<section id="streaming">
<h2>Streaming <a href="#streaming" class="permalink">#</a></h2>
<p>Streaming audio is a common requirement. This is an area that until recently has been dominated by Adobe&#8217;s Flash technology. Proprietary server technologies and protocols are well-established. One of the leading examples of this is Adobe&#8217;s <a href="http://en.wikipedia.org/wiki/Real_Time_Messaging_Protocol">Real Time Messaging Protocol</a> (RTMP). However, current browsers only support streaming over HTTP, and so something like Flash is required to process RTMP streams.</p>
<p>Currently, audio-enabled browsers only support <a href="http://en.wikipedia.org/wiki/SHOUTcast">SHOUTcast</a> and <a href="http://en.wikipedia.org/wiki/Icecast">Icecast</a> servers that stream audio over HTTP. SHOUTcast is propriety and allows streaming of MP3 and AAC files only, while Icecast is non-propriety and supports Ogg Vorbis as well as MP3 and AAC.</p>
<table>
<thead>
<tr>
<th>Stream</th>
<th>AAC</th>
<th>MP3</th>
<th>Ogg Vorbis</th>
<th>Native Support</th>
</tr>
</thead>
<tbody>
<tr>
<td>Icecast</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr>
<td>SHOUTCast</td>
<td>Yes</td>
<td>Yes</td>
<td>No</td>
<td>Yes</td>
</tr>
<tr>
<td>RTMP</td>
<td>Yes</td>
<td>Yes</td>
<td>No</td>
<td>No (requires Flash)</td>
</tr>
</thead>
</table>
</section>
<section id="spec">
<h2>An Evolving Spec (Or, &#8220;Whoa, this thing is moving!&#8221;) <a href="#spec" class="permalink">#</a></h2>
<p>As the audio spec is still evolving, there are a couple of inconsistencies in browser implementations to watch out for. These generally affect older browsers.</p>
<section id="load">
<h3>The <code>load</code> Method <a href="#load" class="permalink">#</a></h3>
<p>Until fairly recently, the <code>load</code> method was required in order to tell the browser about a change in the media source and to get it to update appropriately. Now, <code>media.load()</code> causes the element to reset and to start selecting and loading a new media resource from scratch.</p>
<p>So for older browsers, such as Firefox 3.6, in order to change the media source, you&#8217;ll not only need to change the source value but also issue a load command:</p>
<pre><code>var audio = new Audio();
audio.setAttribute("src","mynew.mp3");
audio.load(); // required for 'older' browsers</code></pre>
</section>
<section id="hacks">
<h3>When Browsers Go Off-Spec <a href="#hacks" class="permalink">#</a></h3>
<p>When creating cross-browser solutions, it&#8217;s useful to know which browsers follow <a href="http://dev.w3.org/html5/spec/video.html#audio">the W3C spec</a> to what extent and how they deviate.</p>
<section id="autoplay-and-volume">
<h4>Autoplay and Volume <a href="#autoplay-and-volume" class="permalink">#</a></h4>
<p>iOS and Blackberry devices ignore the <code>autoplay</code> attribute and media element volume changes, whereas Android supports <code>autoplay</code> but not volume changes.</p>
<p>Effectively, on Blackberry and iOS devices, <code>autoplay</code> functionality is disabled as both require a user-initiated event to &#8220;kick it off&#8221;. This has the unfortunate side-effect that any audio suffers a delay between user interaction and playback.</p>
<p>To mitigate against these issues, you may want to take a look at <a href="http://remysharp.com/2010/12/23/audio-sprites/">Doctor Remy Sharp&#8217;s excellent article on Audio Sprites and fixes for iOS</a>.</p>
</section>
<section id="multiaudio">
<h4>Simultaneous Playback of Multiple Audio Elements <a href="#multiaudio" class="permalink">#</a></h4>
<p>A particular annoyance for developers of anything but the most simple audio web apps: not all browsers will play multiple audio elements simultaneously. This is a particular problem for games developers. Again, we see this issue with iOS and Blackberry devices.</p>
</section>
<section id="oses">
<h4>Operating System Dependence <a href="#oses" class="permalink">#</a></h4>
<aside class="sidenote">
<p>Although of limited use to developers, you could install other codecs such as Ogg Vorbis on the underlying operating system, and browsers that use OS codecs should be able to play them back.</p>
</aside>
<p><a href="http://happyworm.com/blog/2010/08/17/safari-requires-quicktime-for-html5-based-media/">Safari (5+) relies on Quicktime being installed.</a> This is rarely a problem unless you are running it on Windows.</p>
<p>Internet Explorer (9+) relies on the codecs being present at the operating system level. As it only runs on Windows, this is fortunately almost always the case.</p>
</section>
</section>
</section>
<section id="whats-new">
<h2>What&#8217;s New? <a href="#whats-new" class="permalink">#</a></h2>
<p>There are a few new features and whole new APIs being specified for web-based audio, so let&#8217;s take a look at what&#8217;s around the corner.</p>
<section id="playback-rate">
<h3>A Change of Pace <a href="#playback-rate" class="permalink">#</a></h3>
<p>A couple of noteworthy upcoming features are <code>playbackRate</code> and <code>defaultPlaybackRate</code>. As you can probably imagine, these fellas let us alter the speed and direction of playback. This functionality could be used for fast-forward and rewind functions or perhaps to allow users to tweak the playback speed so they can fit more podcasts into their day.</p>
<ul>
<li><code>audio.playbackRate</code> returns 1 at normal speed and acts as a multiple that is applied to the rate of playback. For example, setting <code>playbackRate</code> to 2 would double the speed, while setting it to -1 would play the media backwards.</li>
<li><code>audio.defaultPlaybackRate</code> is the rate at which the audio will play after you pause and restart the media (or issue any event for that matter).</code></li>
</ul>
</section>
<section id="media-fragments">
<h3>Media Fragments <a href="#media-fragments" class="permalink">#</a></h3>
<p>Currently, if we wish to reference some part of a media file, we often first have to download at least some of the media we don't actually need. <a href="http://www.w3.org/TR/media-frags/">The W3C Media Fragments proposal</a> was created to address this issue <a href="http://www.w3.org/TR/2009/WD-media-frags-reqs-20091217/">and others</a>, such as the retrieval of an area of video or just the associated text track. In the case of audio, it will allow us to specify which parts we want to download using parameters on the source URI.</p>
</section>
</section>
<section id="advanced-apis">
<h2>Advanced Audio APIs: The Future Sound of Browsers <a href="#advanced-apis" class="permalink">#</a></h2>
<p>When it comes to more advanced audio functionality, Mozilla was first to enter the fray with <a href="https://wiki.mozilla.org/Audio_Data_API">an early experimental Audio Data API for Firefox</a>. This was intended to facilitate audio manipulation via JavaScript and created a platform for low-level tinkering.</p>
<p>Not to be outdone, Google released <a href="https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html">the Web Audio API for Chrome</a> and put it forward as a W3C proposal. The Web Audio API is a higher-level implementation that takes an audio-node based approach and provides many useful functions.</p>
<p>Both implementations address the desire by developers to do more with audio — to create, manipulate, analyse, and mix audio on the fly. In effect, we may one day be able to do in a browser anything we can currently do with native applications.</p>
<p>So what if we want to play with advanced audio in the browser? Well, two separate implementations currently exist. If you want to write applications that use both APIs in any reasonable way, you need third-party bridging libraries to abstract away the differences.</p>
<p>Also fairly new on the scene is <a href="http://www.w3.org/TR/2011/WD-streamproc-20111215/">Mozilla's MediaStream Processing API</a>, which takes another approach to audio and video streams to allow us to manipulate at both high and low levels.</p>
<p>In fact, using advanced APIs and taking advantage of the speed of modern JavaScript engines, we can even write decoders for unsupported codecs. Currently, we have <a href="http://codecs.ofmlabs.org/">the JSMad MP3 decoder and the lossless Alac.js decoder</a>. Apparently, FLAC and AAC are in the pipeline. There is hope, then, that in the future, we may not have to worry about which browsers are supporting which formats.</p>
<p>For those curious about advanced web audio, I wrote about the differences in approaches and the different libraries that allow us to write cross-browser solutions in <a href="http://happyworm.com/blog/2011/11/15/html5-audio-apis-how-low-can-we-go/"><cite>HTML5 Audio APIs: How Low can we Go?</cite></a></p>
<p>The good news is that all relevant parties are talking, and things seem to be buzzing on <a href="http://www.w3.org/2011/audio/">the W3C Audio Working Group</a>. It looks like everyone is coming together to put their ideas into <a href="http://www.w3.org/TR/audioproc/">a unified Audio Processing API</a>, which is rapidly approaching publication as a Web Standard.</p>
</section>
<section id="summary">
<h2>Summary <a href="#summary" class="permalink">#</a></h2>
<p>Although browser implementations of the current HTML5 audio spec are improving, there are still a few issues to watch out for when creating comprehensive cross-browser solutions. You certainly need to be aware of browser limitations on platforms like iOS. Hopefully, as support matures, these issues will disappear.</p>
<p>Positive news on the "advanced audio" front too: <a href="http://www.w3.org/TR/audioproc/">a new standard is being established</a>, and we're close to get a unified spec for browser makers to work from. In the meantime, JavaScript libraries are available to help bridge the gaps between existing implementations.</p>
<p>There are also signs that we may be seeing the end of the requirement for different browser-dependent codecs. Opera Mobile already supports MP3 where the underlying OS supports it, and <a href="http://groups.google.com/group/mozilla.dev.platform/browse_thread/thread/fb14de8b9ad84e15/4cfccdde2cb064d1?#4cfccdde2cb064d1">Mozilla look like they may enable this too</a>. If this option exists for mobile browsers, it's not a huge stretch to imagine that desktop browsers will follow suit.</p>
<p>So lots happening and lots already achieved. The rough edges of existing browser implementations are being smoothed, consensus and standards are being forged, and we can see the foundations of some very exciting new technologies being established.</p>
<p>The future of web-based audio looks bright!</p>
</section>
<section id="links">
<h2>Further Reading <a href="#links" class="permalink">#</a></h2>
<ul>
<li><a href="http://24ways.org/2010/the-state-of-html5-audio">"Probably, Maybe, No": The State of HTML5 Audio</a></li>
<li><a href="http://www.phoboslab.org/log/2011/03/the-state-of-html5-audio">The State of HTML5 Audio</a></li>
<li><a href="http://www.catswhocode.com/blog/mastering-the-html5-audio-property">Mastering the HTML5 &lt;audio&gt; tag</a></li>
<li><a href="http://blogs.msdn.com/b/ie/archive/2011/05/13/unlocking-the-power-of-html5-lt-audio-gt.aspx">Unlocking the power of HTML5 &lt;audio&gt;</a></li>
<li><a href="http://my.opera.com/core/blog/2010/03/03/everything-you-need-to-know-about-html5-video-and-audio-2">Everything you need to know about HTML5 video and audio</a></li>
</ul>
</section>
<div id="crp_related">
<h3>Related Posts:</h3>
<ul class="related">
<li><a href="http://html5doctor.com/native-audio-in-the-browser/" rel="bookmark" class="crp_title">Native Audio in the browser</a></li>
<li><a href="http://html5doctor.com/video-the-track-element-and-webm-codec/" rel="bookmark" class="crp_title">Video: the track element and webM codec</a></li>
<li><a href="http://html5doctor.com/the-video-element/" rel="bookmark" class="crp_title">The video element</a></li>
<li><a href="http://html5doctor.com/video-subtitling-and-webvtt/" rel="bookmark" class="crp_title">Video Subtitling and WebVTT</a></li>
<li><a href="http://html5doctor.com/getusermedia/" rel="bookmark" class="crp_title">It&#8217;s Curtains for Marital Strife Thanks to getUserMedia</a></li>
</ul>
</div>
<p><a href="http://html5doctor.com/html5-audio-the-state-of-play/" rel="bookmark">HTML5 Audio — The State of Play</a> originally appeared on <a href="http://html5doctor.com">HTML5 Doctor</a> on May 8, 2012.</p>
]]></content:encoded>
			<wfw:commentRss>http://html5doctor.com/html5-audio-the-state-of-play/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Let&#8217;s Talk about Semantics</title>
		<link>http://html5doctor.com/lets-talk-about-semantics/</link>
		<comments>http://html5doctor.com/lets-talk-about-semantics/#comments</comments>
		<pubDate>Wed, 18 Apr 2012 16:51:41 +0000</pubDate>
		<dc:creator>Mike Robinson</dc:creator>
				<category><![CDATA[Elements]]></category>

		<guid isPermaLink="false">http://html5doctor.com/?p=4440</guid>
		<description><![CDATA[It's time we had "the talk". I could get you a book or recommend some sites from Dr Mike's special bookmarks folder, but the best way to make sure you get the right idea is to do it myself. I'm talking about HTML semantics. Understanding the thinking behind the naming of elements will help your markup shine.]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s time we had &#8220;the talk&#8221;. I could get you a book or recommend some sites from Dr Mike&#8217;s special bookmarks folder, but the best way to make sure you get the right idea is to do it myself. I&#8217;m talking about HTML semantics. Understanding the thinking behind the naming of elements will help your markup shine.</p>
<section id="semantics-and-the-web">
<h2>Semantics and the Web <a class="permalink" href="#semantics-and-the-web">#</a></h2>
<p>Semantics are the implied meaning of a subject, like a word or sentence. It aids how humans (and these days, machines) interpret subject matter. On the web, HTML serves both humans and machines, suggesting the purpose of the content enclosed within an HTML tag. Since the dawn of HTML, elements have been revised and adapted based on actual usage on the web, ideally so that authors can navigate markup with ease and create carefully structured documents, and so that machines can infer the context of the wonderful collection of data we humans can read.</p>
<p>Until — and perhaps even after — machines can understand language and all its nuances at the same level as a human, we need HTML to help machines understand what we mean. A computer doesn&#8217;t care if you had pizza for dinner. It likely just wants to know what on earth it should do with that information.</p>
<p>HTML semantics are a nuanced subject, widely debated and easily open to interpretation. Not everyone agrees on the same thing right away, and this is where problems arise.</p>
</section>
<section id="whats-the-point">
<h2>What&#8217;s the point? <a class="permalink" href="#whats-the-point">#</a></h2>
<p>Discussions over the importance of semantics are happening all the time, and every so often there&#8217;s an uproar over specific articles on the subject. <a href="http://twitter.com/divya">Divya Manian</a> caused a stir in her Smashing Magazine article <cite><a href="http://coding.smashingmagazine.com/2011/11/11/our-pointless-pursuit-of-semantic-value/">Our Pointless Pursuit Of Semantic Value</a></cite> in <time datetime="2011-11-11">November 2011</time>, in which she argued we have become too caught up in trying to use HTML5&#8242;s semantics, and that the benefits aren&#8217;t worth it:</p>
<blockquote>
<p>Allow me to paint a picture:</p>
<ol>
<li>You are busy creating a website.</li>
<li>You have a thought, &#8220;Oh, now I have to add an element.&#8221;</li>
<li>Then another thought, &#8220;I feel so guilty adding a <code>div</code>. Div-itis is terrible, I hear.&#8221;</li>
<li>Then, &#8220;I should use something else. The <code>aside</code> element might be appropriate.&#8221;</li>
<li>Three searches and five articles later, you&#8217;re fairly confident that <code>aside</code> is not semantically correct.</li>
<li>You decide on <code>article</code>, because at least it&#8217;s not a <code>div</code>.</li>
<li>You&#8217;ve wasted 40 minutes, with no tangible benefit to show for it.</li>
</ol>
<footer>— <cite><a href="http://coding.smashingmagazine.com/2011/11/11/our-pointless-pursuit-of-semantic-value/" title="Our Pointless Pursuit Of Semantic Value">Divya Manian</a></cite></footer>
</blockquote>
<p>This generated a storm of responses, both positive and negative. In <cite><a href="http://adactio.com/journal/4999/">Pursuing Semantic Value</a></cite> <a href="http://twitter.com/adactio">Jeremy Keith</a> argued that being semantically correct is not fruitless, and he even gave an example of how <code>&lt;section&gt;</code> can be used to adjust a document&#8217;s outline. He concludes:</p>
<blockquote>
<p>But if you can get past the blustery tone and get to the kernel of the article, it’s a fairly straightforward message: don’t get too hung up on semantics to the detriment of other important facets of web development.</p>
<footer>— <cite><a href="http://adactio.com/journal/4999/" title="Pursuing semantic value">Jeremy Keith</a></cite></footer>
</blockquote>
<p>I&#8217;ll admit I&#8217;ve been in a situation where I&#8217;ve dug myself a mind hole, trying to decide which element is &#8220;correct&#8221; and then depressing myself with thoughts of how irrelevant it all seems. What gives me strength is the thought that I&#8217;m not marking this up for me, but for everyone who can benefit from the enhanced meaning. Whether it&#8217;s the browser, a search engine spider, an accessibility tool, the person you pass the project on to, or even future you returning to the project in six months time, the markup indicates how the content should be interpreted. As long as your markup makes sense and isn&#8217;t over the top (e.g., if you just <a href="http://html5doctor.com/avoiding-common-html5-mistakes/#section-wrapper">replace all your HTML 4 <code>&lt;div&gt;</code>s with <code>&lt;section&gt;</code>s</a>, you may be misunderstanding the element or even your content), then don&#8217;t worry so much about it all.</p>
<p>To help you choose the most appropriate element, we released a <a href="http://html5doctor.com/resources/#flowchart">flowchart of HTML5 sectioning elements</a> that you can print off and follow whenever you get stuck. If all else fails, don&#8217;t forget about your old buddy <a href="http://html5doctor.com/you-can-still-use-div/"><code>&lt;div&gt;</code></a>. Then again, maybe you&#8217;ve stumbled across a need for something new&hellip;</p>
<p>  <a href="http://html5doctor.com/resources/#flowchart"><img src="http://html5doctor.com/downloads/h5d-sectioning-flowchart.sml.png" alt="flowchart of HTML5 sectioning elements"></a><br />
</section>
<section id="naming-things">
<h2>Naming Things <a class="permalink" href="#naming-things">#</a></h2>
<p>Of all the possible new element names in HTML5, the spec is pretty set on things like <code>&lt;nav&gt;</code> and <code>&lt;footer&gt;</code>. If you&#8217;ve used either of those as a <code>class</code> or <code>id</code> in your own markup, it&#8217;s no coincidence. Studies of the web from the likes of <a href="http://code.google.com/webstats/">Google</a> and <a href="http://dev.opera.com/articles/view/mama-markup-report-part-2/">Opera</a> (amongst others) looked at which names people were using to hint at the purpose of a part of their HTML documents. The authors of the HTML5 spec recognised that developers needed more semantic elements and looked at what classes and IDs were already being used to convey such meaning.</p>
<p>Of course, it isn&#8217;t possible to use all of the names researched, and of the millions of words in the English language that could have been used, it&#8217;s better to focus on a small subset that meets the demands of the web. Yet some people feel that the spec isn&#8217;t yet doing so.</p>
<section id="what-about-adding-more-elements">
<h3>What about adding more elements? <a class="permalink" href="#what-about-adding-more-elements">#</a></h3>
<figure>
      <img src="http://html5doctor.com/wp-content/uploads/2012/02/why_not_zoidberg.jpg" alt="The character Dr Zoidberg from the TV animation Futurama, with the caption: &lt;article&gt;? Why not &lt;zoidberg&gt;?"><br />
    </figure>
<p>When I first met fellow HTML5 Doctor <a href="http://twitter.com/brucel">Bruce Lawson</a>, I asked him this question: <q>If we have elements like <code>&lt;article&gt;</code>, why don&#8217;t we have one for products of a shop?</q> I understand more about HTML now than I did then, but at the time it seemed like a very logical element to add. Why restrict ourselves to documents with <code>&lt;article&gt;</code>s when the web has evolved beyond that with shops, applications, and games? I&#8217;m sure many of you have felt the same way. Some have even put cases to the WHATWG suggesting more elements like the often requested <code>&lt;comment&gt;</code>.</p>
<p>Recently, editor of the HTML5 spec <a href="http://www.hixie.ch/">Ian Hickson</a> wrote responses to some of these <a href="http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2012-January/034506.html">requests for new elements for comments</a>, explaining why <code>&lt;article&gt;</code> within <code>&lt;article&gt;</code> suffices for marking up comments:</p>
<blockquote>
<p><code>&lt;article&gt;</code> isn&#8217;t just for articles. That&#8217;s the point.</p>
<p>Note that its name is irrelevant here. It could be called <code>&lt;pineapple&gt;</code> — what matters is what it is defined to mean, not what its name is. And its definition is one that covers both articles and comments. They are both self-contained compositions.</p>
<footer>— <cite><a href="http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2012-January/034506.html" title="Requests for new elements for comments">Ian Hickson</a></cite></footer>
</blockquote>
<p>As much as <a href="https://twitter.com/akamike/status/162466809432379392">I am all for the much needed addition of <code>&lt;pineapple&gt;</code></a>, Ian makes a good case for why we don&#8217;t need <code>&lt;comment&gt;</code> (or similar). Dr Bruce often uses the following analogy when trying to explain <code>&lt;article&gt;</code>:</p>
<blockquote>
<p>Don&#8217;t think of <code>&lt;article&gt;</code> as a magazine article. Think of it as an article of clothing, an independent entity that can be arranged in conjunction with other articles of clothing, but is a complete thing in itself.</p>
</blockquote>
<p>I hear you ask, <q>That&#8217;s all well and good, Mike, but what does understanding <code>&lt;article&gt;</code> have to do with adding new elements?</q> To add something to the spec, you need to:</p>
<ol>
<li>document actual use cases,</li>
<li>show how developers are working around the lack of this feature now, and</li>
<li>make a compelling case for why HTML5 needs it.</li>
</ol>
<p>Step one is to make sure what you&#8217;re asking for can&#8217;t be achieved with what already exists. This is exactly the problem with the proposals for <code>&lt;comment&gt;</code>. Any difference from <code>&lt;article&gt;</code> is so minimal that it isn&#8217;t worth adding.</p>
<aside class="sidenote">
<p>The WHATWG has a <a href="http://www.whatwg.org/mailing-list#specs">mailing list for providing feedback</a> on the spec. To get involved, you need to subscribe, and I recommend checking the <a href="http://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/">archives</a> for previous proposals to see if your idea has already been adressed. Not satisfied? Send an email to the list with test cases and evidence as to why your proposal is worth considering.</p>
</aside>
<p>If every proposal for a minor deviation of an existing element was accepted, the spec would be bloated with far more elements than necessary. User agents would have to keep up with the vast array of markup possibilities for a given bit of content — as would you, the author. And think about this: at the end of the day, what are you actually going to use that new element for? <em>Really?</em></p>
<p>That&#8217;s not to say you should be discouraged from putting your ideas forward. Take it as advice on what to look for when you want to contribute something to the spec. It may even help you to think differently about your work. Some problems just need a fresh perspective to help solve them.</p>
</section>
</section>
<section id="stop-worrying">
<h2>HTML5 Doctor, or: How I Learned to Stop Worrying and Love HTML <a class="permalink" href="#stop-worrying">#</a></h2>
<p>Once you learn to look past element names and think of their essential meaning, it gets a bit easier to write markup. Think of your chunks of content in terms of how they relate to each other and in which contexts they can be used. In our <a href="http://html5doctor.com/article-archive/">article archive</a>, we&#8217;ve covered a lot of elements with examples of their use. If you&#8217;re ever in doubt, I highly recommend our <a href="http://html5doctor.com/resources/#flowchart">flowchart of HTML5 sectioning elements</a> to help you along.</p>
<p>Try to keep things simple. Overthinking your markup will only cause more problems than it&#8217;s worth. And let&#8217;s face it: it&#8217;s not like you can&#8217;t change it later!</p>
<p>You may also be interested in adopting <a href="http://microformats.org/">Microformats</a>, something Dr <a href="http://twitter.com/boblet">Oli Studholme</a> has written about here on HTML5 Doctor. <cite><a href="http://html5doctor.com/microformats/">Extending HTML5 — Microformats</a></cite> is recommended reading for those who want to take their markup a bit further. Dr Oli has also looked at <cite><a href="http://html5doctor.com/microdata/">Extending HTML5 with Microdata</a></cite>, which <q cite="http://html5doctor.com/microdata/">gives us a whole new way to add extra semantic information</q>.</p>
<p>Finally, try utilising HTML5 markup in ways that gain the benefit of these new elements. Create tools, use your own documents to test how well-formed and structured they are, and test how portable your content really is. Who knows, you may even find yourself writing a proposal for the next addition to the spec.</p>
<p>Do you know something the web needs that&#8217;s missing from HTML5? Let us know in the comments.</p>
</section>
<div id="crp_related">
<h3>Related Posts:</h3>
<ul class="related">
<li><a href="http://html5doctor.com/time-and-data-element/" rel="bookmark" class="crp_title">Goodbye time, datetime, and pubdate. Hello data and value.</a></li>
<li><a href="http://html5doctor.com/happy-1st-birthday-us/" rel="bookmark" class="crp_title">Happy 1st Birthday us</a></li>
<li><a href="http://html5doctor.com/blockquote-q-cite/" rel="bookmark" class="crp_title">Quoting and citing with <code>&lt;blockquote&gt;</code>, <code>&lt;q&gt;</code>, <code>&lt;cite&gt;</code>, and the cite attribute</a></li>
<li><a href="http://html5doctor.com/your-questions-18/" rel="bookmark" class="crp_title">Your Questions 18</a></li>
<li><a href="http://html5doctor.com/outlines/" rel="bookmark" class="crp_title">Document Outlines</a></li>
</ul>
</div>
<p><a href="http://html5doctor.com/lets-talk-about-semantics/" rel="bookmark">Let&#8217;s Talk about Semantics</a> originally appeared on <a href="http://html5doctor.com">HTML5 Doctor</a> on April 18, 2012.</p>
]]></content:encoded>
			<wfw:commentRss>http://html5doctor.com/lets-talk-about-semantics/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Drag and Drop and Automatically Send to the Server</title>
		<link>http://html5doctor.com/drag-and-drop-to-server/</link>
		<comments>http://html5doctor.com/drag-and-drop-to-server/#comments</comments>
		<pubDate>Tue, 03 Apr 2012 13:30:17 +0000</pubDate>
		<dc:creator>Remy Sharp</dc:creator>
				<category><![CDATA[Events]]></category>
		<category><![CDATA[forms]]></category>
		<category><![CDATA[JavaScript APIs]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[drag and drop]]></category>
		<category><![CDATA[file]]></category>
		<category><![CDATA[filereader]]></category>
		<category><![CDATA[HTML 5]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[meter]]></category>
		<category><![CDATA[xhr2]]></category>

		<guid isPermaLink="false">http://html5doctor.com/?p=4500</guid>
		<description><![CDATA[<p>I realised (when looking myself) that there are a lot of demos and tutorials that show you how to drag-and-drop a file into the browser and then render it on the page. They're often labelled as "drag-and-drop and upload", but they actually <em>don't upload</em>. This tutorial will take you that final step.</p>]]></description>
			<content:encoded><![CDATA[<p>I realised (when looking myself) that there are a lot of demos and tutorials that show you how to drag-and-drop a file into the browser and then render it on the page. They're often labelled as "drag-and-drop and upload", but they actually <em>don't upload</em>. This tutorial will take you that final step.</p>

<p>I'll walk you through <a href="http://html5demos.com/dnd-upload">an example that you can play with</a>: drag a file into the web page, and it'll be uploaded to the server instantly.</p>

<section id="tasks">
  <h2>Tasks <a href="#tasks" class="permalink">#</a></h2>

  <p>Let's break this process down into specific tasks:</p>

  <ol>
    <li>Capture the drop event and read its data.</li>
    <li>Post that binary data to the server.</li>
    <li>Provide feedback on the progress of the upload.</li>
    <li>Optionally render a preview of what's being uploaded and its status.</li>
  </ol>

  <p>To achieve all of this, we need the following HTML5 and non-HTML5 APIs:</p>

  <ol>
    <li><a href="http://www.w3.org/TR/html5/dnd.html">Drag and Drop</a></li>
    <li><a href="http://www.w3.org/TR/2010/WD-XMLHttpRequest2-20100907/#the-formdata-interface">FormData</a></li>
    <li><a href="http://www.w3.org/TR/2010/WD-XMLHttpRequest2-20100907/#handler-xhr-onprogress">XHR progress event</a></li>
    <li><a href="http://www.w3.org/TR/FileAPI/#dfn-filereader">FileReader</a></li>
  </ol>

  <p>Keep in mind that not all browsers support all of this technology today, but they're getting close. I just wanted to create a clear and complete tutorial on how to go the whole hog and upload that dropped file.</p>

  <p>The end result: we're able to drop the file anywhere in the browser, we get a preview and progress of the upload, and it's a slick experience.</p>

  <figure>
    <img src="http://html5doctor.com/wp-content/uploads/2012/03/dnd-upload.jpg" alt="Drag and drop upload" title="" />
    <figcaption>Our drag-and-drop example page</figcaption>
  </figure>
</section>

<section id="dnd">
  <h2>Drag and Drop <a href="#dnd" class="permalink">#</a></h2>

  <p>Just as a forewarning, drag-and-drop has been known to be a bit of a killjoy. In fact, it's a nightmare, but I won't repeat what's been <a href="http://www.quirksmode.org/blog/archives/2009/09/the_html5_drag.html">said</a> <a href="http://html5doctor.com/native-drag-and-drop/">before</a>.</p>

  <p>Our example is going to allow you to drag-and-drop a file anywhere within the browser. To achieve that, we need to attach our event listeners to the <code>body</code> or <code>documentElement</code> (i.e., the root HTML node). By listening on the <code>documentElement</code>, this code <em>could</em> be anywhere in the page, as <code>documentElement</code> will always exist. You can only listen on <code>body</code> once the <code>&lt;body&gt;</code> element has been encountered.</p>

  <p>Here's the pattern of code we need to capture the drop event on the entire document:</p>

  <figure>
    <pre><code>var doc = document.documentElement;
doc.ondragover = function () { this.className = 'hover'; return false; };
doc.ondragend = function () { this.className = ''; return false; };
doc.ondrop = function (event) {
  event.preventDefault &amp;&amp; event.preventDefault();
  this.className = '';

  // now do something with:
  var files = event.dataTransfer.files;

  return false;
};</code></pre>
    <figcaption>Basic pattern for capturing drop events</figcaption>
  </figure>

  <p>I'm using the <code>hover</code> class so that I can toggle a tip explaining to the user that the file can be dropped on the page.</p>

  <p>Inside the <code>drop</code> event, we can access the dropped files via <code>event.dataTransfer.files</code>.</p>

  <section id="alternative">
    <h3>An Alternative to Drag and Drop <a href="#alternative" class="permalink">#</a></h3>

    <p>Annoyingly, as I write this, I realise this combination of API requirements is currently only met by Chrome and Firefox. So, taking the test from <a href="http://modernizr.com">Modernizr</a>, we can test for support and provide our alternative:</p>

    <figure>
      <pre><code>var dndSupported = function () {
  var div = document.createElement('div');
  return ('draggable' in div) || ('ondragstart' in div &amp;&amp; 'ondrop' in div);
};

if (!dndSupported()) {
  // take alternative route
}</code></pre>
      <figcaption>Testing for drag-and-drop support</figcaption>
    </figure>

    <p>Instead of drag-and-drop, we can insert a file input element (I've given it an <code>id</code> of "upload"), and when its value is changed, the file can be scooped in:</p>

    <figure>
      <pre><code>document.getElementById('upload').onchange = function (event) {
  // `this` refers to the element the event fired upon
  var files = this.files;
};</code></pre>
      <figcaption>An alternative to native drag-and-drop</figcaption>
    </figure>

    <p>You can see the equivalent is simply the <code>files</code> property of the <code>HTMLInputElement</code> object. This will give us access to the same file as the <code>event.dataTransfer.files</code> from the drop event.</p>
  </section>
</section>

<section id="uploading">
  <h2>Automatically Uploading the File <a href="#uploading" class="permalink">#</a></h2>

  <p>This is the neat bit, and it's painfully simple. We use a feature of the XHR2 spec: <code>FormData</code>. Once we create an instance of <code>FormData</code>, we can append items to it:</p>

  <figure>
    <pre><code>var formData = new FormData();
for (var i = 0; i &lt; files.length; i++) {
  formData.append('file', files[i]);
}

// now post a new XHR request
var xhr = new XMLHttpRequest();
xhr.open('POST', '/upload');
xhr.onload = function () {
  if (xhr.status === 200) {
    console.log('all done: ' + xhr.status);
  } else {
    console.log('Something went terribly wrong...');
  }
};

xhr.send(formData);</code></pre>
    <figcaption>Creating and posting <code>FormData</code></figcaption>
  </figure>

  <p>Yeah, that's it.†</p>

  <aside class="sidenote">† As with everything and anything, a caveat: <code>FormData</code> isn't in Opera (nor .next) at time of writing, but I'm sure they'll catch up.</aside>

  <p>Let's look at a couple of key things that are going on the above code.</p>

  <pre><code>formData.append('file', files[i]);</code></pre>

  <p>We're sending named parameters to our server, specifically an array of values called <code>file</code>. Obviously, you can call it what you want, but the <code>file</code> is the name your server will be looking for when it saves the uploaded file (or files).</p>

  <pre><code>xhr.onload = function () {
  if (xhr.status === 200) {
    console.log('all done: ' + xhr.status);
  } else {
    console.log('Something went terribly wrong...');
  }
};</code></pre>

  <p>If you're familiar with XHR, you'll notice we aren't listening to <code>onreadystatechange</code>, only <code>onload</code> — which is (in effect) a convenience function to let you know when the <code>readyState</code> is 4 (i.e., loaded!). You should still check and respond appropriately to the status code of the request to ensure it's 200 OK, rather than a 500 (internal server error) or 404 (not found) or anything else.</p>

  <pre><code>xhr.send(formData);</code></pre>

  <p>The nice trick here is that XHR has automatically set the encoding of the posted data to <code>multipart/form-data</code>. This encoding allows your server to read and save the files. It's like the encoding used when you send an attachment in an email.</p>
</section>

<section id="feedback">
  <h2>Providing Feedback to the User <a href="#feedback" class="permalink">#</a></h2>

  <p>XHR2 now (flippin' finally) comes with a <code>progress</code> event. So if you're sending or retrieving a large file via XHR, you can tell the user how far along you are.</p>

  <p>It's pretty simple. If you want to track the progress of the XHR request, listen to the <code>progress</code> event. One gotcha that caught me out for some time: I needed to track the progress of the <em>upload</em>, not the download. To do this properly, you need to listen for progress on the <strong>XHR upload</strong> object, as so:</p>

  <figure>
    <pre><code>xhr.upload.onprogress = function (event) {
  if (event.lengthComputable) {
    var complete = (event.loaded / event.total * 100 | 0);
    progress.value = progress.innerHTML = complete;
  }
};

xhr.onload = function () {
  // just in case we get stuck around 99%
  progress.value = progress.innerHTML = 100;
};</code></pre>
    <figcaption>Providing feedback with XHR2's <code>progress</code> event</figcaption>
  </figure>

  <aside class="sidenote">The funky <code>| 0</code> syntax is bitwise shift to floor the value — for example, 2.69 becomes 2.</aside>

  <p>Note that instead of <code>xhr.onprogress</code>, we use <code>xhr.upload.onprogess</code>. When this event fires, we check that the event supports calculating the amount of data uploaded (the <code>lengthComputable</code> part), and then calculate the amount completed.</p>

  <p>In my HTML, I'm using a <code>&lt;progress&gt;</code> element (similar to the <code>&lt;meter&gt;</code> element, but more semantically appropriate as we're presenting the progress of a task) to show the user how much of their file has been uploaded:</p>

  <pre><code>&lt;progress id="progress" min="0" max="100" value="0"&gt;0&lt;/progress&gt;</code></pre>

  <p>Note that I'm using <code>innerHTML</code> for browsers that don't yet support <code>&lt;progress&gt;</code>. Then with a dash of CSS-generated content, both the <code>innerHTML</code> and <code>value</code> of the progress can be the same (perhaps an over optimisation, but I was rather proud of myself at the time!).</p>
</section>

<section id="preview">
  <h2>And Finally, Rendering a Preview <a href="#preview" class="permalink">#</a></h2>

  <p>As a nice addition, we'll give the user a preview of what we're uploading for them. It requires the <a href="http://dev.w3.org/2006/webapi/FileAPI/">File API</a> — specifically the <code>FileReader</code> API.</p>

  <p>As the drag-and-drop operation (or the <code>input[type=file]</code>) contains a file object, we can hand this over to the <code>FileReader</code> to get the contents of the file. If it's something like an image, we can get the Base64 data and give the user a preview. Or if it's text, we could render it in a <code>&lt;div&gt;</code>. The MIME type for the file is available as the <code>type</code> property on the file object.</p>

  <p>So let's assume we only accept images. Here's the preview part that runs after the file has been received by the browser:</p>

  <figure>
    <pre><code>var acceptedTypes = {
  'image/png': true,
  'image/jpeg': true,
  'image/gif': true
};

if (acceptedTypes[file.type] === true) {
  var reader = new FileReader();
  reader.onload = function (event) {
    var image = new Image();
    image.src = event.target.result;
    image.width = 100; // a fake resize
    document.body.appendChild(image);
  };

  reader.readAsDataURL(file);
}</code></pre>
    <figcaption>Rendering a preview of an uploaded image</figcaption>
  </figure>

  <p>We create the <code>FileReader</code> and give it a file to read. In the above example, I've used <code>readAsDataURL</code>, but you can also read files in plain text and binary formats (<a href="http://www.w3.org/TR/FileAPI/#FileReader-interface">as per the spec</a>).</p>

  <p>When the reader has read the file and the data is available, it fires the <code>load</code> event, which in turn creates our new image.</p>

  <p>The <em>result</em> of the file read action is in the <code>event.target.result</code> property. In the case of the <code>readAsDataURL</code>, the value is along the lines of <code>data:image/png;base64,ABC...</code>.</p>
</section>

<section id="finale">
  <h2>Using All the Tools in the Shed <a href="#finale" class="permalink">#</a></h2>

  <p>This example may be a little contrived for the article that I wanted to write. I've used many different technologies to do something that's a fairly common pattern on the web. In fact, it was because I had trouble finding a definitive source on uploading to the <em>actual</em> server (except, of course, as I wrote this article I found <a href="http://www.profilepicture.co.uk/tutorials/ajax-file-upload-xmlhttprequest-level-2/">this example</a> from back in late 2010!).</p>

  <p>Hopefully, you'll see how each bit of tech can work together to create an application, but equally I hope that you can see where this would work if none or just some of the technology wasn't available. Make sure you detect functionality. Make sure you provide fallbacks. Make sure you develop responsibly.</p>

  <p>Here's the final <a href="http://html5demos.com/dnd-upload">drag-and-drop and upload demo</a> for you to play with.</p>
</section><div id="crp_related"><h3>Related Posts:</h3><ul class="related"><li><a href="http://html5doctor.com/native-drag-and-drop/" rel="bookmark" class="crp_title">Native Drag and Drop</a></li><li><a href="http://html5doctor.com/accessibility-native-drag-and-drop/" rel="bookmark" class="crp_title">Accessibility &#038; Native Drag and Drop</a></li><li><a href="http://html5doctor.com/methods-of-communication/" rel="bookmark" class="crp_title">Methods of communication</a></li><li><a href="http://html5doctor.com/your-questions-answered-9/" rel="bookmark" class="crp_title">Your Questions Answered 9</a></li><li><a href="http://html5doctor.com/server-sent-events/" rel="bookmark" class="crp_title">Server-Sent Events</a></li></ul></div><p><a href="http://html5doctor.com/drag-and-drop-to-server/" rel="bookmark">Drag and Drop and Automatically Send to the Server</a> originally appeared on <a href="http://html5doctor.com">HTML5 Doctor</a> on April 3, 2012.</p>
]]></content:encoded>
			<wfw:commentRss>http://html5doctor.com/drag-and-drop-to-server/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>Using Modernizr to detect HTML5 features and provide fallbacks</title>
		<link>http://html5doctor.com/using-modernizr-to-detect-html5-features-and-provide-fallbacks/</link>
		<comments>http://html5doctor.com/using-modernizr-to-detect-html5-features-and-provide-fallbacks/#comments</comments>
		<pubDate>Tue, 27 Mar 2012 13:30:04 +0000</pubDate>
		<dc:creator>Tom Leadbetter</dc:creator>
				<category><![CDATA[Browser Compatibility]]></category>
		<category><![CDATA[canvas]]></category>
		<category><![CDATA[modernizr]]></category>
		<category><![CDATA[yepnope]]></category>

		<guid isPermaLink="false">http://html5doctor.com/?p=4371</guid>
		<description><![CDATA[<p>Modernizr is a JavaScript library that detects which HTML5 and CSS3 features your visitor's browser supports. In detecting feature support, it allows developers to test for some of the new technologies and then provide fallbacks for browsers that do not support them. This is called <dfn>feature detection</dfn> and is much more efficient than browser sniffing. In this article we'll look at how to use Modernizr for feature detection.</p>]]></description>
			<content:encoded><![CDATA[<p style="text-align:center;"><img src="http://html5doctor.com/wp-content/uploads/2012/02/modernizr-logo.jpg" alt="Modernizr logo" width="296" height="87" /></p>
<p><a href="http://www.modernizr.com/">Modernizr</a> is a JavaScript library that detects which HTML5 and CSS3 features your visitor&#8217;s browser supports. In detecting feature support, it allows developers to test for some of the new technologies and then provide fallbacks for browsers that do not support them. This is called <dfn>feature detection</dfn> and is much more efficient than browser sniffing.</p>
<div class="callout">
<p>Modernizr is very useful for detecting CSS3 support, but this article will focus on HTML5. The principles are essentially the same, though.</p>
</div>
<p>It&#8217;s important to note that Modernizr doesn&#8217;t &#8220;fill in the gaps&#8221; (i.e., <a href="https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-browser-Polyfills" title="HTML5 Cross-browser Polyfills on GitHub">polyfill</a>) for you. It only detects whether something is supported. But you can use Modernizr as part of the polyfilling process.</p>
<div class="callout highlight-block">
<p>Versions of IE8 and below do not recognise new-in-HTML5 elements by default, so you have to fix this with some JavaScript. You could possibly create each of these yourself with the below code, or you might use the <a href="http://code.google.com/p/html5shiv/">HTML5 Shiv</a> by <a href="http://twitter.com/rem" title="Remy Sharp on Twitter">@rem</a>, which includes all the new elements.</p>
<p>Modernizr does all this for you, so you don&#8217;t need include the Shiv.</p>
</div>
<section id="getting-started">
<h2>Getting Started <a href="#getting-started" class="permalink">#</a></h2>
<p>First, you need an HTML document:</p>
<pre><code>&lt;!DOCTYPE html&gt;
&lt;html class="no-js" lang="en"&gt;
&lt;head&gt;
  &lt;meta charset="utf-8"&gt;
  &lt;title&gt;Hello Modernizr&lt;/title&gt;
  &lt;script src="modernizr.js"&gt;&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre>
<p>You can see in the code above that you need a <code>modernizr.js</code> file. You have to <a href="http://www.modernizr.com/download/">build and download</a> this yourself by choosing the features you want to detect. Do this by choosing the &#8216;Production&#8217; option in Figure 1 and then ticking the necessary options in Figure 2. This helps keep the file size down by not detecting everything Modernizr is capable of. There is a <a href="http://www.modernizr.com/downloads/modernizr-2.0.6.js">development version</a> (see Figure 1) that you can link to whilst developing your site, but before you put the site live, you should build the production file you need.</p>
<figure>
    <img src="http://html5doctor.com/wp-content/uploads/2012/02/download-modernizr.jpg" alt="Modernizr download options" width="522" height="202" /></p>
<figcaption>Figure 1: Modernizr download options</figcaption>
</figure>
<figure>
    <img src="http://html5doctor.com/wp-content/uploads/2012/02/download-modernizr-2.jpg" alt="Modernizr build options" width="880" height="863" /></p>
<figcaption>Figure 2: Modernizr configuration &amp; build options</figcaption>
</figure>
<p>Also notice the second line of the HTML above: there is a <code>no-js</code> class on the <code>&lt;html&gt;</code> element. Modernizr first removes this and replaces it with a <code>js</code> class, which could be useful in your CSS. Along with the <code>js</code> class, it adds classes for all the features the browser supports <em>and</em> for the features it does not support, pre-fixing those with <code>no-</code>.</p>
<p>Here are two examples, one from Chrome 16 and one from IE9:</p>
<figure>
<pre><code>&lt;html class="js flexbox canvas canvastext webgl no-touch geolocation postmessage websqldatabase indexeddb hashchange history draganddrop websockets rgba hsla multiplebgs backgroundsize borderimage borderradius boxshadow textshadow opacity cssanimations csscolumns cssgradients cssreflections csstransforms csstransforms3d csstransitions fontface generatedcontent video audio localstorage sessionstorage webworkers applicationcache svg inlinesvg smil svgclippaths"&gt;</code></pre>
<figcaption>Figure 3: Modernizr&#8217;s feature detection in Chrome 16</figcaption>
</figure>
<figure>
<pre><code>&lt;html class="js <mark>no-flexbox</mark> canvas canvastext <mark>no-webgl</mark> no-touch geolocation postmessage <mark>no-websqldatabase</mark> <mark>no-indexeddb</mark> hashchange <mark>no-history</mark> draganddrop <mark>no-websockets</mark> rgba hsla multiplebgs backgroundsize <mark>no-borderimage</mark> borderradius boxshadow <mark>no-textshadow</mark> opacity <mark>no-cssanimations</mark> <mark>no-csscolumns</mark> <mark>no-cssgradients</mark> <mark>no-cssreflections</mark> csstransforms <mark>no-csstransforms3d</mark> <mark>no-csstransitions</mark> fontface generatedcontent video audio localstorage sessionstorage <mark>no-webworkers</mark> <mark>no-applicationcache</mark> svg inlinesvg smil svgclippaths"&gt;</code></pre>
<figcaption>Figure 4: Modernizr&#8217;s feature detection in IE9</figcaption>
</figure>
</section>
<section id="detection">
<h2>Do Some Detecting <a href="#detection" class="permalink">#</a></h2>
<p>Modernizr creates a global <code>Modernizr</code> JavaScript object, which allows us to query <a href="http://www.modernizr.com/docs/#features-html5" title="Full list of Modernizr's HTML5 feature detection">different properties</a> of that object to perform feature detection by calling <code>Modernizr.&lt;featurename&gt;</code>. So to test for <code>canvas</code> support, you would write the following:</p>
<pre><code>&lt;script&gt;
  <strong>if (Modernizr.canvas) {</strong>
    alert("This browser supports HTML5 canvas!");
  <strong>}</strong>
&lt;/script&gt;</code></pre>
<p>So <a href="/demos/modernizr/canvas-yes.htm" title="Live Example #1">try this page</a> in a modern browser and there will be a nice message for you.</p>
<p>Because you&#8217;re all good developers and write unobtrusive, progressive JavaScript so that everyone can use your site, you also want to check if canvas is <em>not</em> supported. You have a couple of options here. You could use the above <code>if</code> statement along with an <code>else</code> statement, <a href="/demos/modernizr/canvas-both.htm" title="Live Example #2">like so</a>:</p>
<pre><code>&lt;script&gt;
  if (Modernizr.canvas) {
    alert("This browser supports HTML5 canvas!");
  } <strong>else {
    alert("no canvas :(");
  }</strong>
&lt;/script&gt;</code></pre>
<p>Or if you want to test purely for no canvas support, you can negate the condition <a href="/demos/modernizr/canvas-not.htm" title="Live Example #3">like this</a>:</p>
<pre><code>&lt;script&gt;
  if (<strong>!Modernizr.canvas</strong>) {
    alert("No canvas here");
  }
&lt;/script&gt;</code></pre>
</section>
<section id="yep-nope">
<h2>Feature Detection and Polyfilling with YepNope <a href="#yep-nope" class="permalink">#</a></h2>
<p>In the examples above, you&#8217;ve seen the simplest way to detect a browser feature. What if you wanted to detect a feature and use a polyfill to make the browser perform better? You can do this with <a href="http://yepnopejs.com">YepNope</a>.</p>
<p>YepNope is a conditional loader, which means it will only load the scripts that are needed by the browser. And it&#8217;s built into Modernizr, so you don&#8217;t have to worry about downloading and linking to another JavaScript file.</p>
<p>So how do you use it?</p>
<p>Using canvas as an example again, you’ll generally want a fallback for non-supporting IE8 and below. The usual way of doing this would be to link to a JavaScript polyfill, such as <a href="http://flashcanvas.net">FlashCanvas</a> in your HTML:</p>
<pre><code>&lt;script src="http://flashcanvas.net/bin/flashcanvas.js"&gt;&lt;/script&gt;</code></pre>
<p>The problem with this approach is that all browsers will download this script. That&#8217;s unnecessary and should be avoided where possible. You could arguably wrap the <code>&lt;script&gt;</code> element in conditional comments, but if you can keep the files out of the markup altogether, then you should. You can do this using <code>Modernizr.load()</code>. Modernizr has YepNope built into it, so you can easily test for a feature and then supply a polyfill.</p>
<p>So let&#8217;s take a look.</p>
<div class="callout">
<p>You should note that <code>.load()</code> is not included in the development file by default. You need to include it and build it yourself.</p>
</p></div>
<p>The basic use of the <code>.load()</code> function allows you to <code>test</code> for a feature and ask whether it&#8217;s true (<code>yep</code>) or false (<code>nope</code>). In this example, Modernizr tests for canvas support, and if the feature doesn&#8217;t exist, then it loads FlashCanvas:</p>
<pre><code>Modernizr.load({
  test: Modernizr.canvas,
  nope: 'http://flashcanvas.net/bin/flashcanvas.js'
});</code></pre>
<p>So open up IE8, take a look at the network tab (Figure 5) in the developer tools. With the above code, you&#8217;ll see that it downloaded and initialised <code>flashcanvas.js</code>. Pretty nifty, yes?</p>
<figure class="wider">
    <img src="http://html5doctor.com/wp-content/uploads/2012/02/ie8-network.jpg" alt="" width="733" height="194" /></p>
<figcaption>Figure 5: FlashCanvas resources loaded in IE8</figcaption>
</figure>
<p>Here&#8217;s a more practical example that detects the support of <code>&lt;input type="date"&gt;</code>. If it isn&#8217;t supported, it loads in <strong>two</strong> jQuery files and a CSS file to generate a styled date picker:</p>
<pre><code>&lt;script src="modernizr.js"&gt;&lt;/script&gt;
&lt;script&gt;Modernizr.load({
  test: Modernizr.inputtypes.date,
  nope: ['http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js', 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.7/jquery-ui.min.js', 'jquery-ui.css'],
  complete: function () {
    $('input[type=date]').datepicker({
      dateFormat: 'yy-mm-dd'
    });
  }
});
&lt;/script&gt;</code></pre>
<p>This test looks for <code>&lt;input type="date"&gt;</code> support. When it fails, it loads in the two external jQuery JavaScript files and a local CSS file. (Our tests suggest that the CSS file needs to be local.) Once it&#8217;s done that (i.e., on <code>complete</code>), it then calls the plugin for each <code>&lt;input type="date"&gt;</code> in the DOM. In most browsers, the jQuery will be loaded (Figure 6), but in Opera, the files aren&#8217;t loaded because it has a native calendar control (Figure 7):</p>
<figure>
    <img src="http://html5doctor.com/wp-content/uploads/2012/02/calendar-firefox.png" alt="jQuery date picker widget" width="430" height="276" /></p>
<figcaption>Figure 6: jQuery date picker widget in Firefox</figcaption>
</figure>
<figure>
    <img src="http://html5doctor.com/wp-content/uploads/2012/02/calendar-opera.png" alt="Opera date picker widget" width="361" height="276" /></p>
<figcaption>Figure 7: Native date picker widget in Opera</figcaption>
</figure>
<p>The two figures below show the difference in which resources the browsers downloads:</p>
<figure>
    <img src="http://html5doctor.com/wp-content/uploads/2012/02/resources-firefox.png" alt="Resources loaded in Firefox" width="253" height="194" /></p>
<figcaption>Figure 8: Date picker resources loaded in Firefox</figcaption>
</figure>
<figure>
    <img src="http://html5doctor.com/wp-content/uploads/2012/02/resources-opera.png" alt="Resources loaded in Opera" width="170" height="70" /></p>
<figcaption>Figure 9: Date picker resources loaded in Opera</figcaption>
</figure>
<p>Notice how the two jQuery JavaScript files are loaded twice. That&#8217;s a <a href="http://yepnopejs.com/#twice">YepNope behaviour</a>, first loading the resource and then executing it. So don&#8217;t worry, that&#8217;s normal.</p>
<p>You can do much more with YepNope. Here&#8217;s <a href="http://yepnopejs.com/#testObject">an example taken from the YepNope web site</a> of all the possible properties, all of which are optional:</p>
<pre class="tallCode"><code>yepnope([{
    test : <span class="optional">/* boolean<span class="comment">(ish)</span> - Something truthy that you want to test */</span>,
    yep : <span class="optional">/* array <span class="comment">(of strings)</span> | string - The things to load if <span class="keyword">test</span> is <span class="keyword">true</span> */</span>,
    nope : <span class="optional">/* array <span class="comment">(of strings)</span> | string - The things to load if <span class="keyword">test</span> is <span class="keyword">false</span> */</span>,
    both : <span class="optional">/* array <span class="comment">(of strings)</span> | string - Load everytime (sugar) */</span>,
    load : <span class="optional">/* array <span class="comment">(of strings)</span> | string - Load everytime (sugar) */</span>,
    callback : <span class="optional">/* function ( testResult, key ) | object { key : fn } */</span>,
    complete : <span class="optional">/* function */</span> }, /* ... */ ]);</code></pre>
</section>
<section id="conclusion">
<h2>Conclusion <a href="#conclusion" class="permalink">#</a></h2>
<p>Modernizr is a powerful feature detection library. It allows you to check whether a browser supports various features and, depending on what you want to achieve, lets you use a polyfill. This article looked at how to generate a Modernizr JavaScript file and examined two different ways of using Modernizr: directly using the Modernizr object (<code>Modernizr.&lt;featurename&gt;</code>) and then using the built-in YepNope.</p>
<p>So, what do you think? Let us know in the comments below!</p>
</section>
<div id="crp_related">
<h3>Related Posts:</h3>
<ul class="related">
<li><a href="http://html5doctor.com/ol-element-attributes/" rel="bookmark" class="crp_title">The <code>ol</code> Element and Related Attributes: <code>type</code>, <code>start</code>, <code>value</code>, and <code>reversed</code></a></li>
<li><a href="http://html5doctor.com/how-to-get-all-the-browsers-playing-ball/" rel="bookmark" class="crp_title">How to get all the browsers playing ball</a></li>
<li><a href="http://html5doctor.com/the-details-and-summary-elements/" rel="bookmark" class="crp_title">The details and summary elements</a></li>
<li><a href="http://html5doctor.com/drag-and-drop-to-server/" rel="bookmark" class="crp_title">Drag and Drop and Automatically Send to the Server</a></li>
<li><a href="http://html5doctor.com/storing-data-the-simple-html5-way-and-a-few-tricks-you-might-not-have-known/" rel="bookmark" class="crp_title">Storing Data the Simple HTML5 Way (and a few tricks you might not have known)</a></li>
</ul>
</div>
<p><a href="http://html5doctor.com/using-modernizr-to-detect-html5-features-and-provide-fallbacks/" rel="bookmark">Using Modernizr to detect HTML5 features and provide fallbacks</a> originally appeared on <a href="http://html5doctor.com">HTML5 Doctor</a> on March 27, 2012.</p>
]]></content:encoded>
			<wfw:commentRss>http://html5doctor.com/using-modernizr-to-detect-html5-features-and-provide-fallbacks/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>CSS3 Pseudo-Classes and HTML5 Forms</title>
		<link>http://html5doctor.com/css3-pseudo-classes-and-html5-forms/</link>
		<comments>http://html5doctor.com/css3-pseudo-classes-and-html5-forms/#comments</comments>
		<pubDate>Tue, 28 Feb 2012 14:30:47 +0000</pubDate>
		<dc:creator>Peter Gasston</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[forms]]></category>
		<category><![CDATA[css3]]></category>
		<category><![CDATA[HTML 5]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[readonly]]></category>
		<category><![CDATA[required]]></category>

		<guid isPermaLink="false">http://html5doctor.com/?p=4483</guid>
		<description><![CDATA[<p>Guest Doctor Peter Gasston takes a look at how new CSS3 Pseudo-classes align perfectly with HTML5 Forms.</p>]]></description>
			<content:encoded><![CDATA[<p>Hello! I’m Doctor Peter and I’m here to treat you with a dose of complementary CSS3. Don’t worry, this won’t hurt a bit.</p>

<p>Contrary to what <a href="http://html5please.com/">HTML5 Please</a> and the W3C would have you believe, CSS3 is not part of HTML5. “But this is HTML5 Doctor,” I imagine you saying. “Why are you talking about CSS3 here?” Well, I want to talk about a very specific part of CSS3, one that works in perfect tandem with HTML5, specifically with the new form functions that are available.</p>

<p>One of the killer features that HTML5 introduces is client-side form validation without using JavaScript. Now, I know the other doctors haven’t discussed this yet, and as I’m just a locum, you might feel as if I’m putting the cart before the horse (#mixedmetaphors), but I’m hoping to explain just enough to let you know how it works, and then your regular doctors can provide the details at a later date.</p>

<section id="pseudo-classes">
  <h2>A Recap of Pseudo-Classes <a href="#pseudo-classes" class="permalink">#</a></h2>

  <p>A <dfn>pseudo-class</dfn> is information about an element that’s in the document tree but not available through any specified attributes. For example, the <code>:first-child</code> pseudo-class applies to elements which are the first child of their parents. You can get that information from the DOM tree, but there’s no <code>first-child</code> attribute.</p>

  <p>In CSS2.1, there were a handful of pseudo-classes available, notably the link states (<code>:link</code>, <code>:visited</code>) and those of user actions (<code>:active</code>, <code>:hover</code>). In CSS3, that handful becomes a basketful, with pseudo-classes of structure (<code>:nth-child</code>, <code>:nth-of-type</code>), UI element (<code>:enabled</code>, <code>:checked</code>), and the ones we’ll look at now, of form validation.</p>
</section>

<section id="form-validation">
  <h2>Form Validation without JavaScript <a href="#form-validation" class="permalink">#</a></h2>
  
  <p>So as I mentioned at the beginning, HTML5 introduces client-side form validation without the need for JavaScript. When you attempt to submit a form, your browser will validate all of the fields and return an error if any of the fields is incorrect. This will happen mostly automagically — provided your browser has the capability — and will look something like what’s shown in Figure 1:</p>

  <figure>
    <img src="http://html5doctor.com/demos/pseudo-classes/figure1.png" alt="Form with an invalid field and associated error message">
    <figcaption>Figure 1: A form validation error message</figcaption>
  </figure>

  <p>Those error messages are browser and OS specific, and hard to modify (<a href="http://www.broken-links.com/2011/06/16/styling-html5-form-validation-errors/" title="Styling HTML5 Form Validation Errors">which I documented on my blog</a>), but you can change the way the errors appear on the elements themselves with the new validation pseudo-classes, which are part of the <a href="http://www.w3.org/TR/css3-ui/">CSS3 Basic UI module</a>.</p>
  
  <p>I’ll cover current browser support as we go through the article, but in a nutshell:</p>
  
  <ul>
    <li>Firefox and IE10 support some of it.</li>
    <li>Opera and Chrome support all of it.</li>
    <li>Safari supports all of it too, but form validation is disabled by default.</li>
  </ul>
  
  <p>That being the case, I’d recommend using Chrome, Opera, or Safari to view the examples I’ll be showing you.</p>
  
  <p>If you want to keep up to date with browser support for form validation, I suggest keeping an eye on <a href="http://caniuse.com/#feat=form-validation">When can I use</a>.</p>
  
  <p>So with all of the boring technical guff out of the way, let’s get on with the interesting technical guff and take a look at some examples of form validation.</p>
  
  <section id="required-and-optional-elements">
    <h3>Required and Optional Elements <a href="#required-and-optional-elements" class="permalink">#</a></h3>
    
    <p>One of the most common patterns of validation is that of mandatory (that is, required) values — the fields that the user must complete in order to progress. To mark a form element as mandatory, you need only add the <code>required</code> attribute to it:</p>
    
    <pre><code>&lt;input type="text" required&gt;</code></pre>
    
    <p>If you want to apply styles to this in order to show that requirement, you can use the new <code>:required</code> pseudo-class, which applies rules to any matched element which has the <code>required</code> attribute. For example, you may want to put an asterisk after the text of the label:</p>
    
    <pre><code>input:required + label::after { content: "*"; }</code></pre>
    
    <p>The exact rules you use depends on how you’ve marked up your document. The rule in this example is based on the markup having this structure:</p>
    
    <pre><code>&lt;input type="text" required id="foo"&gt;
&lt;label for="foo"&gt;Foo&lt;/label&gt;</code></pre>
    
    <p>The opposite of required is, of course, optional. And wouldn’t you know it, we have a pseudo-class for that too, logically named <code>:optional</code>. It affects any form element that doesn’t have a <code>required</code> attribute. For example, you may want to make those have a lighter border:</p>
    
    <pre><code>input:optional { border-color: silver; }</code></pre>
    
    <p>You can see this in action in Figure 2, or <a href="http://html5doctor.com/demos/pseudo-classes/example1.html" title="Live Example #1">take a look at a live example</a>.</p>

    <figure>
      <img src="http://html5doctor.com/demos/pseudo-classes/figure2.png" alt="Required and optional form fields">
      <figcaption>Figure 2: Input fields styled with <code>:required</code> (top) and <code>:optional</code> (bottom)</figcaption>
    </figure>
  </section>

  <section id="valid-and-invalid-elements">
    <h3>Valid and Invalid Elements <a href="#valid-and-invalid-elements" class="permalink">#</a></h3>

    <p>There are other types of validation besides simply “required” or “optional”. You can use pattern matching, such as email address validation:</p>
    
    <pre><code>&lt;input type="email"&gt;</code></pre>

    <p>If the user enters anything into the field, it has to match the pattern of an email address, or else it will be marked as invalid. (Of course, if it’s not required, then it can be left blank.)</p>
    
    <p>You can style valid or invalid form elements using pseudo-classes called — wait for it — <code>:valid</code> and <code>:invalid</code>. Maybe you want add a symbol depending on the validation status:</p>
    
    <pre><code>input:invalid + label::after { content: ' ⨉'; }
input:valid + label::after { content: ' ✓'; }</code></pre>

    <p>Note that these will take effect as soon as the page loads, so you’ll probably want to use JavaScript to apply them only after submission, perhaps by adding a class to the form with JavaScript:</p>
    
    <pre><code>document.forms[0].addEventListener('submit', function(e) {
  e.currentTarget.classList.add('submitted');
  // Your fallback form validation function
});</code></pre>

    <p>The exact script you use will vary, but however you do it, you can use that class to style the form elements, like so:</p>
    
    <pre><code>.submitted input:invalid + label::after { content: ' ⨉'; }</code></pre>
    
    <p>Figure 3 shows the output of this, and you can also <a href="http://html5doctor.com/demos/pseudo-classes/example2.html" title="Live Example #2">see the live example</a>.</p>

    <figure>
      <img src="http://html5doctor.com/demos/pseudo-classes/figure3.png" alt="Valid and invalid form fields">
      <figcaption>Figure 3: Showing the use of the <code>:valid</code> (top) and <code>:invalid</code> (bottom) pseudo-classes</figcaption>
    </figure>
    
    <p>Two extra things to note about this example: first, in order to use my own JavaScript, I’ve prevented the form from automatically validating by using the <code>novalidate</code> attribute on the submit button; and second, Firefox puts a coloured glow around elements depending on their validation state, which I’ve over-ruled by using their proprietary <code>:-moz-ui-invalid</code> selector. View the source of the demo to see how these are used.</p>
  </section>
  
  <section id="number-ranges">
    <h3>Number Ranges <a href="#number-ranges" class="permalink">#</a></h3>

    <p>Some of the new input types, such as <code>number</code>, allow a range of values using the <code>min</code> and <code>max</code> attributes, like so:</p>
    
    <pre><code>&lt;input type="number" max="10" min="1"&gt;</code></pre>
    
    <p>Although form controls will usually prevent the user from entering a value outside of this range, there may be occasions (such as when JavaScript is used to provide values) where the value provided to the input does exceed the range:</p>
    
    <pre><code>&lt;input type="number" max="10" min="1" value="11"&gt;</code></pre>
    
    <p>When this happens, you can use the <code>:out-of-range</code> pseudo-class for your styling:</p>
    
    <pre><code>input[type='number']:out-of-range { border-color: red; }</code></pre>

    <p>And, as you’d expect, there’s a counterpart known by the name of <code>:in-range</code>:</p>
    
    <pre><code>input[type='number']:in-range { border-color: green; }</code></pre>
    
    <p>In Figure 4 you can see these two pseudo-classes at work, and once more there’s also <a href="http://html5doctor.com/demos/pseudo-classes/example3.html" title="Live Example #3">a live example</a> to view.</p>

    <figure>
      <img src="http://html5doctor.com/demos/pseudo-classes/figure4.png" alt="Out-of-range and in-range form fields">
      <figcaption>Figure 4: The <code>:out-of-range</code> (top) and <code>:in-range</code> (bottom) pseudo-classes applied to a <code>range</code> input</figcaption>
    </figure>
  </section>
  
  <section id="reading-and-writing">
    <h3>Reading and Writing <a href="#reading-and-writing" class="permalink">#</a></h3>
    
    <p>You may have a form field that’s pre-filled with a value that you don’t want the user to be able to edit, such as terms and conditions in a <code>textarea</code>. If that’s the case, you can add the <code>readonly</code> attribute:</p>
    
    <pre><code>&lt;textarea readonly&gt;Lorem ipsum&lt;/textarea&gt;</code></pre>
    
    <p>You can style elements which have the <code>readonly</code> attribute applied, using…can you guess? You are correct, imagined reader: the <code>:read-only</code> pseudo-class. You could combine it with the <code>user-select</code> CSS property to prevent the user from being able to select the text (in the example, I’ve also changed the border style to make it more obvious):</p>
    
    <pre><code>textarea:read-only { user-select: none; }</code></pre>
    
    <p>And if you should need it, there is of course a <code>:read-write</code> pseudo-class for elements which don’t have the attribute applied:</p>
    
    <pre><code>textarea:read-write { user-select: text; }</code></pre>
    
    <p>You can see the results in Figure 5, and as before there’s <a href="http://html5doctor.com/demos/pseudo-classes/example4.html" title="Live Example #4">a live example</a> too.</p>

    <figure>
      <img src="http://html5doctor.com/demos/pseudo-classes/figure5.png" alt="Read-only and read-write form fields">
      <figcaption>Figure 5: The textarea on the left is styled using <code>:read-write</code>, and the one on the right, with <code>:read-only</code></figcaption>
    </figure>

    <p>Firefox and IE10 have actually implemented the <code>readonly</code> attribute, but don’t yet have support for these pseudo-classes.</p>
  </section>
</section>

<section id="browser-support">
  <h2>Browser Support <a href="#browser-support" class="permalink">#</a></h2>
  
  <p>This table lists support for HTML5 Form Validation in browsers at the time of writing:</p>
  
  <table>
    <caption>Browser support for HTML5 Form Validation</caption>
    <thead>
      <tr>
        <th>Browser/Attribute</th>
        <th scope="col">Chrome</th>
        <th scope="col">Firefox</th>
        <th scope="col">IE</th>
        <th scope="col">Opera</th>
        <th scope="col">Safari</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <th scope="row"><code>:optional</code> / <code>:required</code></th>
        <td>10.0</td>
        <td>4.0</td>
        <td>10.0</td>
        <td>10.0</td>
        <td>5.0</td>
      </tr>

      <tr>
        <th scope="row"><code>:invalid</code> / <code>:valid</code></th>
        <td>10.0</td>
        <td>4.0</td>
        <td>n/a</td>
        <td>10.0</td>
        <td>5.0</td>
      </tr>

      <tr>
        <th scope="row"><code>:in-range</code> / <code>:out-of-range</code></th>
        <td>10.0</td>
        <td>n/a</td>
        <td>n/a</td>
        <td>10.0</td>
        <td>5.0</td>
      </tr>

      <tr>
        <th scope="row"><code>:read-only</code> / <code>:read-write</code></th>
        <td>10.0</td>
        <td>n/a</td>
        <td>n/a</td>
        <td>10.0</td>
        <td>5.0</td>
      </tr>
    </tbody>
  </table>
</section>

<section id="goodbye">
  <h2>That’s All from Me <a href="#goodbye" class="permalink">#</a></h2>
  
  <p>I hope I’ve given you enough to whet your appetite for finding out more about HTML5 Form Validation. There’s plenty more to it, including a full JavaScript API (you can <a href="http://dev.w3.org/html5/spec-author-view/constraints.html#the-constraint-validation-api" title="4.10.21 Constraints — HTML5: Edition for Web Authors">read about this in the HTML5 spec</a>, but <a href="https://developer.mozilla.org/en/HTML/HTML5/Constraint_validation" title="Constraint Validation">MozDev has better documentation</a>).</p>
  
  <p>Thanks for your time, and thanks to the Doctors for this opportunity.</p>
</section><div id="crp_related"><h3>Related Posts:</h3><ul class="related"><li><a href="http://html5doctor.com/review-html5-designing-rich-internet-applications/" rel="bookmark" class="crp_title">Review: HTML5 Designing Rich Internet Applications</a></li><li><a href="http://html5doctor.com/the-output-element/" rel="bookmark" class="crp_title">The output element</a></li><li><a href="http://html5doctor.com/the-details-and-summary-elements/" rel="bookmark" class="crp_title">The details and summary elements</a></li><li><a href="http://html5doctor.com/html-5-reset-stylesheet/" rel="bookmark" class="crp_title">HTML5 Reset Stylesheet</a></li><li><a href="http://html5doctor.com/the-scoped-attribute/" rel="bookmark" class="crp_title">The scoped attribute</a></li></ul></div><p><a href="http://html5doctor.com/css3-pseudo-classes-and-html5-forms/" rel="bookmark">CSS3 Pseudo-Classes and HTML5 Forms</a> originally appeared on <a href="http://html5doctor.com">HTML5 Doctor</a> on February 28, 2012.</p>
]]></content:encoded>
			<wfw:commentRss>http://html5doctor.com/css3-pseudo-classes-and-html5-forms/feed/</wfw:commentRss>
		<slash:comments>33</slash:comments>
		</item>
		<item>
		<title>The ol Element and Related Attributes: type, start, value, and reversed</title>
		<link>http://html5doctor.com/ol-element-attributes/</link>
		<comments>http://html5doctor.com/ol-element-attributes/#comments</comments>
		<pubDate>Tue, 21 Feb 2012 14:30:52 +0000</pubDate>
		<dc:creator>Oli Studholme</dc:creator>
				<category><![CDATA[Elements]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[li]]></category>
		<category><![CDATA[ol]]></category>

		<guid isPermaLink="false">http://html5doctor.com/?p=4397</guid>
		<description><![CDATA[<p>The <code>&#60;ol&#62;</code> element has a new attribute <code>reversed</code> in HTML5. In addition, a couple of related attributes purged in HTML 4 have made a return, namely <code>start</code> and <code>type</code> for <code>&#60;ol&#62;</code>, and <code>value</code> for <code>&#60;li&#62;</code>. Making things more interesting, the returning attributes were removed from HTML 4 for being presentational. So why are they back? Let’s investigate…</p>]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ol-element" title="4.5 Grouping content — HTML Standard">The <code>&lt;ol&gt;</code> element has a new attribute <code>reversed</code></a> in HTML5. In addition, a couple of related attributes purged in HTML 4 have made a return, namely <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#attr-ol-start" title="4.5 Grouping content — HTML Standard"><code>start</code></a> and <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#attr-ol-type" title="4.5 Grouping content — HTML Standard"><code>type</code></a> for <code>&lt;ol&gt;</code>, and <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-li-element" title="4.5 Grouping content — HTML Standard"><code>value</code> for <code>&lt;li&gt;</code></a>. Making things more interesting, the returning attributes were <a href="http://www.w3.org/TR/html4/appendix/changes.html#h-A.3.2" title="HTML 4 Changes">removed from HTML 4 for being presentational</a>. So why are they back? Let’s investigate…</p>

<section id="presentational-and-semantic">
<h2>Presentational <em>and</em> semantic? <a class="permalink" href="#presentational-and-semantic">#</a></h2>

<p>As we all know, presentational stuff belongs in CSS, not HTML. In HTML 4.01, the <code>type</code> attribute was replaced by <code>list-style-type</code>, and the <code>start</code> and <code>value</code> attributes were dropped, with only the potential (although fiddly) replacement in some cases of <a href="http://dev.w3.org/csswg/css3-content/#counters" title="CSS Generated Content Module Level 3">CSS generated content-based counters</a>. So why would we want to specify “presentational” stuff like a list’s style in our HTML?</p>

<section id="type-attribute">
<h3>The <code>type</code> Attribute <a class="permalink" href="#type-attribute">#</a></h3>

<p>While an ordered list’s counter style is generally presentational, in some documents it can be a part of the document’s <em>meaning</em>, as the specification for the <code>type</code> attribute notes:</p>

<figure>
<blockquote>
The <code>type</code> attribute can be used to specify the kind of marker to use in the list, in the cases where that matters (e.g. because items are to be referenced by their number/letter).
</blockquote>
<figcaption>— <cite><a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#attr-ol-type">HTML: Living Standard</a></cite>, <abbr>WHATWG</abbr></figcaption>
</figure>

<p>Examples of this include legal or technical documents, which can contain references to non-decimal list items in prose:</p>

<figure>
<blockquote id="legalese">
<style scoped>/* yeah, just faking it here for demonstration purposes */
#legalese div {margin-left: 3em;}
#legalese .point-3-3:before {
  display: block;
  position: absolute;
  content: "3.3 ";
  left: -3em;
}
</style>
<div class="point-3-3"><b>Obligations of the Company – Tranche One</b><br />
Subject to satisfaction of <mark>clause 3.2(a)</mark>, on Tranche One Completion the Company will:</div>
<div>(a) Purchase a foosball table for staff use</div>
<div>(b) …</div>
</ol>
</blockquote>
<figcaption>Mockup of an example legal document with a highlighted reference to a non-decimal list item</figcaption>
</figure>

<p>We can specify the list’s style using the <code>type</code> attribute, with the following values:</p>

<table>
<caption><code>type</code> attribute values and their corresponding list counter types</caption>
<thead>
<tr><th scope="col"><code>&lt;ol type=""&gt;</code> values</th><th scope="col">Equivalent <code>list-style-type</code></th></tr>
</thead>
<tbody>
<tr><th scope="row"><code>type="1"</code></th><td><code>decimal</code> (default style)</td></tr>
<tr><th scope="row"><code>type="a"</code></th><td><code>lower-alpha</code></td></tr>
<tr><th scope="row"><code>type="A"</code></th><td><code>upper-alpha</code></td></tr>
<tr><th scope="row"><code>type="i"</code></th><td><code>lower-roman</code></td></tr>
<tr><th scope="row"><code>type="I"</code></th><td><code>upper-roman</code></td></tr>
</tbody>
</table>

<p>Further emphasising that this is not a general alternative to <code>list-style-type</code>, only these five list styles are available, whereas <a href="http://www.w3.org/TR/CSS2/generate.html#list-style" title="Generated content, automatic numbering, and lists">CSS 2.1 defines eleven <code>&lt;ol&gt;</code> list styles</a>. If you’re not referring to list counters in your prose, or even if you are but you’re just using the default decimal list counters, then you should use CSS over the <code>type</code> attribute. However, if the list counter type has a semantic meaning, HTML is the place to put it. Note that CSS <code>list-style-type</code> will override HTML <code>type</code> attribute values, so they’ll only work if you <em>haven’t</em> specified a <code>list-style-type</code> in your CSS.</p>

<!-- /#type-attribute --></section>

<section id="start-value-attribute">
<h3>The <code>start</code> and <code>value</code> Attributes <a class="permalink" href="#start-value-attribute">#</a></h3>

<p>The <code>start</code> attribute lets us set a list’s first counter. It’s handy for lists that must be split over several <code>&lt;ol&gt;</code> elements, by allowing us to continue the list item numbering from where the previous list left off. The related <code>value</code> attribute is used on an <code>&lt;li&gt;</code> element, and lets us manually number list items. <code>value</code> on the first list item also overrides <code>start</code>. A subsequent <code>&lt;li&gt;</code> element <em>without</em> <code>value</code> will increment the previous <code>value</code> by one.</p>

<figure>
<blockquote>
The first item in the list has the ordinal value given by the <code>ol</code> element’s <code>start</code> attribute, unless that <code>li</code> element has a <code>value</code> attribute with a value that can be successfully parsed, in which case it has the ordinal value given by that <code>value</code> attribute.
</blockquote>
<figcaption>— <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ol-element" title="4.5 Grouping content — HTML Standard"><cite>HTML: Living Standard</cite></a>, <abbr>WHATWG</abbr></figcaption>
</figure>

<p>Here’s an example of how you could use <code>start</code> or <code>value</code> to continue a list, which also demonstrates <code>type</code>:</p>

<figure>
<pre><code>&lt;!-- Continuing a previous list with value="" --&gt;
&lt;ol type="I"&gt;
  &lt;li value="7"&gt;seventh item&lt;/li&gt;
  &lt;li&gt;eighth item&lt;/li&gt;
  &lt;li&gt;ninth item&lt;/li&gt;
&lt;/ol&gt;
&lt;!-- Continuing a previous list with start="" --&gt;
&lt;ol type="I" start="7"&gt;
  &lt;li&gt;seventh item&lt;/li&gt;
  &lt;li&gt;eighth item&lt;/li&gt;
  &lt;li&gt;ninth item&lt;/li&gt;
&lt;/ol&gt;
</code></pre>
<div class="column">
<ol type="I">
  <li value="7">seventh item <span class="meta">(using <code>&lt;li value="7"&gt;</code>)</span></li>
  <li>eighth item</li>
  <li>ninth item</li>
</ol>
<ol type="I" start="7">
  <li>seventh item <span class="meta">(using <code>&lt;ol start="7"&gt;</code>)</span></li>
  <li>eighth item</li>
  <li>ninth item</li>
</ol>
</div>
<figcaption>Using <code>value</code> and <code>start</code> to continue a previous list of six items</figcaption>
</figure>

<p>While both of these attributes give us more control, they unfortunately also mean adding or removing list items can make your <code>start</code> or <code>value</code>-based numbering appear broken, so in general you’ll probably want to avoid them and <a href="http://dev.opera.com/articles/view/automatic-numbering-with-css-counters/" title="Automatic numbering with CSS Counters - Dev.Opera">investigate CSS generated content counters</a> instead. You’ll need to use generated content counters if you want to make “1.1.1”-style nested list counters too.</p>

<!-- /#start-value-attribute --></section>

<!-- /#presentational-and-semantic --></section>

<section id="reverse">
<h2>Counting It Down with <code>reverse</code> <a class="permalink" href="#reverse">#</a></h2>

<p>The new attribute <code>reverse</code> allows us to make ordered lists that count <em>down</em> rather than up. If you’re coding a top ten countdown or you’re a space junkie, it’s the attribute you’ve always wanted.</p>

<figure>
<blockquote>
The reversed attribute is a boolean attribute. If present, it indicates that the list is a descending list (..., 3, 2, 1).
</blockquote>
<figcaption>— <cite><a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#attr-ol-reversed">HTML: Living Standard</a></cite>, <abbr>WHATWG</abbr></figcaption>
</figure>

<p>By default, <code>&lt;ol reversed&gt;</code> starts from the total number of list items and counts down to one, so there’s no need to also specify <code>start</code> unless you want something different to happen. Unfortunately, as we’ll see in the <a href="#browser-support">browser support table</a> in just a moment, none of them do yet, so in the meantime you can make a reversed list by manually specifying each list item’s number with <code>value</code> (as you can see in the following example) or via CSS counters.</p>

<figure>
<pre><code>&lt;!-- default list --&gt;
&lt;ol&gt;
  &lt;li&gt;three&lt;/li&gt;
  &lt;li&gt;two&lt;/li&gt;
  &lt;li&gt;one&lt;/li&gt;
&lt;/ol&gt;
&lt;!-- using the reversed attribute (will look the same as the third list in a supporting browser) --&gt;
&lt;ol reversed&gt;
  &lt;li&gt;three&lt;/li&gt;
  &lt;li&gt;two&lt;/li&gt;
  &lt;li&gt;one&lt;/li&gt;
&lt;/ol&gt;
&lt;!-- using value attributes on li --&gt;
&lt;ol&gt;
  &lt;li value="3"&gt;three&lt;/li&gt;
  &lt;li value="2"&gt;two&lt;/li&gt;
  &lt;li value="1"&gt;one&lt;/li&gt;
&lt;/ol&gt;</code></pre>
<div class="columns">
<ol>
<li>three</li>
<li>two</li>
<li>one</li>
</ol>
<ol reversed>
<li>three</li>
<li>two</li>
<li>one</li>
</ol>
<ol>
<li value="3">three</li>
<li value="2">two</li>
<li value="1">one</li>
</ol>
</div>
<figcaption>A normal ordered list, an ordered list with <code>reversed</code>, and an ordered list with each list item numbered manually via <code>value</code></figcaption>
</figure>

<!-- /#reverse --></section>

<section id="browser-support">
<h2>Browser support table <a class="permalink" href="#browser-support">#</a></h2>

<p>Browsers support the <code>start</code>, <code>type</code>, and <code>value</code> attributes as part of supporting legacy content (<a href="http://www.w3.org/TR/REC-html32#ol" title="HTML 3.2 Reference Specification">HTML 3.2 represent!</a>), so we can use them <em>now</em>.</p>

<table class="browser-support centered-data">
<caption>Browser support for <code>type</code>, <code>start</code>, <code>value</code>, and <code>reversed</code> attributes</caption>
<thead>
<tr>
  <th scope="col">Attribute</th>
  <th scope="col"><abbr title="Internet Explorer">IE</abbr></th>
  <th scope="col">Firefox</th>
  <th scope="col">Safari</th>
  <th scope="col">Chrome</th>
  <th scope="col">Opera</th>
</tr>
</thead>
<tbody>
<tr>
  <th scope="row"><code>&lt;ol type=""&gt;</code></th>
  <td><span title="Yes">✔</span></td>
  <td><span title="Yes">✔</span></td>
  <td><span title="Yes">✔</span></td>
  <td><span title="Yes">✔</span></td>
  <td><span title="Yes">✔</span></td>
</tr>
<tr>
  <th scope="row"><code>&lt;ol start=""&gt;</code></th>
  <td><span title="Yes">✔</span></td>
  <td><span title="Yes">✔</span></td>
  <td><span title="Yes">✔</span></td>
  <td><span title="Yes">✔</span></td>
  <td><span title="Yes">✔</span></td>
</tr>
<tr>
  <th scope="row"><code>&lt;li value=""&gt;</code></th>
  <td><span title="Yes">✔</span></td>
  <td><span title="Yes">✔</span></td>
  <td><span title="Yes">✔</span></td>
  <td><span title="Yes">✔</span></td>
  <td><span title="Yes">✔</span></td>
</tr>
<tr>
  <th scope="row"><code>&lt;ol reversed&gt;</code> <a href="#note-1">¹</a></th>
  <td class="warning"><span title="No">✘</span></td>
  <td class="warning"><span title="No">✘</span> <a href="#note-2">²</a></td>
  <td>5.2 <a href="#note-3">³</a></td>
  <td>18 <a href="#note-3">³</a></td>
  <td class="warning"><span title="No">✘</span></td>
</tr>
</tbody>
</table>

<ol>
<li id="note-1">We can use a JavaScript polyfill to get around the lack of native support for the <code>reversed</code> attribute, such as the <a href="http://www.impressivewebs.com/reverse-ordered-lists-html5/" title="Reverse Ordered Lists in HTML5 | Impressive Webs">polyfill (and accompanying article) from Louis Lazaris</a>, or <a href="https://gist.github.com/1671548">Titani’s polyfills</a>, which both use the <code>value</code> attribute.</li>
<li id="note-2"><ins datetime="2012-02-22T11:15:20+13:00">It’s <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=601912">bug 601912</a>, but there’s no progress as yet</ins></li>
<li id="note-3"><ins datetime="2012-02-22T11:15:20+13:00">Chrome 18 (in the dev channel at the time of writing) has support for <code>reversed</code> (thanks <a href="http://html5doctor.com/ol-element-attributes/#comment-24515">Philip Tellis</a>), as does Safari 5.2 Developer Release (thanks <a href="http://html5doctor.com/ol-element-attributes/#comment-24521">Sam Rayner</a>)</ins></li>
</ol>

<figure>
<pre><code>&lt;!-- default (unsupported) reversed attribute --&gt;
&lt;ol reversed&gt;
  &lt;li&gt;three&lt;/li&gt;
  &lt;li&gt;two&lt;/li&gt;
  &lt;li&gt;one&lt;/li&gt;
&lt;/ol&gt;
&lt;!-- using a reversed attribute polyfill --&gt;
&lt;ol class="polyfill-me" reversed&gt;
  &lt;li&gt;three&lt;/li&gt;
  &lt;li&gt;two&lt;/li&gt;
  &lt;li&gt;one&lt;/li&gt;
&lt;/ol&gt;
</code></pre>
<div>

<div class="column">
<ol reversed>
<li>three <span class="meta">(default list with <code>reversed</code>)</span></li>
<li>two</li>
<li>one</li>
</ol>
<ol class="polyfill-me" reversed>
<li>three <span class="meta">(list with polyfilled <code>reversed</code>)</span></li>
<li>two</li>
<li>one</li>
</ol>
</div>

<script>
// https://gist.github.com/1671548 b.js by Titani
// use this if you want support for browsers which don't have ES5 goodies
(function () {
	if ( 'reversed' in document.createElement('ol') ) {
		return;
	}

	// tweak to target only one list by Oli:
	// var lists = document.getElementsByTagName( 'ol' ); /* commented out */
	var lists = document.getElementsByClassName( 'polyfill-me' ); /* added */

	for ( var i = 0, len = lists.length; i < len; i++ ) {
		if ( lists[i].getAttribute( 'reversed' ) !== null ) {
			reverseList( lists[i] );
		 }
	}

	function reverseList ( list ) {
		var children = [], childNodes = list.childNodes,
			count = list.getAttribute('start'), i, len;

		for ( i = 0, len = childNodes.length; i < len; i++ ) {
                        //Node.ELEMENT_NODE === 1
			if ( childNodes[i].nodeType === 1 ) {
				children.push( childNodes[i] );
			}
		}

		// check to see if a start attribute is provided
		if ( count !== null ) {
			count = Number( count );

			if ( isNaN(count) ) {
				count = null;
			}
		}

		// no, this isn't duplication - start will be set to null
		// in the previous if statement if an invalid start attribute
		// is provided
		if ( count === null ) {
			count = children.length;
		}

		for ( i = 0, len = children.length; i < len; i++ ) {
			children[ i ].value = count--;
		}
	}
}());
</script>

</div>
<figcaption>Our earlier <code>reversed</code> example using a tweaked version of Titani’s <code>&lt;ol reversed&gt;</code> polyfill</figcaption>
</figure>

<p>You can detect for browser support using Modernizr, via the Community add-on “<a href="https://github.com/Modernizr/Modernizr/blob/master/feature-detects/lists-reversed.js">lists-reversed</a>”. If your polyfill was called <code>reversed.js</code> you could load it using the following code:</p>

<pre><code>yepnope({
  test : Modernizr.olreversed,
  nope : ['reversed.js']
});</code></pre>

<p>The <a href="http://www.modernizr.com/download/#-addtest-lists_reversed-load" title="Modernizr Download Builder">custom Modernizr build for doing this</a> would be:</p>

<ul>
<li>Extra > Modernizr.load</li>
<li>Extensibility > Modernizr.addTest</li>
<li>Community add-ons > lists-reversed</li>
</ul>

<!-- /#browser-support --></section>


<section id="conclusion">
<h2>Conclusion <a class="permalink" href="#conclusion">#</a></h2>

<p>These attributes aren’t ones you’ll use often, but sometimes they’ll be just the ticket. They’ll help you avoid adding list item numbering as part of your content (leading to double numbering if your CSS with <code>list-style-type: none;</code> is disabled), or ugly hacks like <code>height:0;</code> on a bunch of filler <code>&lt;li&gt;</code> elements to get the right start value. Even better, <code>type</code>, <code>start</code>, and <code>value</code> are supported and ready to use now.</p>

<p>As usual, just make sure you are only using them where appropriate:</p>

<ul>
<li>Only use <code>type</code> if the list style for counters is semantic, and the document’s meaning will change if your CSS (containing the equivalent <code>list-style-type</code> values) didn’t load.</li>
<li>For <code>start</code>, consider whether your lists could be combined.</li>
<li>Avoid <code>value</code> if at all possible, as it’s less fragile and error-prone to let the browser number list items for you.</li>
<li>Unfortunately, the current lack of browser support means you’ll need to polyfill <code>reversed</code> if you want to use it for now.</li>
</ul>

<p>So what do <em>you</em> think of these new attributes? Have you needed them in the past? Have you actually <em>used</em> some of them back in the day to rock some old-skool <a href="http://www.w3.org/TR/REC-html32#ol" title="HTML 3.2 Reference Specification">HTML 3.2</a>? Will you use them in the future? Let us know in the comments!</p>


<!-- /#conclusion --></section>

<section id="updates">
<h2>Updates <a class="permalink" href="#updates">#</a></h2>
<ol>
<li><em><time datetime="2012-02-22T11:18:24+13:00">2012-02-22</time></em> I’ve added more browser support information and corrections from the comments. Thanks!</li>
</ol>
<!-- /#updates --></section>
<div id="crp_related"><h3>Related Posts:</h3><ul class="related"><li><a href="http://html5doctor.com/the-output-element/" rel="bookmark" class="crp_title">The output element</a></li><li><a href="http://html5doctor.com/using-modernizr-to-detect-html5-features-and-provide-fallbacks/" rel="bookmark" class="crp_title">Using Modernizr to detect HTML5 features and provide fallbacks</a></li><li><a href="http://html5doctor.com/the-scoped-attribute/" rel="bookmark" class="crp_title">The scoped attribute</a></li><li><a href="http://html5doctor.com/the-contenteditable-attribute/" rel="bookmark" class="crp_title">The contenteditable attribute</a></li><li><a href="http://html5doctor.com/css3-pseudo-classes-and-html5-forms/" rel="bookmark" class="crp_title">CSS3 Pseudo-Classes and HTML5 Forms</a></li></ul></div><p><a href="http://html5doctor.com/ol-element-attributes/" rel="bookmark">The <code>ol</code> Element and Related Attributes: <code>type</code>, <code>start</code>, <code>value</code>, and <code>reversed</code></a> originally appeared on <a href="http://html5doctor.com">HTML5 Doctor</a> on February 21, 2012.</p>
]]></content:encoded>
			<wfw:commentRss>http://html5doctor.com/ol-element-attributes/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>HTML5 Doctor Drop-In Clinic</title>
		<link>http://html5doctor.com/html5-doctor-drop-in-clinic/</link>
		<comments>http://html5doctor.com/html5-doctor-drop-in-clinic/#comments</comments>
		<pubDate>Thu, 16 Feb 2012 14:41:39 +0000</pubDate>
		<dc:creator>Mike Robinson</dc:creator>
				<category><![CDATA[Misc]]></category>
		<category><![CDATA[freenode]]></category>
		<category><![CDATA[HTML 5]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[irc]]></category>
		<category><![CDATA[WHATWG]]></category>

		<guid isPermaLink="false">http://html5doctor.com/?p=4430</guid>
		<description><![CDATA[<p>Got an itch? A problem that's slowing you down? Need someone to answer your question? If email just doesn't quite patch you up, you should stop by the HTML5 Doctor <abbr title="Internet Relay Chat">IRC</abbr> channel.</p>]]></description>
			<content:encoded><![CDATA[<p>Got an itch? A problem that&#8217;s slowing you down? Need someone to answer your question? If email just doesn&#8217;t quite patch you up, you should stop by the HTML5 Doctor <abbr title="Internet Relay Chat">IRC</abbr> channel.</p>
<p>Originally set up by <a href="http://twitter.com/rem">Remy</a>, the <a href="http://en.wikipedia.org/wiki/Internet_Relay_Chat">IRC</a> channel is there for brief questions about all things HTML5. If one of the HTML5 Doctors is around, we can try to help you, or if you don&#8217;t have a question, you&#8217;re more than welcome to idle and talk with the <abbr title="HTML5 Doctor">H5D</abbr> community.</p>
<p>For those who don&#8217;t know what IRC is, it&#8217;s a protocol for chat that&#8217;s been around almost as long as I have! No matter what <abbr title="Operating System">OS</abbr> you use, you should be able to find an IRC client to get connected. There are even web-based services like <a href="http://webchat.freenode.net/?channels=html5doctor">Freenode&#8217;s own web IRC</a> and <a href="http://irccloud.com/">IRC Cloud</a>, so you can jump on no matter where you are with nothing to install. The Mibbit wiki has an <a href="http://wiki.mibbit.com/index.php/IRC_tutorial">IRC tutorial</a> to help get you using IRC, and Freenode hosts a guide to <a href="http://freenode.net/using_the_network.shtml">using the network</a>.</p>
<p>When you&#8217;re ready, the channel can be found at <a href="irc://irc.freenode.net/html5doctor">#html5doctor</a> on <a href="http://freenode.net/">Freenode</a> (irc.freenode.net). Once you&#8217;re connected and you&#8217;ve joined the channel, say hi and see who&#8217;s around. If no one is there, stick around, and maybe check out other channels on Freenode such as the WHATWG channel, <a href="irc://irc.freenode.org/whatwg">#whatwg</a>.</p>
<p>The only thing to keep in mind is that we HTML5 Doctors do this voluntarily with jobs and lives to run. We can&#8217;t be there 24/7. When we are available to answer questions, we&#8217;ll try to address whomever we can, and maybe another idling patient will be able to lend a hand.</p>
<p>For more extensive problems, or if you also don&#8217;t have time to hang around on IRC, check our <a href="http://html5doctor.com/article-archive/">article archive</a> or drop us an email through <a href="http://html5doctor.com/ask-the-doctor/">Ask the HTML5 Doctor</a> if you can&#8217;t find your answer there.</p>
<p>Drop on by, hang out, and feel free to talk all about HTML5 and the wonderful web.</p>
<p>And please, no medical questions!
<div id="crp_related">
<h3>Related Posts:</h3>
<ul class="related">
<li><a href="http://html5doctor.com/2022-or-when-will-html-5-be-ready/" rel="bookmark" class="crp_title">2022, or when will HTML 5 be ready?</a></li>
<li><a href="http://html5doctor.com/dd-details-wrong-again/" rel="bookmark" class="crp_title">dd-details wrong again</a></li>
<li><a href="http://html5doctor.com/your-questions-answered-2/" rel="bookmark" class="crp_title">Your questions answered #2</a></li>
<li><a href="http://html5doctor.com/u-element/" rel="bookmark" class="crp_title">The return of the u element</a></li>
<li><a href="http://html5doctor.com/your-questions-answered-1/" rel="bookmark" class="crp_title">Your questions answered #1</a></li>
</ul>
</div>
<p><a href="http://html5doctor.com/html5-doctor-drop-in-clinic/" rel="bookmark">HTML5 Doctor Drop-In Clinic</a> originally appeared on <a href="http://html5doctor.com">HTML5 Doctor</a> on February 16, 2012.</p>
]]></content:encoded>
			<wfw:commentRss>http://html5doctor.com/html5-doctor-drop-in-clinic/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>It&#8217;s Curtains for Marital Strife Thanks to getUserMedia</title>
		<link>http://html5doctor.com/getusermedia/</link>
		<comments>http://html5doctor.com/getusermedia/#comments</comments>
		<pubDate>Tue, 07 Feb 2012 14:56:03 +0000</pubDate>
		<dc:creator>Bruce Lawson</dc:creator>
				<category><![CDATA[Elements]]></category>
		<category><![CDATA[JavaScript APIs]]></category>
		<category><![CDATA[multimedia]]></category>
		<category><![CDATA[getusermedia]]></category>
		<category><![CDATA[HTML 5]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[video]]></category>
		<category><![CDATA[webrtc]]></category>

		<guid isPermaLink="false">http://html5doctor.com/?p=4335</guid>
		<description><![CDATA[<p>HTML5 (or now, the WebRTC spec) gives us getUserMedia, a way for JavaScript to access streams from a device's camera and microphone. Find out how to use it and normalise the syntax differences between Opera and Chrome with the gUMshield.</p>]]></description>
			<content:encoded><![CDATA[<p>True story: I was tasked by the lovely Mrs Lawson to buy some curtains that match our carpet during the January sales. I dutifully did so — and had to return to the shop straight away because they didn&#8217;t match at all. Mrs Lawson accompanied me, and with a withering glance at her incompetent mate, immediately found some correctly hued fabric, and all was well.</p>

<p>But what&#8217;s a middle-aged colour-blind bloke to do? I had early in the curtain procurement process decided against cutting a hole in the carpet in order that I may take a sample with me. (All other mistakes aside, this was a correct decision.)</p>

<p>So, in order to ensure that I would never again repeat the mistake, I set out to make an app that would allow me to capture the colour of an image straight from my camera. Of course, it had to be a web app rather than a native app, because we&#8217;re web angels, not proprietary devils.</p>

<section id="intro">
  <h2><code>getUserMedia</code> <a href="#intro" class="permalink">#</a></h2>

  <p><a href="http://dev.w3.org/2011/webrtc/editor/getusermedia.html"><code>getUserMedia</code></a> is an API that gives a web page access to a user&#8217;s camera and microphone via JavaScript. It&#8217;s supported in Opera Labs (<a href="http://dev.opera.com/articles/view/labs-more-fun-using-the-web-with-getusermedia-and-native-pages/">latest Android build</a>, <a href="http://dev.opera.com/articles/view/getusermedia-access-camera-privacy-ui/">latest desktop builds</a>) and WebKit in <a href="http://tools.google.com/dlpage/chromesxs?platform=win">Chrome Canary</a> builds (<a href="https://sites.google.com/site/webrtc/running-the-demos">instructions</a>).</p>

  <p>Like many other APIs, it&#8217;s not part of the &#8220;real&#8221; HTML5 spec. It started life as the HTML5 <code>&lt;device&gt;</code> element, then got moved into the W3C as part of the <a href="http://www.w3.org/TR/webrtc/">webRTC</a> specifications. But let&#8217;s not taxonomise when we could be having fun.</p>

  <p>The first thing we need to do when using super-cool new UIs is detect whether it&#8217;s supported:</p>

  <figure>
    <pre><code> if (navigator.getUserMedia) {
  // do something cool
} else {
  // fallback code
}</code></pre>
    <figcaption>Basic usage of <code>getUserMedia</code></figcaption>
  </figure>

  <p>For this article, our &#8220;do something cool&#8221; will be to grab the dominant colour of the current input stream from the camera. As a fallback, we have several options.</p>

  <p>One option, if we&#8217;re using the default Android browser, is to show a form that automatically starts the camera when focussed:</p>

  <figure>
    <pre><code>&lt;form enctype="multipart/form-data" method="post"&gt;
  &lt;input type="file" accept="video/*;capture=camera" /&gt;
&lt;/form&gt;</code></pre>
    <figcaption>Fallback code for Android</figcaption>
  </figure>

  <p>There&#8217;s also the <a href="http://www.w3.org/TR/2011/WD-html-media-capture-20110414/#captureparam"><code>capture</code> attribute</a>, a proposed extension from the <a href="http://www.w3.org/TR/html-media-capture/">W3C Device API Media Capture API</a> that tells a user agent where to get the input data. Android extends the <a href="http://dev.w3.org/html5/spec/states-of-the-type-attribute.html#attr-input-accept"><code>accept</code> attribute</a>. See more in <a href="http://davidbcalhoun.com/2011/android-3-0-honeycomb-is-first-to-implement-the-device-api">David Calhoun&#8217;s Device API article</a>. Alternative capture arguments are <code>camcorder</code> (for video), <code>microphone</code>, and <code>filesystem</code>.</p>

  <p>Browsers that don&#8217;t understand the still-draft Media Capture API will simply ignore the <code>capture</code> attrbute and prompt the user to browse to a file on their file system for uploading.</p>

  <p>Users on iOS are out of luck, as their devices don&#8217;t allow access to the file system.</p>

  <section id="differences-from-media-capture">
    <h3>Differences Between the Media Capture API and <code>getUserMedia</code> <a href="#differences-from-media-capture" class="permalink">#</a></h3>

    <p>Robin Berjon, co-chair of the Device API (DAP) Working Group explains: The markup-only Media Capture API is a simpler, low-hanging-fruit version that can work easily for a lot of use cases. It also has a very simple security model (just a file upload).</p>

    <p>In fact, it works exactly like <code>&lt;input type=file&gt;</code>, except that it knows to allow the user to grab a pic from the camera by default instead of hitting the filesystem. But just like with <code>&lt;input type=file&gt;</code>, once a picture has been taken (i.e., a file selected), you can access it and read from it using the File API, which means you can stuff it in an <code>&lt;img&gt;</code> or a <code>&lt;canvas&gt;</code> and do nasty things to it without annoying any faraway server.</p>

    <p>But of course, if it&#8217;s part of a form and you submit it, it gets submitted just like a regular file upload.</p>

    <p>The thing is, though, it&#8217;s always a snapshot. Even if you use it to take a video (which you can), the page only gets it after you&#8217;ve finished shooting. With <code>getUserMedia</code> (<b>gUM</b>), you get the live stream, which you can modify, record, or stream elsewhere. The gUM approach is more powerful but more complex, and it has more severe security issues.</p>
  </section>
</section>

<section id="api">
  <h2><code>getUserMedia</code> API <a href="#api" class="permalink">#</a></h2>

  <p>Let&#8217;s assume (because we&#8217;re optimists) that your user has a <code>getUserMedia</code>-enabled device. The API is nice and simple, as all Web APIs should be.</p>

  <p><code>navigator.getUserMedia</code> accepts two required arguments and an optional third.</p>

  <p>The first argument tells the device <b>which media you require access to</b>, and it&#8217;s passed as a JavaScript object. So, if you only require access to the microphone, the first argument would be <code>{audio: true}</code>; for video-chatting, you would use <code>{audio: true, video: true}</code>.</p>

  <p>The device decides which camera to use: <q>User agents are encouraged to default to using the user&#8217;s primary or system default camera and/or microphone (as appropriate) to generate the media stream.</q></p>

  <p>A previous version of the specification allowed hints to user agents about which camera to use. The API could specify &#8220;user&#8221; (the front camera on a phone) or &#8220;environment&#8221; (the rear camera on a phone). Debate continues about whether to reinstate this (<a href="http://lists.w3.org/Archives/Public/public-media-capture/2012Jan/0014.html">read the ongoing conversation</a>). One argument against is that letting sites know what cameras a device has could help Dr Malice of Evil Corp. fingerprint users after luring them to his site (which I find to be overly-cautious). <a href="http://lists.w3.org/Archives/Public/public-media-capture/2012Jan/0018.html">Harald Alvestrand poses a conundrum</a>: <q>conferencing units may have a room camera, a document camera and a lectern camera, neither of which is attached to the physical box; which one of these is <q>front</q>?</q></p>

  <p>But let&#8217;s not worry at the moment. Devices with more than one camera generally have a mechanism that allow the user to choose which one is used, so this gives the user control. Note also that the spec says <q>User agents may allow users to use any media source, including pre-recorded media files.</q></p>

  <p>The second argument is the <b>success callback</b>, the function to be executed on success, assuming that the user allows access and the device supports your request.</p>

  <p>There is an optional third argument. This is the <b>failure callback</b>, the function to be executed if something went wrong. It&#8217;s optional, but only optional in the sense that washing your hands before you eat is optional: if you don&#8217;t do it, you leave yourself open to all sorts of bugs and your mum will shout at you.</p>

  <p>Of course, it&#8217;s important to do feature detection before making an API call to ensure that the browser and device are capable, but even if feature detection succeeds, there is still much that can cause failure. For example, the user could deny permission or turn off the camera via a hardware switch, or the device itself could disable the camera.</p>

  <p>So here&#8217;s how we recommend you use the API:</p>

  <figure>
    <pre><code>navigator.getUserMedia({audio: true, video: true}, success, error);

function success(stream) { 
  // ... use 'stream' ... 
} 

function error(){ 
  // display fallback content 
}</code></pre>
    <figcaption>Using the gUM API</figcaption>
  </figure>

  <p>To check whether it&#8217;s working correctly, we can attach the output of the camera&#8217;s stream to the input of an HTML5 video on the page, like this:</p>

  <figure>
    <pre><code>&lt;video autoplay&gt;&lt;/video&gt;
&lt;script&gt;
if (navigator.getUserMedia) {
  navigator.getUserMedia({audio: true, video: true}, success, error);
  function success(stream)
  { 
    // ... use 'stream' ...
    var video = document.getElementsByTagName('video')[0];
    video.src = stream; 
  }
  // ...
&lt;/script&gt;</code></pre>
    <figcaption>Streaming captured video to an HTML5 <code>&lt;video&gt;</code> element</figcaption>
  </figure>

  <section id="differences-between-webkit-and-opera">
    <h3>Differences Between Webkit and Opera <a href="#differences-between-webkit-and-opera" class="permalink">#</a></h3>

    <p>The two rendering engines that implement getUserMedia do so in two different ways. Hopefully, they&#8217;ll harmonise when the features reach the released browsers.</p>

    <p>The differences:</p>

    <ul>
      <li>WebKit uses a prefix — <code>navigator.webkitGetUserMedia</code> — while Opera doesn&#8217;t.</li>
      <li>
        WebKit implements the options according to an old version of the spec, in which audio and video were passed as strings:
        <pre><code>navigator.webkitGetUserMedia("video, audio", /* ... */)</code></pre>
        whereas Opera implements the most recent version of the specification which uses JavaScript objects:
        <pre><code>navigator.getUserMedia({video: true, audio: true}, /* ... */)</code></pre>
      </li>
      <li>
        WebKit attaches the resulting stream like this:
        <pre><code>video.src = window.webkitURL.createObjectURL(stream);</code></pre>
        which is according to the current version of the spec. Opera uses:
        <pre><code>video.src = stream;</code></pre>
        and has proposed simplifying the spec (but discussion continues).
      </li>
    </ul>

    <p>But this fragmentation, even though it&#8217;s only in experimental browser releases is, like, a total drag, man.</p>
  </section>

  <section id="gUM-shield">
    <h3>Introducing The gUM Shield <a href="#gUM-shield" class="permalink">#</a></h3>

    <p>Fortunately, we&#8217;ve got your back. Two of the finest minds I know — actually, two of the finest <em>Mikes</em>, Doctor <a href="http://twitter.com/akamike">Mike Robinson</a> and Opera&#8217;s <a href="http://twitter.com/miketaylr">Mike Taylor</a> — have created a snippet of script that you can copy to shield you from these annoying differences. We&#8217;ve named this <code>getUserMedia</code> syntax normalisation script snippet <a href="https://gist.github.com/f2ac64ed7fc467ccdfe3">The gUM Shield</a>.

    <p>It assumes that there&#8217;s a variable called <var>video</var> to which you&#8217;ve assigned a reference to the <code>&lt;video&gt;</code> element you&#8217;ll stream to. Do this with some mechanism like:</p>

    <pre><code>video = document.getElementById('video');</code></pre>

    <p>Simply <a href="https://gist.github.com/f2ac64ed7fc467ccdfe3">hit the &#8216;Hub</a>, download it, plug it into your script, and <a href="http://jsbin.com/avaxaq/edit#preview">check it out</a>!</p>

    <p>Note that it&#8217;s <em>experimental</em>. Who knows what&#8217;ll happen when Mozilla, Microsoft, and Apple implement it, but please, have a play. Fork it and improve it!</p>
  </section>
</section>

<sectino id="exciting">
  <h2>Doing Exciting Things with the Video Stream <a href="#exciting" class="permalink">#</a></h2>

  <p>So far, we&#8217;re only echoing the video stream. But, as you&#8217;ll know from Tab Atkins&#8217; guest article <a href="http://html5doctor.com/video-canvas-magic/">video + canvas = magic</a>, if we copy the video into a canvas, we can manipulate it:</p>

  <figure>
    <pre><code>var video = document.querySelector('video');
var canvas = document.querySelector('canvas');
var ctx = canvas.getContext('2d');

ctx.drawImage(video, 0, 0, video.width, video.height,
  0, 0, canvas.width, canvas.height);</code></pre>
    <figcaption>Canvas and video magic</figcaption>
  </figure>

  <p>A common mistake is assuming that this somehow establishes a &#8220;live connection&#8221; between the video stream and the canvas. It doesn&#8217;t. It only grabs the current frame. So you need to grab the current frame repeatedly in order to replicate a video. The magical number is 15 times a second (or every 67 milliseconds), but a slower frame rate would probably be okay for this demo:</p>

  <figure>
    <pre><code>setInterval(function () { 
  ctx.drawImage(video, 0, 0, video.width, video.height,
  0, 0, canvas.width, canvas.height);
}, 1000 / 67);</code></pre>
    <figcaption>Live updating of <code>&lt;canvas&gt;</code> from a <code>&lt;video&gt;</code></figcaption>
  </figure>

  <p>See the <a href="http://jsbin.com/ahozok/edit#html,live">working demo</a>.</p>

  <p>What I want to do now is to grab the dominant colour from the canvas. I&#8217;m stealing <a href="http://experimenting.in/exp/real-life-color-picker/">a demo by Shwetank Dixit</a> (who borrowed from <a href="http://www.lokeshdhakar.com/">Lokesh Dhakar</a>&#8216;s <a href="http://www.lokeshdhakar.com/2011/11/03/color-thief/">Color Thief demo</a>). We won&#8217;t look at how it determines the dominant colour (because that&#8217;s nothing to do with getUserMedia).</p>

  <p><a href="http://html5doctor.com/demos/getusermedia/dominantcolor/">Try this in Opera Labs and Chrome Canary</a>!</p>

  <p>Unfortunately, this works splendidly in Opera but it occasionally fails in Chrome, and we&#8217;re not sure why. (We&#8217;ve emailed the Chrome team to ask them.) Apart from the rather anti-climactic end to an article, you shouldn&#8217;t be dismayed by this. <code>getUserMedia</code> is only available in experimental builds that have plenty of work to be done before they hit production.</p>

  <p>Back to our demo. Once you&#8217;ve got the dominant colour, you could prompt the user for a name for that colour (&#8220;carpet&#8221;, for example) and store that in local storage using its name as a key. Then, when you find a pair of curtains in the shop, you can find their dominant colour and easily compare it with that stored against &#8220;carpet&#8221; from earlier.</p>

  <p>And you can return home, confident of delighting the love of your life with your chromatically appropriate choice of soft furnishings. That&#8217;s HTML5: enriching marriages since 2004.</p>

  <img src="http://html5doctor.com/wp-content/uploads/2012/01/getUserMedia1.jpg" alt="woman says &#039;hey daddy-o, the curtains really razz my berries, ya dig?&#039;. Man replies &#039;Baby, I totally dig. Early night?&#039;. A thought bubble shows him thinking &#039;Thank you, getUserMedia&#039;" width="570" height="390" class="aligncenter size-full wp-image-4336" />
</section>

<section id="harshing-your-mellow">
  <h2>Harshing Your Mellow <a href="#harshing-your-mellow" class="permalink">#</a></h2>

  <p>Things need refining before web apps with <code>getUserMedia</code> are on a par with native applications. At the moment, there is no way of controlling which camera is to be used (and no agreement that a developer should be able to). The camera&#8217;s <a href="http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2011-July/032471.html">flash mechanism isn&#8217;t programmatically controllable</a>, which could harm the user experience. Most importantly are the privacy implications of web pages being able to access your camera. Opera has an <a href="http://dev.opera.com/articles/view/getusermedia-access-camera-privacy-ui/">experimental privacy UI</a>, but Chrome has no UI yet.</p>
</section>

<section id="demos">
  <h2>More Demos <a href="#demos" class="permalink">#</a></h2>

  <p>See Paul Neave&#8217;s <a href="http://neave.com/webcam/html5/">HTML5 Webcam Toy</a> and the links at the foot of my <a href="http://dev.opera.com/articles/view/getusermedia-access-camera-privacy-ui/">Opera Labs article</a>.</p>
</section>

<section id="thanks">
  <h2>Thanks <a href="#thanks" class="permalink">#</a></h2>

  <p>Thank for help and code are due to <a href="http://twitter.com/robinberjon">Robin Berjon</a>, <a href="http://twitter.com/shwetank">Shwetank Dixit</a>, <a href="http://twitter.com/ourmaninjapan">Daniel Davis</a>, <a href="http://www.lokeshdhakar.com/">Lokesh Dhakar</a>, <a href="http://twitter.com/miketaylr">Mike Taylor</a>, <a href="http://twitter.com/akamike">Mike Robinson</a>, and <a href="http://twitter.com/richtibbett">Rich Tibbett</a>.</p>
</section>
<section>
<h2>Addy Osmani&#8217;s Polyfill</h2>
<p>Added 13 March 2012: Addy Osmani has published a <a href="https://github.com/addyosmani/getUserMedia.js">getUserMedia polyfill</a> called getUserMedia.js, which uses Flash if gUM isn&#8217;t available. It&#8217;s not ready for production yet, as IE is still being tested. Forkers may hit the &#8216;hub.
</section><div id="crp_related"><h3>Related Posts:</h3><ul class="related"><li><a href="http://html5doctor.com/how-to-get-all-the-browsers-playing-ball/" rel="bookmark" class="crp_title">How to get all the browsers playing ball</a></li><li><a href="http://html5doctor.com/using-modernizr-to-detect-html5-features-and-provide-fallbacks/" rel="bookmark" class="crp_title">Using Modernizr to detect HTML5 features and provide fallbacks</a></li><li><a href="http://html5doctor.com/introducing-web-sql-databases/" rel="bookmark" class="crp_title">Introducing Web SQL Databases</a></li><li><a href="http://html5doctor.com/html5-briefing-notes-journalists-analysts/" rel="bookmark" class="crp_title">HTML5: briefing notes for journalists and analysts</a></li><li><a href="http://html5doctor.com/video-canvas-magic/" rel="bookmark" class="crp_title">video + canvas = magic</a></li></ul></div><p><a href="http://html5doctor.com/getusermedia/" rel="bookmark">It&#8217;s Curtains for Marital Strife Thanks to getUserMedia</a> originally appeared on <a href="http://html5doctor.com">HTML5 Doctor</a> on February 7, 2012.</p>
]]></content:encoded>
			<wfw:commentRss>http://html5doctor.com/getusermedia/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Server-Sent Events</title>
		<link>http://html5doctor.com/server-sent-events/</link>
		<comments>http://html5doctor.com/server-sent-events/#comments</comments>
		<pubDate>Tue, 24 Jan 2012 14:30:33 +0000</pubDate>
		<dc:creator>Remy Sharp</dc:creator>
				<category><![CDATA[Events]]></category>
		<category><![CDATA[JavaScript APIs]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[eventsource]]></category>
		<category><![CDATA[HTML 5]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[realtime]]></category>
		<category><![CDATA[serversentevents]]></category>
		<category><![CDATA[websockets]]></category>

		<guid isPermaLink="false">http://html5doctor.com/?p=4181</guid>
		<description><![CDATA[We've already had a glimpse at Server-Sent Events (also known as EventSource, and I'll switch between the two to keep you on your toes) in my Methods of Communication article from last year. In this article, I want to delve in to more detail about the SSE API, demonstrate its features, and even show you how to polyfill browsers that lack EventSource support.]]></description>
			<content:encoded><![CDATA[<p>We&#8217;ve already had a glimpse at <a href="http://dev.w3.org/html5/eventsource/">Server-Sent Events</a> (also known as EventSource<sup>†</sup>, and I&#8217;ll switch between the two to keep you on your toes) in my <a href="http://html5doctor.com/methods-of-communication/">Methods of Communication</a> article from last year. In this article, I want to delve in to more detail about the SSE API, demonstrate its features, and even show you how to polyfill browsers that lack EventSource support.</p>

<p>Server-Sent Events are real-time events emitted by the server and received by the browser. They&#8217;re similar to WebSockets in that they happen in real time, but they&#8217;re very much a one-way communication method <em>from</em> the server.</p>

<p>These events are similar to ordinary JavaScript events that occur in the browser — like <em>click</em> events — except we can control the name of the event and the data associated with it.</p>

<p>All the code for this article is <a href="https://github.com/remy/eventsource-h5d">available on github</a>, and a <a href="http://node.remysharp.com:8004/">live demo is available online</a>.
<span id="more-4181"></span></p>

<p><small>† Is it Server-Sent Events or EventSource? Well, they both work. Server-Sent Events is the name of the API and specification. EventSource is the name of the JavaScript object you&#8217;re instantiating. It&#8217;s a bit like Ajax and XHR, where XHR refers to the XMLHttpRequest object…kinda.</small></p>

<p><small>Two notes: a) the uptime for this example is, I&#8217;m afraid, usually rather low — good for my server, bad for you. If you test the demo locally it will give you more interesting figures. b) IE6 isn&#8217;t supported in any of this article.</small></p>

<p><section id="applications"></p>

<h2>Possible Applications <a href="#applications" class="permalink">#</a></h2>

<p>A few simple examples of applications that could make use of Server-Sent Events:</p>

<ul>
<li>A real-time chart of streaming stock prices</li>
<li>Real-time news coverage of an important event (posting links, tweets, and images)</li>
<li>A live Twitter wall fed by Twitter&#8217;s streaming API</li>
<li>A monitor for server statistics like uptime, health, and running processes</li>
</ul>

<p>We&#8217;ll use the server monitor for this article&#8217;s examples. If this application were to be used in the wild, we could also check the <code>EventSource</code>&#8216;s connection state to indicate when there&#8217;s a potential problem connecting to the server.</p>

<p></section></p>

<p><section id="api"></p>

<h2>Overview of the API <a href="#api" class="permalink">#</a></h2>

<p>The client-side API is rather simple, and it hands-down beats the insane hacks required to get real-time events to the browser back in the bad old days.</p>

<p>The main points of interest:</p>

<ul>
<li><code>new EventSource(url)</code> — this creates our <code>EventSource</code> object, which immediately starts listening for events on the given URL.</li>
<li><code>readyState</code> — as with XHR, we have a <code>readyState</code> for the <code>EventSource</code> that tells us if we&#8217;re connecting (0), open (1), or closed (2).</li>
<li><code>onopen</code>, <code>onmessage</code> — two events that we can listen for on the new <code>EventSource</code> object. By default, the <code>message</code> event will fire when new messages are received, <em>unless</em> the server explicitly sets the event type.</li>
<li><code>addEventListener</code> — not only can we listen for the default <code>message</code> event, but we can also listen for custom messages using the <code>addEventListener</code> on the <code>EventSource</code> object, just as if we were listening for a <code>click</code> event.</li>
<li><code>event.data</code> — as with most messaging APIs, the contents of the message reside in the <code>data</code> property of the <code>event</code> object. This is a string, so if we want to pass around an object, we need to encode and decode it with JSON.</li>
<li><code>close</code> — closes the connection from the client side.</li>
</ul>

<p>In the future, EventSource will also support <a href="http://www.w3.org/TR/cors/">CORS</a> using an <code>options</code> argument to the <code>EventSource</code> object: <code>{ withCredentials: true }</code>. But at the time of writing, no stable release includes this property.</p>

<p></section></p>

<p><section id="example"></p>

<h2>Simple Example <a href="#example" class="permalink">#</a></h2>

<p>Our simple web app will notify us of server status messages — things like the load average, number of currently connected users, and most CPU-intensive processes. If I were using this application in anger, I&#8217;d probably build server modules that emit specific event types when they cross specific thresholds, so that I&#8217;m only notified when something gets to warning level.</p>

<p>This snippet of JavaScript connects to our server, listens for messages, and handles the data that comes with the messages:</p>

<pre><code>var source = new EventSource('/stats');
source.onopen = function () {
  connectionOpen(true);
};

source.onerror = function () {
  connectionOpen(false);
};

source.addEventListener('connections', updateConnections, false);
source.addEventListener('requests', updateRequests, false);
source.addEventListener('uptime', updateUptime, false);

source.onmessage = function (event) {
  // a message without a type was fired
};
</code></pre>

<p></section></p>

<p><section id="properties"></p>

<h2>Properties of Server-Sent Events <a href="#properties" class="permalink">#</a></h2>

<p>Server-Sent Events are more than just a one-way web socket. They have some unique features:</p>

<ul>
<li>The connection stream is <em>from</em> the server and read-only. This suits lots of applications, some examples of which I listed above.</li>
<li>They use regular HTTP requests for the persistent connection, not a special protocol, which means we can polyfill using vanilla JavaScript.</li>
<li>If the connection drops, the <code>EventSource</code> fires an error event and automatically tries to reconnect. The server can also control the timeout before the client tries to reconnect.</li>
<li>Clients can send a unique ID with messages. When a client tries to reconnect after a dropped connection, it will send the last known ID. Then the server can see that the client missed <em>n</em> messages and send the backlog of missed messages on reconnect.</li>
</ul>

<p></section></p>

<p><section id="message-format"></p>

<h2>Message Format <a href="#message-format" class="permalink">#</a></h2>

<p>A simple message doesn&#8217;t require much:</p>

<pre><code>data: this is a simple message
&lt;blank line&gt;
</code></pre>

<p>Note that the end of a message is indicated by a blank line (obviously not the literal characters <code>&lt;blank line&gt;</code>).</p>

<p>For a message with multiple lines:</p>

<pre><code>data: this is line one
data: and this is line two
</code></pre>

<p>You can send message IDs to be used if the connection is dropped:</p>

<pre><code>id: 33
data: this is line one
data: this is line two
</code></pre>

<p>You can even send multiple messages in a single response so long as you separate the messages by blank lines:</p>

<pre><code>id: 34
data: Remy is awesome

id: 35
data: Bruce is stinky
</code></pre>

<p>And you can specify your own event types (the above messages will all trigger the <code>message</code> event):</p>

<pre><code>id: 36
event: price
data: 103.34

id: 37
event: news
data: Bruce sells his collection of replica bananas
</code></pre>

<p>You don&#8217;t have to worry about this structure on the client side. It only applies to the server, which I&#8217;ll touch on next.</p>

<p></section></p>

<p><section id="server"></p>

<h2>Typical Server <a href="#server" class="permalink">#</a></h2>

<p>I&#8217;m not going to give a full walkthrough of the server-side code, since this is an HTML5 web site :) But there are a few important and simple features that you need to know to build the server (you&#8217;ll need this part anyway if you&#8217;re going to use EventSource).</p>

<p>I&#8217;ve included <a href="https://github.com/remy/eventsource-h5d">all the files for this demo on GitHub</a> for you to peruse at your own leisure, and I&#8217;ve also deployed a <a href="http://node.remysharp.com:8004">live example of this code</a>.</p>

<p>Ideally, you should use a server that has an <a href="http://en.wikipedia.org/wiki/Event_loop">event loop</a>. This means you should <em>not</em> use Apache, but instead use a platform such as <a href="http://nodejs.org">Node.js</a> (which I&#8217;ve used) or <a href="http://twistedmatrix.com/trac/">Twisted</a> for Python.</p>

<p>Key properties:</p>

<ol>
<li>You can only accept EventSource requests if the HTTP request says it can accept the <code>event-stream</code> MIME type.</li>
<li>You need to maintain a list of all the connected users in order to emit new events.</li>
<li>You should listen for dropped connections and remove them from the list of connected users.</li>
<li>You should optionally maintain a history of messages so that reconnecting clients can catch up on missed messages.</li>
</ol>

<p>Here&#8217;s a sample of my Node.js based server.  It&#8217;s using <a href="http://senchalabs.github.com/connect/">Connect</a> (a simple webby framework for Node). When it receives a request for <code>/stats</code>, it calls the following function. I&#8217;ve commented the code so you can follow along:</p>

<pre><code>function stats(request, response) {
  // only response to an event-stream if the request 
  // actually accepts an event-stream
  if (request.headers.accept == 'text/event-stream') {

    // send the header to tell the client that we're going
    // to be streaming content down the connection
    response.writeHead(200, {
      'content-type': 'text/event-stream',
      'cache-control': 'no-cache',
      'connection': 'keep-alive'
    });

    // support the polyfill - we'll come on to this later
    if (request.headers['x-requested-with'] == 'XMLHttpRequest') {
      response.xhr = null;
    }

    // if there was a lastEventId sent in the header, send
    // the history of messages we've already stored up
    if (request.headers['last-event-id']) {
      var id = parseInt(request.headers['last-event-id']);
      for (var i = 0; i &lt; history.length; i++) {
        if (history[i].id &gt;= id) {
          sendSSE(response, history[i].id, history[i].event, history[i].message);
        }
      }
    } else {
      // if the client didn't send a lastEventId, it's the
      // first time they've come to our service, so send an
      // initial empty message with no id - this will reset
      // their id counter too.
      response.write('id\n\n');
    }

    // cache their connection - the response is where we write
    // to send messages
    connections.push(response);

    // send a broadcast message to all connected clients with
    // the total number of connections we have.
    broadcast('connections', connections.length);

    // if the connection closes to the client, remove them
    // from the connections array.
    request.on('close', function () {
      removeConnection(response);
    });
  } else {
    // if the client doesn't accept event-stream mime type,
    // send them the regular index.html page - you could do
    // anything here, including sending the client an error.
    response.writeHead(302, { location: "/index.html" });
    response.end();
  }
}
</code></pre>

<p>The important trick on the server is to ensure you <em>don&#8217;t</em> close the connection to the <code>EventSource</code> object. If you do, it will of course handle the closed connection, fire an error event, and try to reconnect. So you&#8217;ll just want to maintain the persistent connection.</p>

<p></section></p>

<p><section id="polyfills"></p>

<h2>Polyfills and Tweaks to the Server <a href="#polyfills" class="permalink">#</a></h2>

<p>There are two good polyfills I know of, and though I prefer the one I wrote, I&#8217;ll still lay them both out for you.</p>

<p><section id="yaffle"></p>

<h3>Yaffle&#8217;s Polyfill <a href="#yaffle" class="permalink">#</a></h3>

<p>The first is one by <a href="https://github.com/Yaffle">Yaffle</a> (on github), available on <a href="https://github.com/Yaffle/EventSource">github/Yaffle/eventsource</a>. </p>

<p>The cons:</p>

<ul>
<li>It doesn&#8217;t send the <code>accepts</code> header, and</li>
<li>It completely replaces the <code>EventSource</code> object, so even if your browser supports <code>EventSource</code> natively, this script will replace it. But there&#8217;s a good reason for that.</li>
</ul>

<p>The pros:</p>

<ul>
<li>It maintains a persistent connection (whereas the one we&#8217;re using doesn&#8217;t), and</li>
<li>More interestingly, it supports CORS (which I imagine is why it replaces the native <code>EventSource</code>).</li>
</ul>

<p>These two pros are quite compelling. But when I was testing, I couldn&#8217;t get it working in IE7 (which was my minimum browser target), so that might be a blocker for you…or not.</p>

<p></section></p>

<p><section id="remy"></p>

<h3>Remy&#8217;s Polyfill <a href="#remy" class="permalink">#</a></h3>

<p>The second is my own, available on <a href="https://github.com/remy/polyfills/blob/master/EventSource.js">github.com/remy/polyfills</a>.</p>

<p>The cons:</p>

<ul>
<li>It uses polling, so once a small group of messages come down, it re-establishes the connection, which could lead to significant overhead (though less so on a Node-based server). You have to add about 4 extra lines to your server code.</li>
</ul>

<p>The pros:</p>

<ul>
<li>It doesn&#8217;t replace the native <code>EventSource</code> object (but that also implies that, for now, it won&#8217;t support CORS), and</li>
<li>It supports IE7.</li>
</ul>

<p><small>Retrospectively, I might choose Yaffle&#8217;s polyfill over mine in the future if I wasn&#8217;t bothered about IE7 support.</small></p>

<p></section></p>

<p><section id="using-the-polyfill"></p>

<h3>Using the Polyfill <a href="#using-the-polyfill" class="permalink">#</a></h3>

<p>By including the <code>EventSource.js</code> JavaScript library before my client-side code, I just need a couple of small changes to my server-side code. Other than that, everything on the client side works without any changes (as a polyfill <em>should</em> work).</p>

<p>When posting the server&#8217;s reply to the client, instead of keeping the connection open, I include the following in my server when it&#8217;s finished writing the response:</p>

<pre><code>// send the data (event type, id, message, etc)
response.write(data);

// if our response contains our custom xhr property, then...
if (response.hasOwnProperty('xhr')) {
  // clear any previous timers using the xhr prop as the value
  clearTimeout(response.xhr);

  // now set a timer for 1/4 second (abritrary number) that
  // then closes the connection and removes itself from the
  // connection array.
  // The delay is in place so that a burst of messages can 
  // go out on the same connection *before* it's closed.
  response.xhr = setTimeout(function () {
    response.end();
    removeConnection(response);
  }, 250);
}
</code></pre>

<p></section>
</section></p>

<p><section id="bugs"></p>

<h2>Bugs? <a href="#bugs" class="permalink">#</a></h2>

<p>The <code>error</code> event should always fire when the <code>readyState</code> changes, assuming you didn&#8217;t explicitly call the <code>close</code> method. This works nearly all the time, but in writing this article, I found a few edge cases where it doesn&#8217;t fire. In Chrome, if I put my machine to sleep and then woke it back up, it would close the connection but not fire the event, therefore never triggering a reconnection. As I said, this is an edge case and I&#8217;ll file a bug against it, so I don&#8217;t expect it to hang around for long.</p>

<p></section></p>

<p><section id="why-not-websockets"></p>

<h2>Why Not Use WebSockets? <a href="#why-not-websockets" class="permalink">#</a></h2>

<p>There are two reasons I&#8217;d advocate using EventSource over WebSockets, as they&#8217;re currently the two contenders for sending real-time events to the browser.</p>

<p>The first is that EventSource (as we saw earlier) works over regular HTTP and can therefore be replicated entirely using JavaScript if it&#8217;s not available natively. That means that we can polyfill browsers without support, like IE9.</p>

<p>The second is probably more important: you should always use the right technology for the job. If your real-time data is sourced from your web site, <em>and</em> the user doesn&#8217;t interact in real-time, it&#8217;s likely you need Server-Sent Events. </p>

<p>I recently saw a cool <a href="http://paynedigital.com/2011/12/nodeflakes">demo of snowflakes</a> drifting down a web site. Each snowflake is a tweet based around the Christmas theme — like if someone mentions a particular Christmas-y term, it&#8217;s sucked in to the snowflake. Don&#8217;t get me wrong, I know this is a demo, and it&#8217;s very cool (if you wrote it, this is me sending you hugs), but it&#8217;s based on WebSockets. I&#8217;d suggest this demo should be based on EventSource since all the data is read-only and the user doesn&#8217;t interact with it at all.</p>

<p>The point: evaluate the technology against your problem, and aim to get good fit.</p>

<p></section>
<div id="crp_related"><h3>Related Posts:</h3><ul class="related"><li><a href="http://html5doctor.com/methods-of-communication/" rel="bookmark" class="crp_title">Methods of communication</a></li><li><a href="http://html5doctor.com/storing-data-the-simple-html5-way-and-a-few-tricks-you-might-not-have-known/" rel="bookmark" class="crp_title">Storing Data the Simple HTML5 Way (and a few tricks you might not have known)</a></li><li><a href="http://html5doctor.com/drag-and-drop-to-server/" rel="bookmark" class="crp_title">Drag and Drop and Automatically Send to the Server</a></li><li><a href="http://html5doctor.com/history-api/" rel="bookmark" class="crp_title">Pushing and Popping with the History API</a></li><li><a href="http://html5doctor.com/how-to-get-all-the-browsers-playing-ball/" rel="bookmark" class="crp_title">How to get all the browsers playing ball</a></li></ul></div></p>
<p><a href="http://html5doctor.com/server-sent-events/" rel="bookmark">Server-Sent Events</a> originally appeared on <a href="http://html5doctor.com">HTML5 Doctor</a> on January 24, 2012.</p>
]]></content:encoded>
			<wfw:commentRss>http://html5doctor.com/server-sent-events/feed/</wfw:commentRss>
		<slash:comments>26</slash:comments>
		</item>
	</channel>
</rss>

