Monday, February 24, 2014

Microsoft 70-480: Write code that interacts with UI controls

Exam Objectives


Programmatically add and modify HTML elements; implement media controls; implement HTML5 canvas and SVG graphics


Quick Overview of Training Materials


Programming in HTML5 with JavaScript and CSS3 - Training Guide - Chapters 3, 7, 11, 12, 13
Developing in HTML5 with JavaScript and CSS3 Jump Start - Module 1 (part 2)
MSDN Articles on HTML5 - specifically How to Choose Between Canvas and SVG
Creating new HTML elements, moving elements in the DOM, and modifying the content and attributes of elements can all be easily accomplished using JavaScript.  New elements are created with the document.createElement method. While this method creates a new element, it does not insert it into the DOM. Inserting a node into the DOM requires the use of the .appendChild.replaceChild, or .insertBefore method.  The following JSFiddle demonstrates how to use these functions. Notice that to move an element from one node to the another, you only need to append to the destination node, it is automatically moved and not copied. You'll also notice the use of the .setAttribute() method. In this case, it was used to set the siblings' "class" attribute to "sibling" so that the appropriate CSS styling would be applied.



The w3.org has a very interesting example that uses a regular expression to extract the domain from the "href" attributes of all anchor tags on a page and then appends the extrated domain into a span following the link, so that a link then looks like a link[nowhere.com]. One common use of modifying elements is to change their display behavior.  This can be done by using element.setAttribute("style","display:none OR block") or by changing the property directly, i.e. element.style.display = "block".  The w3.org article also includes some bits about regex and wiring up events that, while good, are not germain to THIS particular discussion. We'll get to them soon enough.

HTML5 Media Controls

HTML5 makes integrating audio and video much easier.  In the past it was necessary to use embedded objects and plug-ins to use these resources, now like images they are first class citizens. Video and audio can now be used by implementing the <video> and <audio> elements.

The <video> element is used to implement video (duh). The height and width of the video element determine the size of the video player. While it is possible to use the src attribute to set the video source, using <source> tags within the <video> element allows you to set multiple source alternatives for the same video, which may come into play if a given browser does not support a certain video format. The three most relevenent video formats are H.264 (MPEG-4 or .mp4), Ogg (Theora), and VP8 (WebM or .webm). The Dive Into HTML5 chapter on video covers these in great detail, suffice it to know that H.264 is probably the most prevalent and is patented, the other two are royalty free and unencumbered by patents. This chapter also points out that no video container format is supported across all major browsers, so encoding multiple versions of your video and using multiple <source> tags will be necessary to ensure universal support.  It may also be necessary to gracefully fall back to Flash if you want to be supported in IE8 or earlier since these versions do not support HTML5 video at all. The chapter includes detailed instructions on how to encode video with Miro, FireFogg, and ffmpeg. I have personally always used VirtualDub with great success. The Training guide also mentions useing Miro and FireFogg to encode video.

Ultimately, a video embedded with HTML5 <video> tag should look something like this:

<video controls autoplay height="480" width="640" poster="image.png">
     <source src="example.mp4" type="video/mp4; codecs=avc1.42E01E,mp4a.40.2">
     <source src="example.webm" type="video/webm; codecs=vp8,vorbis"> 
     <source src="example.ogv" type="video/ogg; codecs=theora,vorbis"></video>

Here, we've specified that player is 480 x 640, the controls should be shown, and the video should start automatically on page load (autoplay). We've set a poster to display a static image when the video isn't playing.  We've specified three different sources for the video to maximize cross browser functionality. Within each <source> tag, it is important to set the MIME type with the type="" attribute, and set the appropriate codec.

The Training guide also mentions using the <track> element within a video to include subtitles with a technology called WebVTT (Web Video Text Tracks). It includes a bit of sample code but doesn't go into great detail. The HTML5Rocks article goes into much greater detail, however. The <track> element has a number of attributes, including kind="captions, subtitles, etc.", label="English Subs", scr="yourfile.vtt", srclang="en", and default (boolean). A .vtt file is essentially a series of timestamps called cues, each of which may have a label preceeding it, and any amount of text following. Cues are seperated by blank lines. The text may even be in HTML or JSON format. This gives the <track> element a lot of potential power, showcased by this demo that uses it to synchronise a video with a Google Maps track.

The <audio> element is similar in purpose to the <video> element. The most common audio formats for audio are Ogg/Vorbis(.oga), MP3, MP4(AAC), and WAV. Like the video element, the audio element can be given an boolean attribute of "controls" that allows the user to control playback. Multiple <source> tags can be used to specify multiple alternate sources. Like video sources, the MIME type and codec must be specified on the <source> element.

Both the <audio> and <video> elements inherit from the HTMLMediaElement object. This object includes a number of methods, properties, and events. These allow for a great deal of flexibility in how the video and audio elements are acutally used in your site or application.

HTML5 Canvas

The Dig Into HTML5 chapter on canvas is an excellent introduction. I followed along in JSFiddle and implemented some of the basic functionality, the results are below. This fiddle demonstrates how to select the canvas element from the DOM, get it's context, and use that context to draw rectangles, define and "stroke" lines, draw text, and draw images. While much of it was copy and pasted, I did have a bit of fun with some random color and coordinate definition. The training guide also has a lesson devoted to <canvas> which walks through quite a few examples, including rectangles, arcs, gradients, and images.



