Rounding Rough Edges

On the Web, everything is a rectangle by default. Form fields, tables,
and even sections of web pages all have a blocky, sharp-edged look, so
many designers have turned to different techniques over the years to
add rounded corners to these elements to soften up the interface a bit.
CSS3 has support for easily rounding corners, and Firefox and Safari
have supported this for quite a long time. Unfortunately, Internet Explorer
hasn’t jumped on board yet. But we can get around that simply
enough.

Softening Up a Login Form

The wireframes and mock-ups you received for your current project
show form fields with rounded corners. Let’s round those corners using
only CSS3 first. Our goal is to create something that looks like Figure
8.1, on the next page.
For the login form, we’ll use some very simple HTML.

< f o rm a c t i o n = ” / l o g i n ” method=”post”>
< f i e l d s e t i d = ” l o g i n ” >
<legend>Log i n < / l e g e n d>
< o l >
< l i >
< l a b e l for=”emai 1 “>Emai l < / l a b e l >
< i n p u t i d = ” e m a i l ” t y p e = ” e m a i l ” name=”emai1″>
</li>
< l i >
< l a b e l f o r = ” p a s s w o r d ” > P a s s w o r d < / l a b e l>
< i n p u t i d = ” p a s s w o r d ” type=”password”
name=”password” v a l u e = ” ” a u t o c o m p l e t e = ” o f f ” / >
</li>
< l i x i n p u t t y p e = ” s u b m i t ” value=”Log i n ” x / l i >
</ol >
< / f i e l d s e t >
< / f o r m >

We’ll style the form a bit to give It a slightly better look.

f i e l d s e t {
w i d t h : 216px;
b o r d e r : none;
b a c k g r o u n d – c o l o r : #ddd;
}
f i e l d s e t legend{
b a c k g r o u n d – c o l o r : #ddd;
p a d d i n g : 0 64px 0 2px;
}
f i e l d s e t > o l { l i s t – s t y l e : none;
p a d d i n g : 0 ;
m a r g i n : 2px;
}
f i e l d s e t > o l > l i {
m a r g i n : 0 0 9px 0;
p a d d i n g : 0;
}
/ * Make i n p u t s go to t h e i r own l i n e */
f i e l d s e t i n p u t {
d i s p l a y : b l o c k ;
}

i n p u t {
w i d t h : 200px;
b a c k g r o u n d – c o l o r : #fff;
b o r d e r : lpx s o l i d #bbb;
i n p u t [ t y p e = ” s u b m i t ” ] {
w i d t h : 202px;
p a d d i n g : 0;
b a c k g r o u n d – c o l o r : #bbb;
}

These basic styles remove the bullets from the list and ensure that the
input fields are all the same size. With that in place, we can apply the
rounding effects to our elements.

Browser-Specific Selectors

Since the CSS3 specification isn’t final, browser makers have added
some features themselves and have decided to prefix their own implementations.
These prefixes let browser makers introduce features early
before they become part of a final specification, and since they don’t
follow the actual specification, the browser makers can implement the
actual specification while keeping their own implementation as well.
Most of the time, the vendor-prefixed version matches the CSS specification,
but occasionally you’ll encounter differences. Unfortunately for
you, that means you’ll need to declare the border radius once for each
type of browser.
Firefox uses this selector:

– m o z – b o r d e r – r a d i u s : 5px;

WebKit-based browsers, such as Safari and Chrome, use this selector:

– w e b k i t – b o r d e r – r a d i u s : 5px;

To round all the input fields on our form, we need a CSS rule like this:

i n p u t , f i e l d s e t , legend{
b o r d e r – r a d i u s : 5px;
– m o z – b o r d e r – r a d i u s : 5px;
– w e b k i t – b o r d e r – r a d i u s : 5px;

Add that to your style.ess file, and you have rounded corners.

Falling Back

You have everything working in Firefox, Safari, and Google Chrome, but
you know it doesn’t work in Internet Explorer and you know it needs to,
so you’ll need to implement something that gets it as close as possible.
Web developers have been rounding corners for a while now using background
images and other techniques, but we’re going to keep it as simple
as possible. We can detect corner radius with JavaScript and round
the corners using any number of rounding techniques. For this example,
we’ll use j Query, the j Query Corner plug-in, and a modification of
the Corner plug-in that rounds text fields.

Detecting Rounded Corners Support

Our fallback solution looks very much like the one we used in Section 9,
Falling Back, on page 91. We’ll include the jQuery library and the plugin,
we’ll detect whether the browser supports our attribute, and if it
doesn’t, we’ll activate the plug-in. In this case, we need to detect the
presence of the border-radius CSS property, but we also need to check
for browser-specific prefixes such as webkit and moz.
Create corner.js, and add this function:

function h a s B o r d e r R a d i u s O {
var element = document.documentElement;
var s t y l e = e l e m e n t . s t y l e ;
if ( s t y l e ) {
return t y p e o f s t y l e . b o r d e r R a d i u s == “string” ||
t y p e o f s t y l e . M o z B o r d e r R a d i u s == “string” ||
t y p e o f s t y l e . W e b k i t B o r d e r R a d i u s == “string” ||
t y p e o f s t y l e . K h t m l B o r d e r R a d i u s == “string”;
}
return null;

We can now detect whether our browser is missing support for rounded
corners, so let’s write the code to do the actual rounding. Thankfully,
there’s a plug-in that can get us started.

jQuery Corners

jQuery Corners2 is a small plug-in that rounds corners by wrapping
elements with additional div tags and styling them so that the targetelement looks rounded. It doesn’t work for form fields; however, with a
little imagination, we can use this plug-in and a little bit of j Query to
make it work.

First, grab jQuery Corners, and link to it from your HTML page. While
there, also link up your corner.js file.

<script src=”jquery.corner.js” charset=”utf-8″ type=’text/javascript’></script>
<script src=”corner.js” charset=”utf-8″ type=’text/javascript’></script>

 

Now we just have to write the code that actually invokes the rounding.

Our formCorners Plug-in

We’re going to write a jQuery plug-in so that we can easily apply this
rounding to all of the form fields. We already talked about writing
jQuery plug-ins in Section 5, Falling Back, on page 60, so I don’t need
to cover that again. Instead, I’ll just walk you through the code for this
plug-in, which is based in part on a solution by Tony Amoyal.

Add this to your corners.js file:

(function«) {
$ . f n . f o r m C o r n e r = function(){
return this.each(function() {
var i n p u t = $(this);
var input_background = input.css(“background-color”);
var i n p u t _ b o r d e r = input.cssC’border-color”);
i n p u t . e s s ( ” b o r d e r ” , “none”) ;
var wrap_width = p a r s e l n t ( i n p u t . c s s ( ” w i d t h ” ) ) + 4;
var wrapper = i nput .wrap( “<divx/div>”) . p a r e n t O ;
var border = wrapper .wrapC “<divx/div>”) . p a r e n t O ;
wrapper.ess C’background-col or”, i nput_background)
.essC’padding”, “lpx”) ;
b o r d e r . ess C’backg round-col or” , i n p u t _ b o r d e r )
.essC”width”, wrap_width + ” p x ” )
. c s s ( ‘padding’, ‘lpx’);
wrapper.cornerC”round 5px”);
b o r d e r . c o r n e r C”round 5px”) ;
} ) ;
} ;
}) CjQuery) ;

We’re taking a jQuery object that could be an element or a collection of
elements, and we’re wrapping it with two div tags that we then round.
We first make the innermost div the same color as the background of the
original input, and we turn off the border of the actual form field. Then
we wrap that field with another field with its own background color,
which is the color of the original input’s border color, and give it a little
bit of padding. This padding is what makes the border’s outline visible.
Imagine two pieces of construction paper—a green one that’s 4 inches
wide and the other a red one that’s 3 inches wide. When you place the
smaller one atop the larger one, you’ll see a green border around the
red one. That’s how this works.

Invoking the Rounding

With the plug-in and our detection library in place, we can now invoke
the rounding.

Add this to the corners.js file:

$(function O {
i f ( ! h a s B o r d e r R a d i u s ( ) ) {
$(“input”).formCornerO;
SC’fi eldset”) . corner Ç” round 5px”) ;
$(“legend”).corner(“round top 5px c c : # f f f ” );
} ) ;}

We’re rounding the three form fields and the fieldset, and finally, on
line 5, we’re rounding only the top part of the legend and specifying
that the cutout of the corner should use white. The plug-in uses the
background color of the parent for its cutaway color, and that’s not
appropriate here.

If the browser has support for the border-radius property, then it runs
our plug-in. If not, then it’ll use the CSS we added earlier.

A Minor Nudge

IE treats legends a little differently. We can add in a small style fix for
IE that pushes the fieldset’s legend up a bit so that it looks the same
as it does in Firefox and Chrome.

< l i n k r e l = ” s t y l e s h e e t ” h r e f = ” s t y l e . e s s ” t y p e = ” t e x t / c s s ” media=”screen”>
<! — [ i f I E ] >
< s t y l e >
f i e l d s e t 1 e g e n d { m a r g i n – t o p : -lOpx }
< / s t y l e >
< ! [ e n d i f ] – – >

Now things look relatively similar on all of the major browsers; you can
see the Internet Explorer version in Figure 8.2, on the preceding page.
Rounded corners add a bit of softness to your interfaces, and it is extremely
easy to use. That said, it’s important to be consistent with your
use and to not overuse this technique, just like any other aspect of
design.

 

 

Embedding Audio and Video

Audio and video are such an Important part of the modern Internet.
Podcasts, audio previews, and even how-to videos are everywhere, and
until now, they’ve only been truly usable using browser plug-ins.
HTML5 introduces new methods to embed audio and video files into
a page. In this chapter, we’ll explore a few methods we can use to not
only embed the audio and video content but also to ensure that it is
available to people using older browsers.

We’ll discuss the following two elements in this chapter

<audio> [<audio src=”drums.mp3″x/audio>]
Play audio natively in the browser. [C4, F3.6, IE9, S3.2, OlO.l,
IOS3, A2]
<video> [<video src=”tutorial.m4v”x/video>]
Play video natively in the browser. [C4, F3.6, IE9, S3.2, 010.5,
IOS3, A21

Before we do that, we need to talk about the history of audio and video
on the Web. After all, to understand where we’re going, we have to
understand where we’ve been.

A Bit of History

People have been trying to use audio and video on web pages for a long
time. It started with people embedding MIDI files on their home pages
and using the embed tag to reference the file, like this:

<embed src=”awesome.mp3″ a u t o s t a r t = ” t r u e ”
1oop=”true” control 1er=”true”></embed>

The embed tag never became a standard, so people started using the
object tag instead, which is an accepted W3C standard. To support
older browsers that don’t understand the object tag, you often see an
embed tag nested within the object tag, like this:

<object>
<param name=”src” va”lue=”simpsons.mp3″>
<param name=”autoplay” value=”false”>
<param name=”contro”ner” value=”true”>
<embed src=”awesome.mp3″ a u t o s t a r t = ” f a 7 s e ”
1 oop=”false” control 1 er=”true”></embed>
</object>

Not every browser could stream the content this way, though, and not
every server was configured properly to serve it correctly. Things got
even more complicated when video on the Web became more popular.
We went through lots of iterations of audio and video content on
the Web, from RealPlayer to Windows Media to QuickTime. Every company
had a video strategy, and it seemed like every site used a different
method and format for encoding their video on the Web.

Macromedia (now Adobe) realized early on that its Flash Player could
be the perfect vehicle for delivering audio and video content across platforms.
Flash is available on close to 97 percent of web browsers already.
Once content producers discovered they could encode once and play
anywhere, thousands of sites turned to Flash streaming for both audio
and video.

Then Apple came along in 2007 with the iPhone and iPod touch and
decided that Apple would not support Flash on those devices. Content
providers responded by making video streams available that would play
right in the Mobile Safari browser. These videos, using the H.264 codec,
were also playable via the normal Flash Player, which allowed content
providers to still encode once while targeting multiple platforms.

The creators of the HTML5 specification believe that the browser should
support audio and video natively rather than relying on a plug-in thatrequires a lot of boilerplate HTML. This is where HTML5 audio and
video start to make more sense: by treating audio and video as firstclass
citizens in terms of web content.

Containers and Codecs

When we talk about video on the Web, we talk in terms of containers
and codecs. You might think of a video you get off your digital camera as
an AVI or an MPEG file, but that’s actually an oversimplification. Containers
are like an envelope that contains audio streams, video streams,
and sometimes additional metadata such as subtitles. These audio and
video streams need to be encoded, and that’s where codecs come in.
Video and audio can be encoded in hundreds of different ways, but
when it comes to HTML5 video, only a few matter.

Video Codecs

When you watch a video, your video player has to decode it. Unfortunately,
the player you’re using might not be able to decode the video you
want to watch. Some players use software to decode video, which can
be slower or more CPU intensive. Other players use hardware decoders
and are thus limited to what they can play. Right now, there are three
video formats that you need to know about if you want to start using
the HTML5 video tag in your work today: H.264, Theora, and VP8.

Codec and Supported Browsers

H.264
[IE9, S4, C3, IOS]
Theora
[F3.5, C4, 010]
VP8
[IE9 (if codec installed), F4, C5, 010.7]

H.264

H.264 is a high-quality codec that was standardized in 2003 and created
by the MPEG group. To support low-end devices such as mobile
phones, while at the same time handling video for high-definition devices,
the H.264 specification is split into various profiles. These profiles
share a set of common features, but higher-end profiles offer additional
options that improve quality. For example, the iPhone and Flash Player
can both play videos encoded with H.264, but the iPhone only supports
the lower-quality “baseline” profile, while Flash Player supports
higher-quality streams. It’s possible to encode a video one time and
embed multiple profiles so that it looks nice on various platforms.
H.264 is a de facto standard because of support from Microsoft and
Apple, which are licensees. On top of that, Google’s YouTube converted
its videos to the H.264 codec so it could play on the iPhone, and Adobe’s
Flash Player supports it as well. However, it’s not an open technology. It
is patented, and its use is subject to licensing terms. Content producers
must pay a royalty to encode videos using H.264, but these royalties do
not apply to content that is made freely available to end users.2
Proponents of free software are concerned that eventually, the rights
holders may begin demanding high royalties from content producers.
That concern has led to the creation and promotion of alternative
codecs.

Theora

Theora is a royalty-free codec developed by the Xiph.Org Foundation.
Although content producers can create videos of similar quality with
Theora, device manufacturers have been slow to adopt it. Firefox,Chrome, and Opera can play videos encoded with Theora on any platform
without additional software, but Internet Explorer, Safari, and
the iOS devices will not. Apple and Microsoft are wary of “submarine
patents,” a term used to describe patents in which the patent application
purposely delays the publication and issuance of the patent in
order to lay low while others implement the technology. When the time
is right, the patent applicant “emerges” and begins demanding royalties
on an unsuspecting market.

VP8

Google’s VP8 is a completely open, royalty-free codec with quality similar
to H.264. It is supported by Mozilla, Google Chrome, and Opera,
and Microsoft’s Internet Explorer 9 promises to support VP8 as long as
the user has installed a codec already. It’s also supported in Adobe’s
Flash Player, making it an interesting alternative. It is not supported in
Safari or the iOS devices, which means that although this codec is free
to use, content producers wanting to deliver video content to iPhones
or iPads still need to use the H.264 codec.

Audio Codecs

As if competing standards for video weren’t complicating matters
enough, we also have to be concerned with competing standards for
audio.

Codec and Supported Browsers

AAC
[S4, C3, IOS]
MP3
[IE9, S4, C3, IOS]
Vorbis (OGG)
[F3, C4, 010]

Advanced Audio Coding (AAC)

This is the audio format that Apple uses in its iTunes Store. It is designed
to have better audio quality than MP3s for around the same file
size, and it also offers multiple audio profiles similar to H.264. Also,
like H.264, it’s not a free codec and does have associated licensing fees.
All Apple products play AAC files. So does Adobe’s Flash Player and the
open source VLC player.

Vorbis (OGG)

This open source royalty-free format is supported by Firefox, Opera,
and Chrome. You’ll find it used with the Theora and VP8 video codecs
as well. Vorbis files have very good audio quality but are not widely
supported by hardware music players.

MP3s

The MP3 format, although extremely common and popular, isn’t supported
in Firefox and Opera because it’s also patent-encumbered. It is
supported in Safari and Google Chrome.
Video codecs and audio codecs need to be packaged together for distribution
and playback. Let’s talk about video containers.

Containers and Codecs, Working Together

A container is a metadata file that identifies and interleaves audio or
video files. A container doesn’t actually contain any information about
how the information it contains is encoded. Essentially, a container
“wraps” audio and video streams. Containers can often hold any combination
of encoded media, but we’ll see these combinations when it
comes to working with video on the Web

• The OGG container, with Theora video and Vorbis audio, which
will work in Firefox, Chrome, and Opera.
• The MP4 container, with H.264 video and AAC audio, which will
work in Safari and Chrome. It will also play through Adobe Flash
Player and on iPhones, iPods, and iPads.
• The WebM container, using VP8 video and Vorbis audio, which will
work in Firefox, Chrome, Opera, and Adobe Flash Player.

Given that Google and Mozilla are moving ahead with VP8 and WebM,
we can eliminate Theora from the mix eventually, but from the looks of
things, we’re still looking at encoding our videos twice—once for Apple
users (who have a small desktop share but a large mobile device share
in the United States) and then again for Firefox and Opera users, since
both of those browsers refuse to play H.264.3
That’s a lot to take in, but now that you understand the history and the
limitations, let’s dig in to some actual implementation, starting with
audio.

 

 

Graphing Statistics with RGraph

AwesomeCo is doing a lot of work on the website, and senior management
would like to see a graph of the web stats. The back-end programmers
will be able to get the data in real time, but first they’d like
to see whether you can come up with a way to display the graph in the
browser, so they’ve provided you with some test data. Our goal is to
transform that test data into something that resembles Figure 6.2, on
the following page.

There are lots of ways to draw graphs on a web page. Developers use
Flash for graphs all the time, but that has the limitation of not working
on some mobile devices like the iPad or iPhone. There are server-side
solutions that work well, but those might be too processor-intensive if
you’re working with real-time data. A standards-based client-side solution
like the canvas is a great option as long as we’re careful to ensure it
works in older browsers. You’ve already seen how to draw squares, but
drawing something complex requires a lot more JavaScript. We need a
graphing library to help us along.

The fact that HTML5 isn’t available everywhere yet hasn’t stopped the
developers of the RGraph library.5 RGraph makes it ridiculously simple
to draw graphs using the HTML5 canvas. It’s a pure JavaScript solution,
though, so it won’t work for those user agents that don’t have
JavaScript available, but then again, neither will the canvas. Here’s the
code for a very simple bar graph:

<canvas width=”500″ height=”250″ id=”test”>[no canvas support]</canvas>
<script type=”text/javascript” charset=”utf-8″>
var bar = new RGraph.BarC’test’, [50,25,15,10]);
bar.SetC’chart.gutter’, 50);
bar.Set(‘chart.colors’, [‘red’]) ;
bar.SetC’chart.title’, “A bar graph of my favorite pies”);
bar.SetC’chart.labels’, [“Banana Creme”, “Pumpkin”, “Apple”, “Cherry”]);
bar.DrawC) ;
</script>

A client-side bar graphAll we have to do is create a couple of JavaScript arrays, and the library
draws the graph on the canvas for us.

Describing Data with HTML

We could hard-code the values for the browser statistics in the Java-
Script code, but then only users with JavaScript would be able to see
the values. Instead, let’s put the data right on the page as text. We can
read the data with JavaScript and feed it to the graphing library later.

<div id=”graph_data”>
<hl>Browser share for this site</hl>
<ul>
<li>
<p data-name=”Safari 4″ data-percent=”15″>
Safari 4 – 15%
</p>
</li>
<li>
<p data-name=”Internet Explorer” data-percent=”55″>
Internet Explorer – 55%
</p>
</li>
<li>
<p data-name=”Firefox” data-percent=”14″>
Firefox – 14%
</p>
</li>

<li>
<p data-name=”Google Chrome” data-percent=”16″>
Google Chrome – 16%
</p>
</li>
</ul>
</div>

We’re using the HTML5 data attributes to store the browser names and
the percentages. Although we have that information in the text, it’s
so much easier to work with programmatically since we won’t have to
parse strings.
If you open up the page in your browser or just look at Figure 6.3,
you’ll see that the graph data is nicely displayed and readable even
without the graph. This will be your fallback content for mobile devices
and other users where either the canvas element or JavaScript is not
available.
Now, let’s turn this markup into a graph.

Turning Our HTML into a Bar Graph

We’re going to use a bar graph, so we’ll need to require both the RGraph
Bar graph library as well as the main RGraph library. We’ll also use
j Query to grab the data out of the document. In the head section of the
HTML page, we need to load the libraries we need.

<script type=”text/javascript”
charset= “utf-8″
src=”http://ajax.googleapis.com/ajax/1ibs/jquery/1.4.2/jquery.min.js”>
</scri pt>
<script src=”javascri pts/RCraph. common, js” ></script>
<script src=”javascripts/RCraph.bar.js” ></script>

To build the graph, we need to grab the graph’s title, the labels, and
the data from the HTML document and pass it to the RGraph library.
RGraph takes in arrays for both the labels and the data. We can use
j Query to quickly build those arrays.

Une l function canvasGraph(){
var title = $(‘#graph_data hi’) .textO ;
var labels = $C”#graph_data>ul>li>p[data-name]”).map(function(){
5 return $(this),attr(“data-name”);
} ) ;
var percents = $C”#graph_data>ul>li>p[data-percent]”).map(function(){
return parselnt($(this).attr(“data-percent”)) ;
io });
var bar = new RGraph.Bar(‘browsers’, percents);
bar.SetC ‘chart.gutter’ , 50);
bar.Set(‘chart.colors’, [ ‘red’]) ;
15 bar. Set C ‘chart, title’ , title);
bar.Set( ‘chart.labels ‘ , labels);
bar.DrawO ;
}

First, on line 2, we grab the text for the header. Then, on line 4, we select
all the elements that have the data-name attribute. We use jQuery’s map
function to turn the values from those elements into an array.
We use that same logic again on line 8 to grab an array of the percentages.
With the data collected, RGraph has no trouble drawing our graph.

Displaying Alternative Content

In Section 14, Describing Data with HTML, on page 120, I could have
placed the graph between the starting and ending canvas tags. This would hide these elements on browsers that support the canvas while
displaying them to browsers that don’t. However, the content would
still be hidden if the user’s browser supports the canvas element but
the user has disabled JavaScript.

We simply leave the data outside the canvas and then hide it with
jQuery once we’ve checked that the canvas exists.

var canvas = document.getElementByld(‘browsers’);
if (canvas.getContext){
$C’#graph_data’) .hideO ;
canvasGraphO ;
}

Falling Back

When building this solution, we already covered fallbacks for accessibility
and lack of JavaScript, but we can create an alternative graph for
people who don’t have canvas support but can use JavaScript.
There are a ton of graphing libraries out there, but each one has its
own way of grabbing data. Bar graphs are just rectangles with specific
heights, and we have all the data on the page we need to construct this
graph by hand.

Line l function divGraph(barColor, textColor, width, spacer, lblHeight){
$(‘#graph_data ul’).hide();
var container = $C’#graph_data”) ;
5 container.css( {
“display” : “block”,
“position” : “relative”,
“height”: “300px”}
);
$ C”#graph_data>ul>li>p”).each(function(i){
var bar = $(“<div>” + $(this) .attrC’data-percent”) + “%</div>”) ;
var label = $(“<div>” + $(this) ,attr(“data-name”) + “</ch’v>”);
var commonCSS = {
“width”: width + “px”,
“position” : “absolute”,
“left” : i * (width + spacer) + “px”};
var barCSS = {
“background-color” : barColor,
“color” : textColor,
“bottom” : lblHeight + “px”,
25 “height” : $(this) .attr(“data-percent”) + “%”
};
var labelCSS = {“bottom” : “0”, “text-align” : “center”};
bar.cssC $.extend(barCSS, commonCSS) );
30 label.css( $. extend (label CSS, commonCSS) );
container.append(bar);
container.append(label);
});
}

On line 2, we hide the unordered list so that the text values are hidden.
We then grab the element containing the graph data and apply some
basic CSS styles. We set the positioning of the element to relative on 6,
which will let us absolutely position our bar graphs and labels within
this container.
Then we loop over the paragraphs in the bulleted list (line 11) and create
the bars. Each iteration over the labels creates two div elements, one for
the bar itself and another for the label, which we position below it. So,
with just a little bit of math and some j Query, we are able to re-create

Our graph now displays

the graph. Although it doesn’t look exactly the same, it’s close enough
to prove the concept.
We then just need to hook it into our canvas detection, like this:

if (canvas.getContext){
S(‘#graph_data’).h i de();
canvasGraphO;
}
else{
divGraph(“#f 00”, “#fff”, 140, 10, 20);
}

You can see the fallback version in Figure 6.4. With a combination
of JavaScript, HTML, and CSS, we’ve provided a client-side bar graph
and statistical information about browser usage to any platform that
requires it. Using the canvas has an additional benefit—it got us to
start thinking about a fallback solution from the beginning, rather than
trying to wedge something in later. That’s really good for accessibility.
This is one of the most accessible and versatile methods of graphing
data available. You can easily create the visual representation as well
as a text-based alternative. This way, everyone can use the important
data you’re sharing.

The Future

Now that you know a little about how the canvas works, you can start
thinking of other ways you might use it. You could use it to create
a game, create a user interface for a media player, or use it to build
a better image gallery. All you need to start painting is a little bit of
JavaScript and a little bit of imagination.

Right now, Flash has an advantage over the canvas because it has
wider support, but as HTML5 picks up and the canvas is available to a
wider audience, more developers will embrace it for simple 2D graphics
in the browser. The canvas doesn’t require any additional plug-ins
and uses less CPU than Flash, especially on Linux and OS X. Finally,
the canvas provides you with a mechanism to do 2D graphics in environments
where Flash isn’t available. As more platforms support the
canvas, you can expect the speed and features to improve, and you’ll
see more developer tools and libraries appear to help you build amazing
things.

But it doesn’t stop with 2D graphics. The canvas specification will eventually
support 3D graphics as well, and browser manufacturers are
implementing hardware acceleration. The canvas will make it possible
to create intriguing user interfaces and engaging games using only
JavaScript.

 

Describing Data with New Input Fields

HTML5 introduces several new input types that you can use to better describe the type of data your users are entering. In addition to the standard text fields, radio buttons, and checkbox elements, you can use elements such as email fields, calendars, color pickers, spinboxes, and sliders. Browsers can use these new fields to display better controls to the user without the need for JavaScript. Mobile devices and virtual keyboards for tablets and touchscreens can use the field types to display different keyboard layouts. For example, the iPhone’s Mobile
Safari browser displays alternate keyboard layouts when the user is entering data into the URL and email types, making special characters like (@), (7), (7), and [/) easily accessible.

Improving the AwesomeCo Projects Form

AwesomeCo is working on creating a new project management web application to make it easier for developers and managers to keep up with the progress of the many projects they have going on. Each project has a name, a contact email address, and a staging URL so managers can preview the website as it’s being built. There are also fields for the start date, priority, and estimated number of hours the project should take to complete. Finally, the development manager would like to give each project a color so he can quickly identify each project when he looks at reports.

Let’s mock up a quick project preferences page using the new HTML5 fields.

Setting Up the Basic Form

Let’s create a basic HTML form that does a POST request. Since there’s nothing special about the name field, we’ll use the trusty text field.

<form method=”post” action=”/projects/l”>
<fieldset id=”personal_information”>
<1egend>Proj ect Information</legencb<ol>
<li>
<label for=”name”>Name</label>
<input type=”text” name=”name” autofocus id=”name”>
</li>
<li>
<input type=”submit” value=”Submit”>
</li>
</ol>
</fieldset>
</form>

Notice that we are marking this form up with labels wrapped in an ordered list. Labels are essential when creating accessible forms. The for attribute of the label references the id of its associated form element. This helps screen readers identify fields on a page. The ordered list
provides a good way of listing the fields without resorting to complex table or div structures. This also gives you a way to mark up the order in which you’d like people to fill out the fields.

Creating a Slider Using Range

Sliders are commonly used to let users decrease or increase a numerical value and could be a great way to quickly allow managers to both visualize and modify the priority of the project. You implement a slider with the range type.

<label for=”priority”>Priori ty</label>
<input type= “range” min=”0″ max= “10”
name= “priority” value=”0″ id =”priority”>

Add this to the form, within a new li element just like the previous field. Chrome and Opera both implement a Slider widget, which looks like this:

Priority

Notice that we’ve also set the min and max range for the slider. That will constrain the value of the form field.

Handling Numbers with Spinboxes

We use numbers a lot, and although typing numbers is fairly simple, spinboxes can make making minor adjustments easier. A spinbox is a control with arrows that increment or decrement the value in the box. Let’s use the spinbox for estimated hours. That way, the hours can be easily adjusted.

<label for=”estimated_hours”>Estimated Hours</label>
<input type=”number” name=”estimated_hours”
min=”0″ max=”1000″
i d=”estimated_hours”>

Opera supports the spinbox control, which looks like this:

Estimated Hours

The spinbox also allows typing by default, and like range sliders, we can set minimum and maximum values. However, those minimum and maximum ranges won’t be applied to any value you type into the field. Also notice that you can control the size of the increment step by giving
a value to the step parameter. It defaults to 1 but can be any numerical value.

Dates

Recording the start date of the project is pretty important, and we want to make that as easy as possible. The date input type is a perfect fit here.

<label for=”start_date”>Start date</label>
<input type= “date” name=”start_date” id =”start_date”
value=”2010-12-01″>

At the time of writing, Opera is the only browser that currently supports a full calendar picker.

Here’s an example of its implementation:

Safari 5.0 displays a field similar to the number field with arrows to increment and decrement the date. It defaults to “1582” if left blank. Other browsers render a text field.

Email

The HTML5 specification says that the email input type is designed to hold either a single email address or an email address list, so that’s the perfect candidate for our email field.

<label for=”email”>Emai 1 contact</label>
<input type=”email” name=”email” id=”email”>

Mobile devices get the most benefit from this type of form field, because the virtual keyboard layouts change to make entering email addresses easier.

There’s a field type designed to handle URLs too. This one is especially nice if your visitor uses an iPhone, because it displays a much different keyboard layout, displaying helper buttons for quickly entering web addresses, similar to the keyboard displayed when entering a URL into Mobile Safari’s address bar. Adding the staging URL field is as simple as adding this code:

<label for=”url”»Staging URL</label>
<input type=”url” name=”url” id=”url”>

Virtual keyboards use this field type to display a different layout as well.

Figure 3.1: Some form controls are already supported in Opera.

Color

Finally, we need to provide a way to enter a color code, and we’ll use the color type for that.

<label for=”project_color”>Project color</label>
<input type=”color” name=”project_color” id=”project_color”>

At the time of writing, no browsers display a color picker control, but that shouldn’t stop you from using this field. You’re using proper markup to describe your content, and that’s going to come in handy in the future, especially when you need to provide fallback support.

Opera supports most of these new controls right now, as you can see in Figure 3.1, but when you open the page in Firefox, Safari, or Google Chrome, you won’t see much of a difference. We’ll need to fix that.

Falling Back

Browsers that don’t understand these new types simply fall back to the text type, so your forms will still be usable. At that point, you can bind one of the jQuery UI or YUI widgets to that field to transform it. As time goes on and more browsers support these controls, you can remove the JavaScript hooks.

Replacing the Color Picker

We can easily identify and replace the color picker using jQuery with CSS3’s attribute selectors. We locate any input field with the type of color and apply a jQuery plug-in called SimpleColor.

if (!hasColorSupportO){
$C’input[type=color]’) .simpleColorO ;
}

Since we used the new form types in our markup, we don’t have to add an additional class name or other markup to identify the color pickers. Attribute selectors and HTML5 go together quite well.

We don’t want to use this color picker plug-in if the browser has native support for it, so we will use some JavaScript to detect whether the browser supports input fields with a type of color.

Une l function hasColorSupport(){
input = document.createElementC”input”) ;
input.setAttributeC”type”, “co7or”) ;
var hasColorType = (input.type !== “text”);
5 // handle Safari/Chrome partial implementation
if(hasColorType){
var testString = “foo”;
i nput.value=testStri ng;
hasColorType = (input.value != testString);
10 }
return(hasColorType);
}

First, we use plain JavaScript to create an element and set its type attribute to color. Then, we retrieve the type attribute to see whether the browser allowed us to set the attribute. If it comes back with a value of color, then we have support for that type. If not, we’ll have to apply our script.

Things get interesting on line 6. Safari 5 and Google Chrome 5 have partially implemented the color type. They support the field, but they don’t actually display a color widget. We still end up with a text field on the page. So, in our detection method, we set the value for our input field and see whether the value sticks around. If it doesn’t, we can assume that the browser has implemented a color picker because the input field isn’t acting like a text box.

The whole bit of code to replace the color picker looks like this:

if (!hasColorSupportO){
$C’input[type=color]’) .simpleColorO ;
}

That solution works, but it’s very brittle. It targets a specific set of browsers and only for the color control. Other controls have their own quirks that you need to learn. Thankfully, there’s an alternative solution.

Modernizr

The Modernizr2 library can detect support for many HTML5 and CSS3 features. It doesn’t add the missing functionality, but it does provide several mechanisms similar to the solution we implemented for detecting form fields that are more bulletproof.

Before you start throwing Modernizr in your projects, be sure you take some time to understand how it works. Whether you wrote the code yourself or not, if you use it in your project, you’re responsible for it. Modernizr wasn’t ready to handle Safari’s partial support of the color field right away. When the next version of Chrome or Firefox comes out, you may have to hack together a solution. Who knows, maybe you’ll beable to contribute that solution back to Modernizr!

You’ll implement fallbacks for controls such as the date picker and the slider in the same manner. Sliders and date pickers are included as components in the jQuery UI library.3 You’ll include the jQuery UI library on the page, detect whether the browser supports the control
natively, and, if it doesn’t, apply the JavaScript version instead.

Eventually you’ll be able to phase out the JavaScript controls and rely completely on the controls in the browser. Because of the complexity involved with detecting these types, Modernizer will be very helpful to you. However, we’ll continue writing our own detection techniques throughout the rest of this book so you can see how they work.

Aside from new form field types, HTML5 introduces a few other attributes for form fields that can help improve usability. Let’s take a look at autofocus next.