The Deep Dive video for <canvas> is from MIX11, and the presenter Jatinder Mann gives a general overview of Canvas and then gives a number of best practices for using Canvas in a production environment. One best practice I used in the above example was to use the .clearRect() method rather than setting the canvas width equal to itself (as was suggested in the guide).    One capability of canvas that was showcased in the video that was surprising was the fact that you can also draw video to a canvas. A hands-on demo was available to play with some of the other capabilities of canvas.

The important DOs and DON'Ts covered in the deep dive include:

  • DONT create loads of small objects with clipping, shadows, and composition. These operations are expensive and create intermediate images, and doing it a bunch of times will hurt performance. Use ONE image with lots of little things on it if possible.
  • DO check to see if your use of canvas is impacted by differences in the way some browsers handle compositions (source-in, source-out, destination-in, copy, and destination-atop).
  • DO use ctx.save() and ctx.restore(). Canvas attributes are global and do not reset after a use.
  • DO keep in mind that security is built in and cross domain images cannot be saved with canvas.toDataURL()
  • DO use the interior of the canvas tag for fallback content. Doing so can make your site more accessible.
  • DO canvas feature detection, for example: if (canvas && canvas.getContext && canvas.getContext("2d")){ //canvas code} else {//non-canvas fallback code}
  • DON'T do this with browser detection or conditional comments as it can break other stuff
  • DO add a DOCTYPE to ensure your site is in standards mode. Quirky browser modes may break canvas
  • DON'T repeatedly call getImageData() for small areas, loop through every pixel, or access canvas.ImageData.data[i]. These make a lot of unnecessary calls to the DOM or the data, and hurt performance. Instead...
  • DO request large areas of data with getImageData() and cache it in a JavaScript Object.
  • DON'T clear the canvas by setting dimensions every frame, use .clearRect() instead. Setting width wipes out all your objects and re-using objects is a key to high performance.
One interesting point he made about time interval on animation is the fact that it is pointless to set a time interval lower then the refresh rate on the monitor. Mismatching the rate can cause frame skipping, and setting it to 1ms would use a lot of extra resources (think battery life). Most monitors use a 60hz refresh rate, so a 17ms interval is ideal. The hands-on demo for video calculates it directly (1000ms/60hz = 16.67 ms refresh rate), though it applies a floor so it's actually using 16ms.

SVG


I started out with the MIX11 video with Jennifer Yu. She wasn't as well prepared as Jatinder was for canvas, but she still covered a lot of material.  I managed to follow along with and create a JSFiddle demo that is embedded below.  Like the canvas presentation, she covered the basics, showed off some cool demos, and then went over best practices. There is also a hands-on demo site for SVG filter effects.



SVG is a much different animal compared to Canvas. Whereas a Canvas element is basically a raster surface that you draw on with JavaScript, SVG is specified by geometry. SVG shapes exist as XML elements right in the DOM.  While this means you don't have to worry about tracking their state (as you would in canvas), it does mean that if you have lots of small elements performance can bog down.  Other than the basic shapes (rectangles, circles, paths, text), you can also define a viewBox attribute which will allow you to scale a large vector image into a given area. Gradients, patterns, and paths can be defined in a <defs> tag and then reused elsewhere (make sure you spell it right, it took me forever to figure out why my gradients weren't working in my JSFiddle demo haha).  Also, if you want to conform with XML, don't forget to include the SVG and xlink namespaces.

Since SVG is part of the DOM, you can use regular DOM commands such as .setAttribute, but it's worth mentioning that SVG has it's own DOM that may perform better, though it is a little more complicated. So instead of  myCircle.setAttribute("r",42) you might use myCircle.r.baseVal.value = 42, though if you want to perform numeric operations you will have to parse with core DOM whereas SVG DOM gets the value directly.  Always use the base value (not the animation value) for scripting.

SVG images can be compressed using GZip, just remember to include "Content-encoded: gzip" in response header.  Also important to include the MIME type of  "image/svg+xml", and use DOCTYPE to ensure the browser is in standards mode.

While my demo uses only inline <svg> elements, there are other methods of displaying SVG. One is by using the <object> element. This has the advantage of allowing you to fallback to a regular <img> if SVG is not supported in a users browser. You would accomplish this feature like this:
<object src="myPic.svg">
     <img src="myPic.png" />
</object>

While most SVG shapes are pretty intuitive, the <path> shape deserves special mention as it is the basis for most complex SVG drawings, and is covered well in the training guide.  The central attribute to the <path> element is "d" which defines the path data with a number of special commands. "m" moves to a specified corrdinate, where the x and y coordinate are the two numbers imediately following, so "m80 120" or "m 80,120" moves the drawing point to (80,120). Drawing lines is accomplished using commands such as l (lower case L, a line to x,y), h (horizontal line), v (vertical line), a (arc), q & t(quadratic bezier curve), c & s (cubic bezier curve), and z (closes shape by drawing straight line to beginning of path).  Specifying very complex shapes by hand would be tedious and prone to error, so it's recommended to use tools to specify these shapes (CAD or vector drawing software).




1 comment: