Вы находитесь на странице: 1из 102

appliness

#2 - MAY 2012

Pamela

Exclusi

ve inte rview

Fox

The digital magazine for web app

DEVELOPERS

TUTORIALS

HTML5, BACKBONE, jQUERY, PHONEGAP, BOOTSTRAP, CSS3...


HTML5 & JS

PHONEGAP FILE API, MULTIMEDIA COMPONENTS, APP-UI JS

appliness

THE FIRST DIGITAL MAGAZINE FOR WEB APPLICATION DEVELOPERS


welcome to appliness. the contributors of this free magazine are all professional and passionate developers. if you want to write a tutorial, showcase your application, contact us on our website appliness.com. we hope that you enjoy reading the second issue of this magazine.

(
FOCUS GROUP INTERVIEW SHOWCASE video tutorial VISUAl and juicy WTFJS BLEEDING EDGE TEAM

TABLE OF CONTENTS SHAPE TOMORROW TODAY

EXPRESSING RICH LAYOUTS WITH SIMPLE, DECLARATIVE CSS


by Deepa Subramaniam

DONt WORRY, BE APPLI

DRAG & DROP WITH JQUERY UI


by Michal Chaize

Javascript object creation: learning to live without new


by Keith Peters

Crafting native looking ios apps with html


by Christophe Coenraets

using backbone.js with jquery mobile


by Christophe Coenraets

demo of handlebars, and why you should consider a templating engine


by Raymond Camden

REAL-TIME data exchange in html5 with websockets


by Ryan Stewart

swipe to delete items with jquery mobile on touch devices


by Michal Chaize

LIBRARY OF THE MONTH

app-ui, a javascript library


by Andrew Trice

HTML5 AND MULTIMEDIA: VIDEO, AUDIO AND COMPONENTS


by Ian Devlin

INTERVIEW OF PAMELA FOX


by Maile Valentine

Three great PHONEGAP APPLICATIONS


by Michal Chaize

WHICHELEMENT.com

pull quote and comments


by Terry Ryan & Ray Camden

phonegap and the file api


by Raymond Camden

decision path to phonegap


by Michal Chaize

false advertising
by Toby Ho

generating color palettes from html5 video


by Raymond Camden

css variables draft


by Terry Ryan

HELTER SKELTER NEWS

NEWS about html and javascript


by Brian Rinaldi

whos behind the magazine


by the team

NAVIGATION GUIDE READ

NAVIGATE
GO BACK TO THE LIBRARY MOVE TO THE PREVIOUS ARTICLE DISPLAY THE TABLE OF CONTENTS VISUALLY BROWSE ALL THE ARTICLES

MOVE TO THE NEXT ARTICLE BY A HORIZONTAL SWIPE

READ THROUGH THE ARTICLE BY A VERTICAL SWIPE

appliness

SHAPE TOMORROW TODAY

Expressing Rich Layouts with Simple, Declarative CSS

Along with the community, ADOBE ENGINEERS ARE developing new standards and advancing existing standards. IN THIS ARTICLE, they introduce CSS REGIONS AND CSS EXcLUSIONS which are two proposals for the w3c. thanks to these new additions, a designer or developer can create high-quality, magazine-style layouts for the web using HTML5 and CSS3.

a rich digital format


It is hard to deny that its an exciting time for innovation on the web. Some of the powerful proposals coming out of working groups in the W3C are letting designers and developers build standards-based rich content with HTML5, CSS3 and JavaScript in a much easier way. One area that is ripe for innovation is around how to better translate classic print designs to a rich digital format. The reality is that several of the capabilities that are taken for granted when designing content for print are still very difficult to implement using web standards. When print designs are converted to an HTML-based form for digital consumption, one of the current limitations is that expressive layouts do not translate well. This is an area that Adobe has a lot of experience with and a problem we want to help solve. To start, we have worked with partners to introduce two proposals to the W3C CSS Working Group: CSS Regions and CSS Exclusions. In addition to championing two new standards, were implementing these proposals directly in open browser engines like WebKit. With both CSS Regions & CSS Exclusions, a designer or developer can create high-quality, magazine-style layouts for the web using HTML5 and CSS3.

CSS REGIONS
Lets first discuss CSS Regions. HTML and CSS today allow you to place text in a box, and has support for flowing text through identical column boxes contained in a single box. If you want to size and position
3/7

separate boxes for your text to flow through, you can only approximate your desired layout by breaking up your text and assigning which text goes in which box. This results in a fixed layout that breaks down at the slightest change of font or window size. With the introduction of CSS Regions, you can flow unbroken text fluidly from box to box without any restrictions on size or position. Designers & developers are free to use columns and gutters with different widths and flow text through whatever expressive layout they choose to create. CSS Regions makes achieving this easy. With this new feature, you can specify how text or images should flow across multiple regions with simple, declarative CSS. In the video below, three distinct regions are specified and as the browser resizes, notice how the text flows naturally from one region to the other.

VIDEO CSS Regions shows how browser resizing causes fluid reflowing of text

The code for this is quite simple. The text source is named using the new vendor prefixed -webkitflow-into CSS property on the element that contains the content. This naming causes the content to be removed from the normal CSS layout flow and allows it to be inserted into specially defined regions by setting the -webkit-flow-from property. The code for the video above looks like this: CSS: #source{ -webkit-flow-into: main-thread; } .region{ -webkit-flow-from: main-thread; } HTML: <div id=source> <p>Lorem ipsum dolor [...]</p> </div> <div id=region1 class=region></div> <div id=region2 class=region></div> <div id=region3 class=region></div>
4/7

In fact, regions can be positioned anywhere. Using this same syntax, you can have multiple threads of text or images flow into separate chains of regions. The video below shows two threads of text flowing into non-contiguous regions because the order in which text is flowed is explicitly controlled by the -webkit-flow-into property.
VIDEO Multiple text threads flow naturally into non-contiguous regions with simple CSS properties

Here is a video of a more complex example created by Adobe engineer, Christian Cantrell. In this sample, a short story is formatted using CSS Regions. Youll notice that the story is divided into two columns, which is more of a print-like layout and friendly to read. The power of CSS Regions becomes obvious when you see that the text is actually flowing from one column to the other. Notice that as the browser resizes, the text flows from column to column and the page concept is maintained. Without CSS Regions, you would have to write a fair amount of JavaScript to break the text into appropriately sized pieces (and re-run the script any time the font or window size changed). Now its just a matter of setting a few CSS properties!

VIDEO Multiple text threads flow naturally into non-contiguous regions with simple CSS properties

5/7

What is even better is that CSS Regions can be experimented with now! All of the above examples were shown in recent builds of Chrome. CSS Regions is also available in the Developer Preview of Internet Explorer 10 and nightly builds of WebKit. While there has been great progress, CSS Regions is still a cutting edge feature so in some cases it is protected by both vendor prefixes and runtime flags. To play with CSS Regions in Chrome you will need to enable the feature through the --enable-css-regions runtime flag. There are instructions on the web about how to easily do this in Chrome. We are thrilled with how CSS Regions is progressing and are working on some new features to add. These include making it even simpler to style regions, auto-setting the height for regions, and introducing a page template model to create boxes in CSS and better handle pagination. To stay informed of the evolution of CSS Regions and get access to sample code and new demos, keep an eye on the CSS Regions page on html.adobe.com.

CSS EXCLUSIONS
A complementary feature to CSS Regions is CSS Exclusions, which allows the creation of custom text exclusions to wrap text with shapes or images. Again, with simple CSS properties, you can define a custom shape as the container for text, like so:

Or cause text to flow around a custom shape like so:

6/7

This behavior is simple to achieve with just a few new properties CSS Exclusions introduces. The webkitwrap-shape property defines the boundary in which to flow text content and also defines the area to be avoided when laying out content. The -webkit-wrap-shape-mode property controls how the content responds to a shape and flows the content appropriately. In this video, using the webkit-wrap-shape and webkit-wrap-shape-mode CSS properties, you can see several things. Notice that as the browser resizes, text flows around the custom shape and if the shape size changes, the text continues to flow as one would expect of a responsive layout. Additionally, the custom shape can be dynamically swapped to any polygon and text layout and reflowing capabilities are maintained!

VIDEO Dynamic shapes can be used to cause text to flow naturally with CSS Exclusions

Adobe is actively working on CSS Exclusions and while it is not yet fully available in current browsers, it should be available in Chrome and WebKit nightly builds soon. The CSS Exclusions page on Adobe & HTML will be updated as the feature progresses but till then, it is there you can access a custom WebKit build to play with the feature now. We think the power that both CSS Regions and CSS Exclusions offer designers and developers is very exciting! Expressive, liquid layouts are achievable with just a few CSS properties and a clever eye. Were thrilled that the features are being used to create compelling digital experiences, like in the following example where both features are used to cause text to flow around the mountain and car images as the user scrolls the arrow to pan around. Keep an eye out for CSS Regions and Exclusions to land in your favorite browser and we hope you consider using them as you develop rich layouts on both desktop and mobile devices.

ABOUT THIS ARTICLE


Deepa Subramaniam is the Group Product Manager for Adobes Web Platform team a team focused on making the web more awesome by collaborating with the community to champion new standards and contributing to open source projects like WebKit. She loves sun, coffee and good-looking code. http://html.adobe.com @iamdeepa

ONLINE RESOURCES The Adobe & HTML website http://html.adobe.com CSS Regions W3C Specification http://dev.w3.org/csswg/css3-regions/ CSS Exlusions W3C Sepcification http://dev.w3.org/csswg/css3-exclusions/

appliness

DONT WORRY, BE APPLI

Drag and Drop with jQUERY UI


WHY USE DRAG AND DROP ON A TABLET?

Drag and drop is a classic gesture in desktop applications. Learn how to code it on touch devices such as your tablet using jQuery UI and some hacks.

As a RIA (Rich Internet Application) developer, I try to introduce meaningful and efficient user interactions in my apps. A classic and natural way to associate items is to use drag and drop. Its a classic action in desktop applications. With the introduction of touch screens, its even more natural on mobile devices. When you need to order items, assign items to categories or to an action, drag-and-drop makes sense. In this tutorial, Ill play with a list of team members and a list of tasks. As you can guess, the enduser will be able to assign a specific member to a task member using drag-and-drop. Desktop frameworks have implemented Drag and Drop management based on mouse events. Thats why a lot of these libraries are not effective on touch devices. Well see in this tutorial how to hack these libraries and simulate touch events. On the next page, you can start playing with the final application. Drag users on tasks using your finger and read this tutorial to understand how to code it.

d n u o laygr

Difficulty
- rookie - intermediate - expert

- jQuery I U y r e u Q j - CSS

Todo list
- drag stuff - drop things - wash fingers
by Michal Chaize
8/14

PLAY WITH THE FINAL APPLICATION

Some cool features that you should notice: - If you dont drop a user on a task, then he will automatically move back to his original place. - Users snap to the edges of the task boxes while dragging them on the stage. - Once a user is assigned to a task, you cannot drag him anymore, and you cannot drop another user on this task.

Enable Drag and Drop on touch devices


There are several ways to enable drag and drop for items in a web page. For this application, I wanted to use jQuery UI because it provides robust abstractions for low-level interactions and animations. Its built on top of jQuery, so you can easily reuse that library for your desktop and mobile apps. Once you import the jQueryUI library in your web project, you just need to give an id to a <DIV> element and call $(#idOfMyElement).draggable(). Unfortunately, jQueryUI has been designed for desktop apps and mouse events. David Furfero (furf.com) has developed a small hack that consists of mapping touch events to their mouse event analogs. It works perfectly on iOS and Android devices. He shared his code on gitHub in a library called Touch-Punch for jQueryUI. Its160 lines of code library that can become very useful. First, David starts by detecting if the device supports touch events.

9/14

// Detect touch support $.support.touch = ontouchend in document; // Ignore browsers without touch support if (!$.support.touch) { return; } Then he gets a reference to the mouse prototype: var mouseProto = $.ui.mouse.prototype; For every touch event, he will simulate the corresponding mouse event. He rewrites the touchMove handler: mouseProto._touchMove = function (event) { // Ignore event if not handled if (!touchHandled) { return; } // Interaction was not a click this._touchMoved = true; // Simulate the mousemove event simulateMouseEvent(event, mousemove);

};

The simulateMouseEvent contains the hack and the classic event.preventDefault() call. function simulateMouseEvent (event, simulatedType) { // Ignore multi-touch events if (event.originalEvent.touches.length > 1) { return; } event.preventDefault(); var touch = event.originalEvent.changedTouches[0], simulatedEvent = document.createEvent(MouseEvents); // Initialize the simulated mouse event using the touch events coordinates simulatedEvent.initMouseEvent( simulatedType, // type true, // bubbles true, // cancelable window, // view 1, // detail touch.screenX, // screenX touch.screenY, // screenY touch.clientX, // clientX touch.clientY, // clientY

10/14

);

false, false, false, 0, null

// // // // //

altKey shiftKey metaKey button relatedTarget

// Dispatch the simulated event to the target element event.target.dispatchEvent(simulatedEvent);

This touch-punch library is on github. Just download it and include it in your web project in addition to jQueryUI and jQuery. <head> <script src=jquery-1.7.1.min.js/></script> <script src=jquery-ui-1.8.18.custom.min.js/></script> <script src=jquery.ui.touch-punch.min.js/></script> </head>

DRAG...
Now you can use the draggable() plugin on your elements and start dragging them on the stage. <html> <head> <title>Drag</title> <link rel=stylesheet type=text/css href=css/ui-lightness/jquery-ui-1.8.18.custom.css rel=stylesheet> <link rel=stylesheet type=text/css href=style.css> <script src=jquery-1.7.1.min.js/> </script> <script src=jquery-ui-1.8.18.custom.min.js></script> <script src=jquery.ui.touch-punch.min.js></script> <script> $(function() { $( #draggable1 ).draggable(); }); </script> </head> <body> <div class=titleStyle style=width:600px> DRAG ME </div> <div id=members style=width:600px; height:150px> <div id=draggable1 class=ui-widget-content displayBloc>

11/14

<img src=mchaize-sf-low.jpg width=100/>Michal C. </div> </div> <div class=titleStyle style=width:600px;margin-top:50px;>DROP HERE</div> <div id=tasks class= bigBox> <div id=droppable_1 class=ui-widget-header dropyBloc titleStyle> <p>Task 1</p> </div> </div> </div> </body> </html>

...AND DROP
Lets define a drop zone for our user. The jQuery UI Droppable plugin makes the elements of your choice droppable, which means that they accept being dropped on by draggables. In this application, the <DIV> element with the id droppable_1 will be our target. A drop event will be triggered when the draggable will be dropped over. In the callback, well find the paragraph <p> element and modify the text from Task 1 to Task assigned. <script> $(function() { $( #draggable1 ).draggable(); $(#droppable_1).droppable({ drop: function( event, ui ) { $( this ) .find( p ) .html( Task assigned) } }); }); </script> </head> <body> <div class=titleStyle style=width:600px> DRAG ME </div> <div id=members style=width:600px; height:150px> <div id=draggable1 class=ui-widget-content displayBloc> <img src=mchaize-sf-low.jpg width=100/>Michal C.
12/14

</div> </div> <div class=titleStyle style=width:600px;margin-top:50px;>DROP HERE</div> <div id=tasks class= bigBox> <div id=droppable_1 class=ui-widget-header dropyBloc titleStyle> <p>Task 1</p> </div> </div> </div> </body>

SNAP MODE
The method has some very cool built-in options. To guide the user, you can choose to snap a draggable to the edges of a specific element. In this case, I want the user to snap the inner edges of the task box while dragging it. In the draggable plugin options, I specify the selector as a snap target and I set the to (possible values are , and ). I also want to add a visual feedback if a user is not dropped on a task (on a valid droppable element). Thats why I set the option to . $( #draggable1 ).draggable({ snap: .ui-widget-header, snapMode: inner,revert:true }); By default, the draggable object will always return to its original position when dropped. I need to disable the behavior when the item is dropped on a correct place. To do so, I just need to extend the drop callback setting the option to . Im also setting the final coordinates of the draggable element once dropped using the options. $(#droppable_1).droppable({ drop: function( event, ui ) { $( this ) .find( p ) .html( Task assigned) ui.draggable.draggable(option,revert,false); ui.draggable.position({of: $( this ),my: left bottom, at: left bottom }); } });

13/14

DISABLE AND STYLE WITH CSS


Lastly, I need to disable the draggable and the droppable behaviors on my elements. I can also set new styles using the addClass() method to change the visual appearance of my draggable item and of my task box. $(#droppable_1).droppable({ drop: function( event, ui ) { $( this ) .addClass( ui-state-highlight ) .droppable(disable) .find( p ) .html( Task assigned); ui.draggable.draggable(disable); ui.draggable.addClass(correct); ui.draggable.draggable(option,revert,false); ui.draggable.position({of: $( this ),my: left bottom, at: left bottom }); } }); /... style.CSS .../ .correct{ opacity:1; background-color:#C2FF84; }

GET THE SOURCE CODE


If my final application, I have four users and four tasks. Using jQuery loops, you can easily reproduce the techniques Ive used in this tutorial. In a tasks DIV element, I have several droppable_n elements (droppable_1, droppable_2), so I can use the generic iterator each() function of jQuery. $(#tasks div).each(function(idx, item) { var idTask = parseInt(idx) + 1; $(#+item.id).droppable({ drop: function( event, ui ) { $( this ) .addClass( ui-state-highlight ) .droppable(option, disabled, true) .find( p ) .html( Task +idTask+ assigned ); ui.draggable.draggable(disable); ui.draggable.addClass(correct); ui.draggable.draggable(option,revert,false); ui.draggable.position({of: $( this ),my: left bottom, at: left bottom }); } }); });

MORE INFORMATION

>

>

appliness

DONT WORRY, BE APPLI

In this article, Im going to discuss object creation in JavaScript using prototypal inheritance as an alternative to the new operator.

JavaScript object creation: Learning to live without new

embrace the javascript language


One significant aspect of JavaScript is that there is rarely a single right way to do any particular task. JavaScript is a loosely-typed, dynamic, and expressive language, which means that there are usually many different ways to accomplish the same task. Im not saying that the methods described here to create objects are the only correct ways to do so or even the best ways, but I do feel that they are closer to the true nature of the language and will help you to understand whats going on under the covers if you choose to use other methods. To help you better understand these concepts, this article describes the creation of a basic particle system with multiple rendering targets. This is a complex enough task to represent a real world test of the concepts Ill be demonstrating, rather than a simple hello world type of application.

d n u o laygr

t - JavaScrip e p y t o t o r P - Canvas

Difficulty
- rookie - intermediate - expert

Todo list
forget class code reuse particles
by Keith Peters
15/27

Object creation basics


The crux of this article is the creation of JavaScript objects. Most tutorials you see will tell you to create a constructor function, add methods to the functions prototype property, and then use the new operator like so: function Foo() { this.name = foo; } Foo.prototype.sayHello = function() { alert(hello from + this.name); }; var myFoo = new Foo(); myFoo.sayHello(); The newly created object now has all the properties that were defined on the constructor functions prototype. This creates something that looks much like a class in a class-based language. To make a new subclass that inherits from that class, youd set the prototype property of the subclass to a new instance of the original class. (Im using quotation marks here because the entities are not actual classes or subclasses.) function Bar() { } Bar.prototype = new Foo(); Bar.prototype.sayGoodbye = function() { alert(goodbye from + this.name); } var myBar = new Bar(); myBar.sayHello(); myBar.sayGoodbye(); The problem is that because this structure looks so similar to real classes in other languages, people start expecting it to behave exactly like real classes behave in other languages. But the more you work with these types of classes, the more you see that they dont behave that way at all. So people get upset with JavaScript, and start thinking it is a bad language that cant be used for anything serious. Others go about trying to fix these class-like structures, tacking on various bits of functionality and building up very complex frameworks to get constructor functions and prototypes to look and behave more and more like classes. Personally, I see this as a bit of a misguided effort. Its not necessarily wrong, but the energy being spent would likely produce better results if it was in another direction.

Embracing prototypal inheritance


JavaScript is not a class-based language, but a prototype-based one. Code reuse is done not by making class templates that are used to instantiate objects, but by creating new objects directly, and then making other new objects based on existing ones. The existing object is assigned as the prototype of the new object and then new behavior can be added to the new object. Its quite an elegant system and its beautifully implemented in the Io language, which I encourage you to look into.
16/27

Before going any further, I want to clarify the term prototype. First, there is the prototype property of a constructor function as shown in the last sections example. There is another hidden property that is the actual prototype of an object. This can be very confusing. The ECMAScript proposal refers to this hidden property as [[Prototype]]. This is exposed in some JavaScript environments as the __proto__ property, but this is not a standard part of the language and should not be counted on. When you create a new object using new with a constructor function, that new objects [[Prototype]] is set with a reference to the constructor functions prototype. In addition to this naming confusion, there were two design decisions made in the language that have added to the confusion ever since. First, due to the concern that some developers might not be comfortable with prototypal inheritance, constructor functions and the new operator were introduced. Second, there was no direct native way to create a new object with another object as its [[Prototype]], except through the new operator with a constructor function. Fortunately, most browsers now support the Object.create method. This method takes an existing object as a parameter. It returns a new object that has the existing object assigned as its [[Prototype]]. Even more fortunately, this method is quite easy to create for those environments that do not support it: if(typeof Object.create !== function) { Object.create = function (o) { function F() {} F.prototype = o; return new F(); }; } So, how would you rewrite the earlier example using Object.create? First you create a foo object that has a name property and a sayHello function: var foo = { name: foo, sayHello: function() { alert(hello from + this.name); } }; foo.sayHello(); Then, you use Object.create to make a bar object that has foo as its prototype, and add a sayGoodbye function to it: var bar = Object.create(foo); bar.sayGoodbye = function() { alert(goodbye from + this.name); } bar.sayHello(); bar.sayGoodbye(); Its also very common to create an extend function that simplifies the adding of methods and properties to the new object. The following method simply copies over any properties from props onto obj: function extend(obj, props) { for(prop in props) { if(props.hasOwnProperty(prop)) { obj[prop] = props[prop]; }}}

17/27

This enables you to create bar like so: var bar = Object.create(foo); extend(bar, { sayGoodbye: function() { alert(goodbye from + this.name); } }); Not such a big deal here, but it simplifies things greatly when you are adding several more properties or methods. OK, now that you have the basics down, you can start putting them together in a real world scenario.

Creating particles using Object.create


The particles used in the example project are going to be very basic: black dots that move around in a two-dimensional space and bounce off the walls. They also support gravity and friction as needed. Youll define a particle object that has all the properties and methods it needs, and place it in an adc object to avoid polluting the global namespace. Here is the running example:

18/27

var adc = adc || {}; adc.particle = { x: 0, y: 0, vx: 0, vy: 0, gravity: 0.0, bounce: -0.9, friction: 1.0, bounds: null, color: #000000, context: null, update: function() { this.vy += this.gravity; this.x += this.vx; this.y += this.vy; this.vx *= this.friction; this.vy *= this.friction; if(this.x < this.bounds.x1) { this.x = this.bounds.x1; this.vx *= this.bounce; } else if(this.x > this.bounds.x2) { this.x = this.bounds.x2; this.vx *= this.bounce; } if(this.y < this.bounds.y1) { this.y = this.bounds.y1; this.vy *= this.bounce; } else if(this.y > this.bounds.y2) { this.y = this.bounds.y2; this.vy *= this.bounce; }

},

} };

render: function() { if(this.context === null) { throw new Error(context needs to be set on particle); } this.context.fillStyle = this.color; this.context.fillRect(this.x - 1.5, this.y - 1.5, 3, 3);

Next, youll need a particle system to keep track of all the particles and handle updating and rendering them.

19/27

var adc = adc || {}; adc.particleSystem = { particles: [], addParticle: function(particle) { this.particles.push(particle); }, update: function() { var i, numParticles = this.particles.length; for(i = 0; i < numParticles; i += 1) { this.particles[i].update(); }

},

};

render: function() { var i, numParticles = this.particles.length; for(i = 0; i < numParticles; i += 1) { this.particles[i].render(); } }

And finally, youll need a main file that creates the system, creates and adds all the particles, and sets up the animation loop. (function() { if (typeof Object.create !== function) { Object.create = function (o) { function F() {} F.prototype = o; return new F(); }; } var system, numParticles, canvas, context, bounds; function initSystem() { system = Object.create(adc.particleSystem); numParticles = 200; canvas = document.getElementById(canvas); context = canvas.getContext(2d); canvas.width = window.innerWidth; canvas.height = window.innerHeight; bounds = { x1: 0, y1: 0,

20/27

};

x2: canvas.width, y2: canvas.height

function initParticles() { var i, particle; for(i = 0; i < numParticles; i += 1) { particle = Object.create(adc.particle); particle.bounds = bounds; particle.context = context; particle.x = Math.random() * bounds.x2; particle.y = Math.random() * bounds.y2; particle.vx = Math.random() * 10 - 5; particle.vy = Math.random() * 10 - 5; system.addParticle(particle); } } function animate() { context.clearRect(bounds.x1, bounds.y1, bounds.x2, bounds.y2); system.update(); system.render(); } initSystem(); initParticles(); setInterval(animate, 1000 / 60); }()); The code in this file is contained in an immediately invoked function expression, again to avoid global namespace pollution. It includes the Object.create shim for browsers that might need it. This is all pulled together in the following HTML file: <!DOCTYPE html> <html> <head> <title>Particles v1</title> <style type=text/css> .html, body { margin: 0; padding: 0; } </style> </head> <body> <div> <canvas id=canvas/> </div> <script type=text/javascript src=v1/particle.js></script> <script type=text/javascript src=v1/particleSystem.js></script> <script type=text/javascript src=v1/main.js></script> </body></html>

21/27

The important lines, for the purposes of this article, are those that create the particle system: system = Object.create(adc.particleSystem); and that create the particles themselves: particle = Object.create(adc.particle); particle.bounds = bounds; particle.context = context; particle.x = Math.random() * bounds.x2; particle.y = Math.random() * bounds.y2; particle.vx = Math.random() * 10 - 5; particle.vy = Math.random() * 10 - 5; You havent implemented any kind of extend function yet, but you can see here where it would be useful calling extend a single time, rather than line after line of assigning properties. In the next iteration, youll add that and then some.

Adding extend and init


For the second version of the particle system, rather than having the main file create and extend each and every particle by itself, it would be better to have the particles know how to create, extend, and initialize themselves. To support that, you can use two new functions, extend and init , which are added to adc.particle : var adc = adc || {}; adc.particle = { x: 0, y: 0, vx: 0, vy: 0, gravity: 0.0, bounce: -0.9, friction: 1.0, bounds: null, color: #000000, context: null, extend: function(props) { var prop, obj; obj = Object.create(this); for(prop in props) { if(props.hasOwnProperty(prop)) { obj[prop] = props[prop]; } } return obj; }, init: function() { this.x = Math.random() * this.bounds.x2; this.y = Math.random() * this.bounds.y2; this.vx = Math.random() * 10 - 5;

22/27

};

}, // // rest of methods are the same as version 1

this.vy = Math.random() * 10 - 5;

The extend method takes care of creating a new object, passing this as a parameter to Object.create. Thus, it makes a copy of itself. It then takes any properties that were passed into extend, copies them onto the new object it created, and finally returns the new object. Now, rather than calling Object.create(adc.particle) and setting and tweaking property after property, you can call adc.particle.extend, passing in an object with the properties you want to set, and then call init on the newly created particle. When you add the extend method to the particle system, the main file becomes a bit simpler. In initSystem, you call adc.particleSystem.extend() to create the new system. You dont need to add any properties to the system, so extend is called with no parameters. Not much of a change there: function initSystem() { system = adc.particleSystem.extend(); numParticles = 200; canvas = document.getElementById(canvas); context = canvas.getContext(2d); canvas.width = window.innerWidth; canvas.height = window.innerHeight; bounds = { x1: 0, y1: 0, x2: canvas.width, y2: canvas.height }; } In the initParticles method, though, you see an improvement: function initParticles() { var i, particle; for(i = 0; i < numParticles; i += 1) { particle = adc.particle.extend({ bounds: bounds, context: context }); particle.init(); system.addParticle(particle); } } Now you can call adc.particle.extend to create each particle, passing in an object that contains the bounds and context, which are then copied to each particle. Finally, you just call init on the new particle, which takes care of randomly setting up its position and velocity. This version works exactly the same as the last, but the creation of individual particles has been greatly simplified.
23/27

Adding inheritance
The third version of the particle system supports inheritance. This is key to code reuse. You have one type of object and you want to make another type of object that is slightly different. You dont want to completely recreate the first object with just a couple of changes. Code reuse has two important benefits. First, there is less code to write. You certainly dont want to write the same code twice. You also dont want to copy and paste code, as this can lead to things getting out of sync, with a function implemented one way over here and the same function implemented a bit differently over there. The second benefit is better performance. When you have the same code duplicated in your live application, it takes longer to download, eats up more memory, and can cause your code to be slower, particularly in object instantiation (because it is instantiating the same code again and again). The particle system currently renders to an HTML5 canvas. Now, you may want to make a different particle type that renders itself as a DOM object. Ideally, almost all of the particle code would be reused, with only the render method differing. So, with great confidence, you can just take particle.js and remove the render method from it. Next, make two new files, canvasParticle.js and comParticle.js. The canvas version will be similar to what youve just done: var adc = adc || {}; adc.canvasParticle = adc.particle.extend({ render: function() { if(this.context === null) { throw new Error(context needs to be set on particle); } this.context.fillStyle = this.color; this.context.fillRect(this.x - 1.5, this.y - 1.5, 3, 3); } }); This code is quite simple. You just call adc.particle.extend, passing in an object that contains your old render method. This will create a new object that has particle as its [[Prototype]], and render as a new method directly on the object. Next youll have to change main.js a bit to allow for your new object types. Create a mainCanvas.js file for setting up the canvas-based particles. It will only differ in one line, where it uses the adc.canvasParticle type to instantiate particles, rather than just adc.particle: function initParticles() { var i, particle; for(i = 0; i < numParticles; i += 1) { particle = adc.canvasParticle.extend({ bounds: bounds, context: context }); particle.init(); system.addParticle(particle); } }
24/27

The particleSystem.js file can remain unchanged, but of course the HTML file will have to reflect new source files youve created. This example should function identically to the first two versions. Now youre ready to create the DOM version. The domParticle.js file will be almost as simple as canvasParticle.js. It assumes that there is an element it can position, and positions it using style properties: adc.domParticle = adc.particle.extend({ render: function() { if(this.element === null) { throw new Error(element needs to be set on particle); } this.element.style.left = this.x; this.element.style.top = this.y; } });

But in this example, the HTML file and main.js file will need to change significantly. In addition to referencing different source files, the HTML file can eliminate the canvas element and add a container div in which to put all the particle elements: <html> <head> <title>Particles v3</title> <style type=text/css> .html, body { margin: 0; padding: 0; overflow: hidden; } </style> </head> <body> <div id=container> </div> <script <script <script <script </body> </html> type=text/javascript type=text/javascript type=text/javascript type=text/javascript src=v3/particle.js></script> src=v3/domParticle.js></script> src=v3/particleSystem.js></script> src=v3/mainDom.js></script>

The main.js file will become mainDom.js and will obviously need to change a bit to create domParticles and give them individual elements instead of references to the canvass context.

25/27

(function() { var system, numParticles, container, bounds; function createElement() { var el = document.createElement(div); el.style.position = absolute; el.style.width = 3; el.style.height = 3; el.style.backgroundColor = #000000; container.appendChild(el); return el; } function initSystem() { system = adc.particleSystem.extend(); numParticles = 200; container = document.getElementById(container); bounds = { x1: 0, y1: 0, x2: window.innerWidth, y2: window.innerHeight }; } function initParticles() { var i, particle; for(i = 0; i < numParticles; i += 1) { particle = adc.domParticle.extend({ bounds: bounds, element: createElement() }); particle.init(); system.addParticle(particle);

function animate() { system.update(); system.render(); } initSystem(); initParticles(); setInterval(animate, 1000 / 60); }());
26/27

This makes use of a new function, createElement, that simply creates a div, styles it, and adds it to the container div. This is what the particle will position when its render method is called. This final example should be nearly identical to all the other versions. Of course, there are lots of optimization and enhancements that you can do to improve all of these examples. I purposely kept it simple to better illustrate the inheritance aspect.

Where to go from here


You may still prefer constructor functions and the new operator. Im not going to twist your arm about it. I personally find this method of object creation to be very clean and in accord with the basic prototypal nature of JavaScript. I encourage you to explore the source code provided in the sample files for this tutorial and try out the particle system in a browser that supports HTML5. As your needs for more complex apps grow, you can add features onto this basic setup far more cleanly than you can with an pseudo-class based system. For more information, see the following resources: - Douglas Crockfords Prototypal Inheritance in JavaScript - Douglas Crockfords Classical Inheritance in JavaScript - WOODY2SHOESs 005 JSJ Javascript Objects

ABOUT THIS ARTICLE


Keith Peters is a JavaScript and Flash / ActionScript developer in the Boston area. He writes books, speak at conferences, blogs and is an avid jogging & fitness expert. Keith is well-known for several books including Foundation HTML5 Animation with JavaScript http://www.bit-101.com @bit101

ONLINE RESOURCES Prototypal Inheritance in JavaScript http://javascript.crockford.com/prototypal.html Classical Inheritance in JavaScript http://javascript.crockford.com/inheritance.html JavaScript Objects http://javascriptjabber.com/005-jsj-javascript-objects/

appliness

DONT WORRY, BE APPLI

Ive been blogging a lot about Backbone.js recently. Backbone.js is a lightweight architectural framework that brings structure to your Web applications. Backbone is not, however, a user interface framework that helps you with the way your application looks.

Crafting Native LOOking IOS APPS WITH HTML, BACKBONE.JS AND PHONEGAP

So, where do you turn to for help when you need to make your application look good?

BACKGROUND
For traditional web apps (delivered through a browser), Twitter Bootstrap can help (read here). But what about Mobile apps? I explored Backbone.js + jQuery Mobile here. Depending on what you are looking for, it may or may not be the right solution: jQM provides mobile skins, but they dont look native. Its also more of a full stack framework than a lightweight UI toolkit that you can easily layer on top of your app. The alternative to using an existing UI toolkit is to roll your own styles to make your application look and behave like a native app. Sounds easy enough, but when you consider all the details and want to achieve pixel perfection, it becomes a daunting task.

d n u o laygr

p - Bootstra ile b o M y r e u - jQ p a G e n o h P -

Difficulty
- rookie - intermediate - expert

Todo list
- look native - perform - fire Jim
by Christophe Coenraets
28/29

As I was getting ready to tackle the challenge, and build a new native looking version of my Employee Directory app, I came across this great blog post by Chee Aun where he documents the process he went through to build his own Hacker News mobile app. His post is a real gem, and I ended up reusing a lot of the Hacker News app styles. Compared to the Hacker News app, the Employee Directory page flow is more random. Here are a few examples: 1. *-SearchPage -> EmployeePage -> ReportsPage -> EmployeePage -> 2. SearchPage -> EmployeePage -> EmployeePage (manager) -> Reports -> 3. SearchPage -> EmployeePage -> EmployeePage (manager) -> EmployeePage (managers manager) ->

As you can see, the page flow includes same page transitions, when the user navigates from one employee to his/her manager. To accommodate the Employee Directory page flow requirements, my Backbone.js infrastructure creates and destroys pages as needed with the appropriate slide-in/slide-out transitions. The implementation of these transitions was inspired by Wesley Hales article.

PhoneGap
Even though you can run this application in a browser (here), I built it with the intention of packaging it as a native app with PhoneGap so that you could start it like any other app from your iPhone home screen. If you are not familiar with PhoneGap, Ill provide more details on packaging this app as a native app in my next post.

Source Code
I updated the backbone-directory GitHub repository to include this version: It is available in the iphone directory.

ABOUT THIS ARTICLE


Christophe Coenraets is a Technical Evangelist for Adobe where he focuses on Mobile and Rich Internet Applications for the Enterprise. In his previous role at Macromedia, Christophe worked on JRun, the companys J2EE application server. http://coenraets.org/ @ccoenraets

ONLINE RESOURCES
JQuery Mobile official website http://jquerymobile.com/ Backbone.js official website http://documentcloud.github.com/backbone/ Backbone-JQuery mobile https://github.com/ccoenraets/backbone-jquerymobile

appliness

DONT WORRY, BE APPLI

using backbone.js with jquery mobile


bakcbone.js is an architectural framework that helps you write well-structured web applications. it is not, however, a user interface framework and it therefore doesnt help you with the way your application looks.

Backbones confined scope is a good thing: its lightweight, non-intrusive, not coupled to things you dont need, and it lets you use the UI toolkit of your choice or simply roll your own styles and widgets. In my previous post, I demonstrated how to use Twitter Bootstrap on top of Backbone.

QUEST FOR A MOBILE UI TOOLKIT


After that post, I wanted to create a mobile version of the same application; a version that I could package with PhoneGap and that would look and behave like a native app. Twitter Bootstrap can probably be tweaked for that purpose as well, but I was looking for a UI toolkit dedicated to providing native looking controls and behaviors on mobile devices.

d n u o laygr

- Backbone e l i b o M Q j M O D L M - HT

Difficulty
- rookie - intermediate - expert

Todo list
- catch event - use bootstrap - structure code
by Christophe Coenraets
30/33

ANOTHER WAY TO USE JQUERY MOBILE


jQuery Mobile (jQM) is one option that Ive explored before (here and here), but it fits more in the category of full-stack frameworks that tie together architectural structure and UI controls and behaviors. John Bender, my colleague at Adobe and member of the jQuery Mobile team, recently pointed out to me that you can disable the routing and navigation capabilities of jQM, and essentially use it as a pure UI framework on top of other architectural frameworks like Backbone.js.

SAMPLE APPLICATION
I ended up spending a decent amount of time trying different things to get the two frameworks to play well together without stepping on each other. To save you some headaches if you are trying to do the same, I put together a simple application with the basic setup to combine Backbone (for the application structure and routing) and jQuery Mobile (for its styles and widgets). NOTE: Another approach would be to use jQMs routing instead of Backbones. Ben Nolan has an example of this approach here. I prefer to use Backbones routing because I find it more flexible and less page-centric. Here is the app:

Click here to run the application in a separate window. The source code is available in this GitHub repository.
31/33

HOW IT WORKS
The key to this approach is to disable jQuery Mobiles routing: In other words, you need to tell jQuery Mobile not to handle links, hash tag changes, and so on. I isolated that code in jqm-config.js: $(document).bind(mobileinit, function () { $.mobile.ajaxEnabled = false; $.mobile.linkBindingEnabled = false; $.mobile.hashListeningEnabled = false; $.mobile.pushStateEnabled = false; }); If jQuery Mobile is not in charge of page navigation, you also have to manually remove the pages from the DOM when they are not used anymore. Here is one way to do it: $($(div[data-role=page]).live(pagehide, function (event, ui) { $(event.currentTarget).remove(); }); With this configuration in place, you use Backbones routing as usual: $.mobile.hashListeningEnabled = false; var AppRouter = Backbone.Router.extend({ $.mobile.pushStateEnabled = false; routes:{ :home, page1:page1, page2:page2 }, home:function () { this.changePage(new HomeView()); }, page1:function () { this.changePage(new Page1View()); }, page2:function () { this.changePage(new Page2View()); }, changePage:function (page) { $(page.el).attr(data-role, page); page.render(); $(body).append($(page.el)); $.mobile.changePage($(page.el), {changeHash:false}); } });
32/33

IS THIS THE RIGHT STACK?


I like the idea of a lightweight architectural framework combined with a UI toolkit. Backbone + Twitter Bootstrap felt right because the two frameworks have different areas of concern and complement each other very well. I was happy to see you could decouple jQM from its navigation infrastructure. However, thats probably not the main design center at this point. I think it would be interesting for jQM to focus on that utilization scenario as well. At the end of the day, frameworks are often a matter of personal preferences, and not all applications are equal. So try it, see if it works for you, and share your experience. What UI toolkit are you using?

SOURCE CODE
The source code is available in this repository on GitHub.

A MORE REAL-LIFE APPLICATION


In my next post, Ill share a Backbone.js + jQuery Mobile version of the Employee Directory application first explored with Backbone.js + Twitter Bootstrap.

Backbone & Twitter

JQuery & PhoneGap

JQuery Getting Started

John Bender

Ben Nolan

Sample App

MORE INFORMATION

>

ABOUT THIS ARTICLE


Christophe Coenraets is a Technical Evangelist for Adobe where he focuses on Mobile and Rich Internet Applications for the Enterprise. In his previous role at Macromedia, Christophe worked on JRun, the companys J2EE application server. http://coenraets.org/ @ccoenraets

ONLINE RESOURCES
JQuery Mobile official website http://jquerymobile.com/ Backbone.js official website http://documentcloud.github.com/backbone/ Backbone-JQuery mobile https://github.com/ccoenraets/backbone-jquerymobile

>

appliness

DONT WORRY, BE APPLI

I had heard about Handlebars from various people. Its also the templating engine that Ember.js uses. Handlebars works by allowing you to define templates using simple script blocks

Demo of Handlebars, and why you should consider a templating engine

a JavaScript templating engine


For a while now Ive been thinking I need to pick up, and start using, a JavaScript templating engine. I had used a jQuery-based one a few years back, but that project was abandoned and Ive yet to really look what - if any - solution would work good for me. Another reason Ive not found the time is that a majority of my JavaScript examples are small little demos built for blog posts. When I blog, I try my best to keep my code as simple as possible. I dont go all MVC just to demonstrate date formatting. It may not be real world, but it also keeps you focused on the topic Im trying to discuss. Today I made the time - and more specifically - made a demo. The demo is stupid. Its not even important. What is important is this: If youve ever used JavaScript to build strings of HTML, you never realized just how much of a pain that is until you dont have to. You never realized how resistant you are to adding new features - or tweaking the design. You never realized how much you held back - just because of how much of a pain in the rear it was!

d n u o laygr

s - Handlebar s e t a l p m e T - Ember

Difficulty
- rookie - intermediate - expert

Todo list
- shave - MVC - use gravatar
by Raymond Camden
34/40

Im probably being overly dramatic, but to me, it feels a lot like ORM. Yeah, its simple to go into a database client, open a table, and add a new field. But when you can do all of that via code... it feels incredibly freeing. You feel yourself trying new and interesting things. In fact, the demo Im going to show has about twice the features I was planning just because it was so damn easy to add. Thats how I feel today - and any day where my computer makes me smile is a good day. Ok, enough rambling. I had heard about Handlebars from various people. Its also the templating engine that Ember.js uses. Handlebars works by allowing you to define templates using simple script blocks, so for example, you can write your template in your document like so: <script id=result-template type=text/x-handlebars-template> <div class=entry> <h1>{{title}}</h1> <div class=body> {{body}} </div> </div> </script> You then use the Handlerbars API to create a template out of the block, apply data to it, and then render it to screen. Its all relatively simple, but the docs dont necessarily do a great job I think of demonstrating simple examples in full pages so you can see things in context. Here is a trivial example: <html> <head> <title>Test 1</title> <script src=js/handlebars-1.0.0.beta.6.js></script> <script id=result-template type=text/x-handlebars-template> <h2>Your Bio</h2> <p> Your name is {{firstname}} {{lastname}} and you are {{age}} years old. </p> </script> <link rel=stylesheet href=style.css type=text/css /> </head> <body> <h2>Render Simple Bio</h2> <input type=text id=firstname placeholder=First Name><br/> <input type=text id=lastname placeholder=Last Name><br/> <input type=number id=age placeholder=Age><br/> <button id=demoButton>Demo</button>

<div id=resultDiv></div> <script> document.addEventListener(DOMContentLoaded, function() { //Get the contents from the script block var source = document.querySelector(#result-template).innerHTML;

35/40

//Compile that baby into a template template = Handlebars.compile(source); document.querySelector(#demoButton).addEventListener(click, function() { var fname = document.querySelector(#firstname).value; var lname = document.querySelector(#lastname).value; var age = document.querySelector(#age).value; var html = template({firstname:fname, lastname:lname,age:age}); document.querySelector(#resultDiv).innerHTML = html; }); }); </script> </body> </html> Notice how Ive got a simple template block on top. If youve never seen Handlebars before, or any JavaScript templating engine, you can probably guess which portions of the block represent dynamic portions and which represent static text. Ive got a simple form with a button bound to a simple click listener. Looking at the JavaScript, you can see that first I have to grab the HTML from the template block. I then compile this. This gives me a template that I can reuse to generate output. My form has a simple click handler. When you hit the button, I pass the values to my template and grab the HTML out of it. You can play with this demo here:

36/40

dynamic templates
Of course, not every template will be a simple set of keys and values. Your template may also need to be dynamic based on the values passed in. Lets look at another example that makes use of both lists and conditionals. <html> <head> <title>Test 2</title> <script src=js/handlebars-1.0.0.beta.6.js></script> <script id=result-template type=text/x-handlebars-template> <h2>Your Favorite Things</h2> {{#if things}} <ul> {{#each things}} <li>{{this}}</li> {{/each}} </ul> {{else}} <p> Apparently, you like nothing. Poor you. </p> {{/if}} </script> <link rel=stylesheet href=style.css type=text/css /> </head> <body> <h2>List of Things</h2> <p> Enter a comma-separated list of things you like. </p> <input type=text id=things placeholder=Things you like...><br/> <button id=demoButton>Demo</button> <div id=resultDiv></div> <script> document.addEventListener(DOMContentLoaded, function() { //Get the contents from the script block var source = document.querySelector(#result-template).innerHTML; //Compile that baby into a template template = Handlebars.compile(source); document.querySelector(#demoButton).addEventListener(click, function() { var things = document.querySelector(#things).value;

37/40

if(things.length) var arrThings = things.split(,); var html = template({things:arrThings}); document.querySelector(#resultDiv).innerHTML = html; }); }); </script> </body> </html> In our template, weve got two things going on here. First is a conditional that checks if things is a truthy value (truthy being one of the things that make JavaScript so fun). Within the true part of the conditional we use an each block to enumerate over a set of values. If you scroll down to the HTML/JavaScript, you can see Im just asking for you to enter a list of things you like. That value is split into an array and passed (if there were values) to the template. Demo is below:

38/40

custom functions
Lets look at one more example. One of the cooler aspects of Handlebars is that you can add custom functions to the engine. For example, you could write a cowbell function that wraps your results in the beautiful rocking sounds of the cowbell. Ok, maybe not that. But what about something a bit complex - like converting an email address into a MD5 hash that could be used for Gravatar? Yeah - no way that would work... <html> <head> <title>Test 3</title> <script src=js/handlebars-1.0.0.beta.6.js></script> <script src=js/webtoolkit.md5.js></script> <script id=result-template type=text/x-handlebars-template> <h2>You and Your Gravatar</h2> <p> Your email is {{email}} and your gravatar is:<br/> <img src={{gravatarurl email }}> </p> </script> <link rel=stylesheet href=style.css type=text/css /> </head> <body> <h2>Enter Email Address for Awesomeness</h2> <input type=email id=email placeholder=Email goes here...> <button id=demoButton>Demo</button> <div id=resultDiv></div> <script> document.addEventListener(DOMContentLoaded, function() { //Tip on using Gravar with JS: http://www.deluxeblogtips.com/2010/04/getgravatar-using-only-javascript.html Handlebars.registerHelper(gravatarurl, function(email) { return http://www.gravatar.com/avatar/ + MD5(email) + .jpg?s=250; }); //Get the contents from the script block var source = document.querySelector(#result-template).innerHTML; //Compile that baby into a template template = Handlebars.compile(source); document.querySelector(#demoButton).addEventListener(click, function() { var email = document.querySelector(#email).value; if(!email.length) return;
39/40

var html = template({email:email});

document.querySelector(#resultDiv).innerHTML = html; }); }); </script> </body> </html> Notice in the template we have one simple value, email, and then this: gravatar email. This isnt something built into Handlebars, but rather, injected via the registerHelper function you see in the main script block of the page. The demo is below:

ABOUT THIS ARTICLE


Meet Raymond Camden. He is a 38 year old married father of three living in beautiful Lafayette, Louisiana. Ray is a developer evangelist for Adobe where his primary technical focus is ColdFusion, jQuery, Flex, AIR and the mobile space. http://raymondcamden.com/ @cfjedimaster

ONLINE RESOURCES Full tutorial with code http://www.raymondcamden.com/index.cfm/2012/4/19/Demo-ofHandlebars-and-why-you-should-consider-a-templating-engine Handlebars http://handlebarsjs.com/ Ember http://emberjs.com/

appliness

DONT WORRY, BE APPLI

Real-time data exchange in html5 with websockets

the websocket api is one of the more powerful new features in the html5 specification because it opens the door to real-time communication and pushing messages. This article describes a basic chat program that shows the basics of websockets and how to implement them on the client side.

USING WEBSOCKETS
The WebSocket API has been somewhat volatile over the past year as the W3C specification has been solidified. It has finally been completed and the specification can now be implemented consistently across browsers. Why use WebSockets? Instead of using the HTTP protocol, WebSockets use their own protocol. There is a significant amount of overhead incurred whenever communication over HTTP happens. Because of the request/response mechanism and all of the information that HTTP stores in header information, exchanging even basic information can result in lots of data being sent back and forth. WebSockets, by contrast, are full duplex, which means they can communicate back and forth at the same time without the request/response overhead. The header information is also much smaller, so the bulk of the data being exchanged is the actual data from the application.

d n u o laygr

- real-time s e g a s s e m - sockets

Difficulty
- rookie - intermediate - expert

Todo list
- hike - build a chat - read the spec
by Ryan Stewart
41/47

Browser Support for WebSockets Most of the major browsers now support some version of WebSockets. Firefox, Chrome, and the latest version of Internet Explorer all have added support for the WebSocket API. Safari and Opera offer partial support for the API. One of the major issues is understanding which draft of the WebSocket spec is supported by the browsers. Wikipedia has a good entry that lists the specifications by version number and which browser versions support them; for details, visit http://en.wikipedia.org/wiki/WebSocket#Browser_support. Going forward, the final version of the specification, RFC 6455, is the one that will be implemented. Setting Up a Server When working with WebSockets, you need to have a server that supports them. Complete instructions for configuring a server that adheres to the WebSockets specification are beyond the scope of this article, but its an important enough topic to address at least briefly. There are a few different ways to potentially implement WebSockets. PHP ships with built-in support for WebSockets, so you could write your own PHP socket server that handles the requests and responses from the client code. There are also Java and Ruby projects that provide WebSocket support for those languages. One of the more interesting ways to get up and running is a project called Socket.io that runs on Node. js. It has server-side and client-side libraries that make using WebSockets very easy. Node.js lets you use JavaScript on the server so the client- and server-side languages can be the same. For basic socket testing, websocket.org hosts a test server at http://websocket.org/echo.html that will simply send the transmitted data as a response back to the client. The server I use comes from Kevin Hoyt who wrote a socket server using Adobe AIR. For details, see the AIRWebSocket project on Github.

Connecting to a WebSocket Server


The core of the WebSocket API is the WebSocket class, which provides the methods and events that handle all of the communication with the server. It is important to have your code first check that the browser supports WebSockets. The quickest way to do this is to see if window.WebSocket exists. A more powerful solution is to use the Modernizr library, which helps detect support for WebSockets while providing a graceful fallback for older browsers. The example chat application provides a Connect button that the user can use to initiate the connection to the socket server. This process is implemented in a connect() function: var connection = {}; function connect() { if(window.WebSocket != undefined) { if(connection.readyState === undefined || connection.readyState > 1) { connection = new WebSocket(ws://localhost:1740); } } }
42/47

The first line of code above defines the connection object that will be used by the rest of the application. When you make it a global variable, the connection object can be used in other functions. After checking to make sure that the browser supports WebSockets, the code checks to make sure there isnt already a connection active. The WebSocket object provides a readyState property that indicates the connections ready status. The values are as follows: const const const const unsigned unsigned unsigned unsigned short short short short CONNECTING = 0; OPEN = 1; CLOSING = 2; CLOSED = 3;

As long as the readyState is greater than 1, the connection isnt open so the application can connect to the socket server. Connecting to the server is just a matter of instantiating the WebSocket class and passing in the URL and port number of the socket server. The browser then makes a connection with the server. Handling the WebSocket object in Firefox The WebKit browsers and Opera handle WebSockets in the same way, but in Firefox the WebSocket object has a prefix; it is referred to as MozWebSocket. Beyond that, the APIs are the same, so an easy way to keep everything simple is to check for the existence of window.MozWebSocket and then set it to the regular WebSocket object. if (window.MozWebSocket) { window.WebSocket = window.MozWebSocket; } The open event If the connection is successful, the browser will fire an open event. To make sure this gets caught, the WebSocket API includes an onopen property, which is assigned to a function that will run code for every open event. The code below sets the onopen property to a corresponding onopen() function that sets a couple of variables so that the UI is updated to indicate that the user is logged in. window.WebSocket Here is the onopen() function: function onopen (event) { document.getElementById(connected).innerHTML = Connected; document.getElementById(chat).innerHTML = You have joined the chat<br />; } Note that most people dont actually assign those methods to named functions but rather include them in anonymous functions right where they are first defined. I have implemented it this way because I like having the separation, but it may seem a bit redundant to you as you dig into more WebSocket examples.
43/47

Managing Data
Now that your client is connected you can start dealing with actual chat messages. The server I have set up for the moment just cycles through all of the currently connected users whenever it gets a message and then sends that message out to all of those users. Though it is a pretty basic chat server, it illustrates many key WebSocket concepts. Sending messages With WebSockets you can send text, or UTF-8 data, as well as binary data such as pictures or videos. They both use the same API on the client side, but it will largely depend on the server to actually handle the data types correctly. To send a message to the socket server the chat application simply invokes the send() method of the connection object. It takes a single parameter, the message being sent, which it passes to the socket server. When the user clicks on the Send Message button in the chat application, the sendmessage() method sends the message typed by the user along with the username. The socket server will then loop through all the clients, including the sender, and deliver the message to them. function sendmessage() { var messagetext = document.getElementById(chatmessage).value; messagetext = username + : + messagetext; connection.send(messagetext); }

Receiving messages To handle incoming messages, the WebSocket API uses the onmessage property of the connection event. Just like the onopen property covered earlier, this property takes a function that will be called whenever a new message arrives. So the first step is to set up the event handler in the original connect() method right before the onopen definition: connection.onmessage = onmessage; Once that is set up, define the onmessage() function: function onmessage (event) { var chatdiv = document.getElementById(chat); chatdiv.innerHTML = chatdiv.innerHTML + event.data + <br />; } The event that is received by onmessage is of type MessageEvent . It includes a data property that has the value of the message being received. In this case, that is used to display the chat text. This data property includes the username of the chat participant along with the message they sent. This value is appended to the chat div window.
44/47

Handling errors Error handling is an important topic to cover, even if only quickly. Along with onopen and onmessage, the WebSocket API also includes an onerror property, which takes a function that runs any time an error occurs. The error event includes a data property that provides some information about the error. Here is the basic error handler used in the chat application: function onerror(event) { console.log(event); document.getElementById(chat).innerHTML = There was an error: + event. data; }

Going binary
By enabling the exchange of real-time data, the WebSocket API opens some interesting possibilities when combined with the rest of the host of new HTML5, JavaScript, and CSS3 features. One of the cooler demos Ive seen is a collaborative whiteboard using the canvas element. Every time someone connected to the socket draws on it, a message gets sent out to the connected clients so everyone can see what is being drawn. Its a neat idea, but all thats really happening under the hood is that the socket server and application are exchanging a set of x and y coordinates in text. To illustrate the binary capabilities of the WebSocket API, I implemented a similar application that uses binary data. Specifically, I implemented a quick canvas painting feature that the user can use to draw something on a small canvas area. When the user clicks a button, the application does not send a set of coordinates to the socket server, but rather takes a snapshot of the image and sends it as binary data to the socket server. The socket server sends the data back as an image, which will appear in the chat window of all connected clients. This demo will only work in the latest version of Chrome because binary WebSocket support is still somewhat on the cutting edge. Creating binary data To send and receive binary data correctly you need to set up a binaryType for the WebSocket API. The binaryType can be either arraybuffer or blob , which are the two basic binary types that JavaScript supports. You can use either one depending on what youre sending and how you want to access it. I found arraybuffer to be ideal for this example because its easy to iterate through an array, and I found that I had to copy a lot of data back and forth between arrays. So the WebSocket setup code becomes this: connection = new WebSocket(ws://localhost:1740); connection.binaryType = arraybuffer; connection.onopen = onopen; connection.onmessage = onmessage; connection.onclose = onclose; connection.onerror = onerror;

45/47

Now you need to get binary data out of the canvas. I wrote a sendphoto() method that does the work of pulling the binary data out of the canvas element on the page. It uses the getImageData() method to get the actual binary array data and then it loops through the data and inserts it into a Uint8Array. The code accesses the buffer property of this array and sends it using the WebSocket API. function sendphoto() { imagedata = context.getImageData(0, 0, imagewidth,imageheight); var canvaspixelarray = imagedata.data; var canvaspixellen = canvaspixelarray.length; var bytearray = new Uint8Array(canvaspixellen); for (var i=0;i<canvaspixellen;++i) { bytearray[i] = canvaspixelarray[i]; } connection.send(bytearray.buffer); context.fillStyle = #ffffff; context.fillRect(0, 0, imagewidth,imageheight);

That data goes to the socket server and the socket server sends the binary data back out to all of the connected clients. If youre interested in seeing how the server does that, you can take a look at the Github project for the code. Receiving a binary message To handle incoming binary messages, youll need to modify the onmessage() function. Because youll have to handle two types of data, the ArrayBuffer and the String data, youll want to check the instanceof property of event.data and route the data accordingly. Once you do that, the process will be to translate the ArrayBuffer data into a typed JavaScript array. Then, create a temporary Canvas element that is used to insert the ArrayBuffer data by manipulating the image data of the canvas. Finally, with the image stored in the temporary canvas, use the toDataURL() method to get a URL string that you can set as the source of an img element, which then gets displayed on the screen. if(event.data instanceof ArrayBuffer) { var bytearray = new Uint8Array(event.data); var tempcanvas = document.createElement(canvas); tempcanvas.height = imageheight; tempcanvas.width = imagewidth; var tempcontext = tempcanvas.getContext(2d);
46/47

var imgdata = tempcontext.getImageData(0,0,imagewidth,imageheight); var imgdatalen = imgdata.data.length; for(var i=8;i<imgdatalen;i++) { imgdata.data[i] = bytearray[i]; } tempcontext.putImageData(imgdata,0,0); var img = document.createElement(img); img.height = imageheight; img.width = imagewidth; img.src = tempcanvas.toDataURL(); chatdiv.appendChild(img); chatdiv.innerHTML = chatdiv.innerHTML + <br />;

And with that, youre sending and receiving text and binary messages with the WebSocket API.

Where to go from here


This tutorial provided an introduction to the WebSocket API and how to use it. Even though the API itself is pretty straightforward, there are a surprising number of great uses for it. Everything from basic chat to real-time games or enterprise dashboards that need real-time data can all rely on the WebSocket API for their communications. Mozillas Developer Network has some great content on WebSockets that applies to both WebKit and Firefox; visit https://developer.mozilla.org/en/WebSockets for details. Also take a look at Socket.io, which is great way to get started with WebSockets without having to write much code on the server to make the connections happen. Explore the sample files for this article for the client-side source code. Youll need both it and the AIRbased socket server from Github to get the application to work. The client-side code by itself should give you a good idea of how to use the WebSocket API for any socket server that supports binary data.

+ This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License. Permissions beyond the scope of this license, pertaining to the examples of code included within this work are available at Adobe.

MORE INFORMATION

>

>

appliness

DONT WORRY, BE APPLI

Swipe to delete items with jquery mobile on touch devices


getting closer to native behavior

The swipe gesture has been broadly used on list to remove items, especially in native ios applications. lets code this behavior with jquery mobile.

Hybrid applications raise a lot of UI and technical challenges. Using web standards, developers are working hard to reproduce native UI behaviors without impacting the global performance of their application. The swipe gesture is one of them. Today, jQuery Mobile handle swipe events which are triggered when a horizontal drag of 30px or more occurs within 1 second duration. But these thresholds can be configured. To play with this event, well use a simple jQuery Mobile list and manage a two-step deletion task. First, the user will swipe on an item. Then, an active delete button appears to confirm the deletion. The swipe gesture is ideal for actions that requires an user confirmation.

d n u o laygr

e l i b o m y r - jQue s s a l C e l g g - To - Events

Difficulty
- rookie - intermediate - expert

Todo list
- swipe left - buy milk - try on iOS
by Michal Chaize
48/52

PLAY WITH the final application


Here is the running sample of this tutorial. Its a simple HTML page that creates a list of items from an XML file. If you swipe your finger on an item, a delete button appears. If you press the delete button, the row will fade out and be removed from the list. Try it! How does it work? The delete buttons are hidden with a height of 0px. Well use the toggleClass method to modify the style of a delete button when a swipe item is triggered. The project contains two files, an HTML page and a JavaScript file. Click on this icon to get more details about a section of the code:

try
i

me

Ready for some code? Go to the next page of this tutorial.

LOADING THE APPLICATION

49/52

THE HTML PAGE

<html> <head> <meta http-equiv=Content-Type content=text/html; charset=UTF-8 /> <title>swipe</title> <link type=text/css rel=stylesheet href=http://code.jquery.com/mobile/1.1.0-rc.1/jquery.mobile-1.1.0-rc.1.min.css/> <script src=http://code.jquery.com/jquery-1.7.1.min.js/></script> <script src=http://code.jquery.com/mobile/1.1.0-rc.1/jquery.mobile-1.1.0-rc.1.min.js></script> <script type=text/javascript src=myScript.js> </script> <style> div.menu{ height: 0px; overflow:hidden; position:absolute; top:0; right:0; -webkit-transition: all 0.2s ease-in-out; } div.menu.active { position:absolute; top:0; right:0; width:160px; height:50px; } .myItem{ height:40px; vertical-align:middle; } .ui-btn{ width:140px; } .myItem.active{ color:#CC0000; } </style> <meta name=viewport content=width=device-width; initial-scale=1.0; maximum-scale=1.0; userscalable=0; /> </head>

<body> <div data-role=page id=page1> <div data-role=header data-position=fixed> <h1>Swipe events</h1> </div> <div data-role=content> <div class=list-questions> <ul data-role=listview id=listQuestions> </ul> </div> </div> </div></body></html>

i
50/52

THE javascript code

$( document ).delegate(#page1, pageinit, function() { $.ajax({ type: GET, url: questions.xml, dataType: xml, success: function(xml){ var i=0; var myItems = ; $(xml).find(question).each(function() { var titleQuestion = $(this).find(title).text(); myItems += <li id=listItem+i+><div class=myItem>+titleQ uestion+<div class=menu><a id=myButton+i+ data-role=button dataicon=delete data-inline=false>Delete</a></div></div></li>; i = i+ 1; }); $(#listQuestions).html(myItems); $(#listQuestions).listview(refresh); $(#listQuestions).trigger(create); addBinding(); } }); });

function addBinding(){ for(var j=0; j< $(#listQuestions li).size();j++){ $(#listItem+j).bind(swipe,function(event) { $(div.menu, this).toggleClass(active); $(div.myItem, this).toggleClass(active); }); $(#myButton+j).attr(index,j); $(#myButton+j).bind(tap,function(event) { theIndex = $(# + event.currentTarget.id).attr(index);

$(#listItem+theIndex).fadeOut(500,function(){ $(#listItem+theIndex).remove(); }) ; }); } }

51/52

tips from this tutorial


I hope that you enjoyed the tips inside the source of this tutorial. The main ones used to achieve this sample were: - ToggleClass() This is a very useful jQuery method to manipulate class attributes. The easiest way to define transitions between states in your HTML apps is to declare two CSS styles, declare a transition in the default one and use ToggleClass() on your elements. - .trigger(create) When you add elements dynamically within your code, you may want to force jQuery to start again the analysis of your DOM elements. - .attr(index,j) Its an easy to flag your dynamically added HTML elements. attr() sets attributes to a set of elements. - Use pageInit(), not $document.ready() The first thing you learn in jQuery is to call code inside the $(document).ready() function so everything will execute as soon as the DOM is loaded. However, in jQuery Mobile, Ajax is used to load the contents of each page into the DOM as you navigate, and the DOM ready handler only executes for the first page. To execute code whenever a new page is loaded and created, you can bind to the pageinit event. - Swipe event (from the jQuery mobile documentation) Triggers when a horizontal drag of 30px or more (and less than 20px vertically) occurs within 1 second duration but these can be configured: - scrollSupressionThreshold (default: 10px) More than this horizontal displacement, and we will suppress scrolling - durationThreshold (default: 1000ms) More time than this, and it isnt a swipe - horizontalDistanceThreshold (default: 30px) Swipe horizontal displacement must be more than this. - verticalDistanceThreshold (default: 75px) Swipe vertical displacement must be less than this. - More swipe events You can also use the swipeleft and swiperight events. The swipe gesture is a classic on iOS, but the UI pattern is completely different on Android for instance. For each mobile platform, you need to learn the best UI best practices and discover how to code them using web standards. Thats a big challenge, but a funny one.

ABOUT THIS ARTICLE


Michal Chaize is a Developer Evangelist at Adobe where he focuses on Rich Internet Application and Mobile applications. Based in Paris, he works with large accounts that need to understand the benefits of rich user interfaces. Hes the editor in chief of Appliness. http://riagora.com/ @mchaize

ONLINE RESOURCES JQuery Mobile official website http://jquerymobile.com/ PhoneGap official website http://www.phonegap.com Using JQuery mobile themes http://www.adobe.com/fr/devnet/dreamweaver/articles/themecontrol-jquery-mobile.html

appliness

GET THE SOURCE CODE

Download the source code of all the tutorials ON YOUR DESKTOP:

http://appliness.com/code/02.zip

appliness

LIBRARY OF THE MONTH

app-UI is a collection of reusable application container user interface components that may be helpful to web and mobile developers for creating interactive applications using HTML and JavaScript, especially those targeting mobile devices.

APP-UI by andrew trice

app-UI is a continual work in progress it was born out of the necessity to have rich & native-feeling interfaces in HTML/JS experiences, and it works great with PhoneGap applications (http://www.phonegap.com). app-UI can easily be styled/customized using CSS. All of app-UI was created using HTML, CSS, & JavaScript. All animations are rendered using CSS3 translate3d, so that they are hardware accelerated (where supported). app-UI works well on iOS, Android and BlackBerry browsers (others not tested), and works well on the latest releases of most desktop browsers (I know it does not work on old versions of IE).

54/58

Why a new navigator?


You might be wondering why create this? when there are other open source alternatives like jQuery Mobile. The primary motivation for creating app-UI was to have reusable application containers that are highly performant, and do not force any prescriptive development paradigms. With respect to animations/transitions, app-UI outperforms the alternatives, particularly on mobile devices. app-UI can be used with many different existing frameworks app-UI only requires jQuery as a solution accelerator framework. It will work with existing UI widget frameworkss (jQuery UI, Twitter Bootstrap, etc), and will work with existing templating frameworks (Moustache, Knockout, Handlebars, etc).

Application Containers
app-UI currently has three application containers, and at this time it is not intended to be a complete UI widget framework.

ViewNavigator
The ViewNavigator component allows you to create mobile experiences with an easily recognizable mobile UI paradigm. You use this to push & pop views from the stack.

55/58

The ViewNavigator component allows you to create mobile experiences with an easily recognizable mobile UI paradigm. You use this to push & pop views from the stack. Some code used in the sample: $(document).ready( function() { //Setup the default view var defaultView = getView(); defaultView.backLabel = null; //Setup the ViewNavigator window.viewNavigator = new ViewNavigator( body ); window.viewNavigator.pushView( defaultView ); } ); function pushView() { //create a view and push it onto the view navigator var view = getView(); window.viewNavigator.pushView( view ); } function popView() { //pop a view from the view navigator window.viewNavigator.popView(); } function getView() { //create a view descriptor with random content var bodyView = $(<div> + Math.random().toString() + <hr><li href=# onclick=pushView() class=viewNavigator_backButton>push view</li> <li href=# onclick=popView() class=viewNavigator_backButton>pop view</li><hr> + getMeat() + </div>); var links = bodyView.find(a); return { title: Default View + parseInt(Math.random()*1000), backLabel: Back, view: bodyView }; }

56/58

SplitViewNavigator
The SplitViewNavigator component allows you to create tablet experiences with an easily recognizable mobile UI paradigm. The SplitViewNavigator allows you to have side-by-side content in the landscape orientation, and the sidebar is hidden in portrait orientation.

57/58

function getSidebarView() { var viewHTML = <ul> + <li onclick=pushSidebarView() class=viewNavigator_ backButton>Push Sidebar View</li> + <li onclick=window.splitViewNavigator.popSidebarView() class=viewNavigator_backButton>Pop Sidebar View</li> + <li onclick=pushBodyView() class=viewNavigator_backButton>Push Body View</li> + <li onclick=window.splitViewNavigator.popBodyView() class=viewNavigator_backButton>Pop Body View</li> + </ul>; return { title: Sidebar + parseInt( Math.random() * 100 ).toString(), backLabel: Back, view: $(viewHTML) }; } function pushSidebarView() { window.splitViewNavigator.pushSidebarView( getSidebarView() ); }

SlidingView
The SlidingView allows content to slide to the side using a horizontal swipe gesture, revealing a navigation container underneath. This is very similar to the behavior in Facebooks iPad application. Just swipe horizontally with a finger:

DOWNLOAD AND CONTRIBUTE


No software is ever bug-free. If you encounter an issue, have feedback, or have feature requests, please log them at: https://github.com/triceam/app-UI/issues or fork it, fix it, and send me a pull request. You can see this framework in the following real-world apps: US Census Browser: http://itunes.apple.com/us/app/us-census-browser/id483201717?mt=8 http://tricedesigns.com/census Get started with appiUI today! Just browse to http://triceam.github.com/app-UI/, read the details, download a copy, and start building your own apps! If youre building something cool with it, then let me know! Id love to hear about it.

MORE INFORMATION

>

>

appliness

APPLINESS FOCUS GROUP

HTML5 multimedia components Part I: overview


Interview of Ian Devlin
Hi Ian. Youve been working on web technologies for more than 10 years. Can you introduce yourself to our readers? Hi Michael and thanks. Well I havent always worked with web technologies as I initially started off as a software developer for a speech recognition company where I was working with the C programming language. During my time at that company I did become interested in web technologies though, as we were creating team intranet sites and I was a part of that. It led me to look for a more web development role for my next job (after being made redundant) and I ended up working for the games company Jagex as a web developer working with Java and of course HTML, CSS and JavaScript. I then (erroneously) moved away from web development for a short while before realising that it was where I wanted to be and Ive been doing it ever since. I first became interested in HTML5 at the end of 2009, and have been using it since then. I was also lucky

IAN DEVLIN, THE AUTHOR OF HTML5 Multimedia: Develop and Design explains how to use the HTML5 VIDEO AND AUDIO ELEMENTS, AND HOW TO CREate custom playback components.

enough to write a book on HTML5 Multimedia with Peachpit. What are you currently working on? Nothing special est. Ive re c e n t moved Germaso Ive b e e n concentrating on settling in here and trying to improve my German. That said, I did find the time to redesign my to be hono n l y l y t o ny

website, including a custom built Wordpress theme (based on HTML5 Starkers though which sped up the process!). In addition my job requires learning some new technologies such as TYPO3 which is used a lot in Germany so I have that to do too. I am trying to find some personal project to work on though, so if anyone needs a co-conspirator... Youre a recognized HTML5 expert, especially when it deals with Multimedia elements such as video and audio. Why did you focus on this topic? It happened by accident! I curate for HTML5 Gallery and Peachpit, now my publisher, who were looking for someone to write a book on HTML5 multimedia and they approached us. Writing a book was something I had never thought about doing before but I thought that this would be a good opportunity so I went for it. I knew the basics of using HTML5 multimedia already of course, but there were other related topics that I had to learn in order to be able to write about them. This was ideal though as I would read about something, test it, and then write about it in an orderly fashion while it was still fresh in my mind. So it wasnt planned and I focused on it as I had a book to write! Apple encouraged the use of the HTML5 video tag when they launched devices without Flash. What has evolved since this positioning that happened 2 years ago? Do you feel that HTML5 is rapidly growing and evolving to broadcast multimedia content? I think a lot of developers were already aware of HTML5 multimedia and the <audio> and <video> elements, but Apples announcement probably increased this number (of developers) but also brought it to the attention of nondevelopers who suddenly had to find another method of delivering video and audio to Apple devices. A number of related JavaScript APIs which utilise HTML5 multimedia are currently being developed that allow more advanced audio manipulation and also the ability to access a devices web cam (e.g. Opera have re-

leased a demo of this). Eventually it will probably be possible to have video conferencing in the browser using HTML5 alone. In your opinion, what should be improved in the current HTML5 specifications for multimedia content? The issue of DRM is a big one for some companies who have a business requirement for protected content. Not everyone agrees with this requirement, but I feel thats a moot point as you wont change that mindset for a long time. This has restricted these big companies from using HTML5 multimedia and I think that something to facilitate these companies requirements should be added. That said, there is currently a proposal to explore this topic and potentially either add it to the HTML5 specification or create a separate but related specification that supports it. Whether you agree with DRM or not, its addition would increase take up. Do you have in mind an amazing HTML5 multimedia experience that we could share with the readers? I dont know about amazing, but I think there will come a time when the afformentioned video conferencing with configurable sound and automatic subtitles (if required) will be possible and quite useful. HTML5 already helps with subtitles via WebVTT and I think itll be possible to either have someone translating on the fly (in the same way subtitles are added to live TV programmes) and entering values that way. With some of the sound APIs being worked on, browser games and videos in general should hopefully be able to take advantage of all the capabilities of advanced sound systems (e.g., surround sound) through the browser. You blog, you also wrote a book... Would you say that sharing your knowledge is essential for you and for developers in general? Sharing knowledge is not essential, but definitely very useful. I cant count the number

of times Ive come across a problem, gone to Google and found that others have had the exact same issue and solved it. Even if the solution isnt presented, blog and forum posts can lead to discussions that will set you on the right track, or even off on a tangent to creating something else. As web develoeprs were constantly learning, especially from each other. Im a big fan of the music band called Justice. Now that we get the Audio and the Video elements in HTML5, should we get the Disco tag pretty soon? My first thought on reading that was that it would be similar to the <blink> tag that was deprecated in HTML5! Id envision it taking a number of images and flashing them to the screen with various filters...and that cant be a good thing! Interview by Michal Chaize

HTML5 Multimedia: Develop and Design


By Ian Devlin
One of the most exciting and talked about aspects of the HTML5 specification is the introduction of in-browser multimedia. Websites no longer have to rely on a third-party tool such as Flash or Silverlight to play video and audio. This book is an easy, approachable guide to building native HTML5 multimedia into a website, from the simplest addition to more advanced features. Its written in a simple, straightforward style thats not too techy, yet advanced enough for the more experienced coder who just needs to get up to speed on these powerful new capabilities. The books companion website provides all the examples in a working format for easy access and enhanced visualization for the reader.

Topics include: - Using Audio: How to add audio to web documents using the HTML5 audio element. - Using Video: How to add video to web documents using the HTML5 video element. - JavaScript API and Custom Controls: How to use the HTML5 Media JavaScript API to create custom controls for HTML5 audio and video. - Styling Media Elements with CSS: Shows how HTML5 media elements can be styled with CSS2.1 and CSS3. - Using Video with SVG: Shows how SVG and HTML5 video can work together. - Using Video with Canvas: Introduces the HTML5 canvas element and shows how HTML5 video and canvas can work together.

appliness

HTML5 multimedia components Part II: VIDEO

This new ability for browsers to provide native video has made it easier for web developers to add video content to their websites without having to rely on the availability of external technology.

THE VIDEO ELEMENT


As you are no doubt aware by now, one of the most popular and most talked about features of HTML5 is the ability to embed video content directly into your web pages without the need for a third-party plug-in such as Flash Player. This new ability for browsers to provide native video has made it easier for web developers to add video content to their websites without having to rely on the availability of external technology. With the limitations Apple has currently imposed on Flash technology for iPhones and iPads, the ability to deliver HTML5 video has become even more important. This tutorial introduces you to the video element, its attributes, and the different types of video that can be used with it. It is the first tutorial in a three-part series that covers the video element, the audio element, and custom controls for working with both elements.

d n u o laygr

APPLINESS FOCUS GROUP

Difficulty
- rookie - intermediate - expert

- HTML5 - Video - Codecs

Todo list
- encode - play - fallback

by Ian Devlin

62/68

Serving a video: A quick comparison of two techniques


If you were to set up a simple MP4 video to be played on a website using Flash Player, you might use the following code: <object type=application/x-shockwave-flash data=player.swf?videoUrl=myVideo.mp4&autoPlay=true height=210 width=300> <param name=movie value=player.swf?videoUrl=myVideo.mp4&autoPlay=true> </object> Using HTML5, you can use the following code: <video src=myVideo.mp4 controls autoplay width=300 height=210></video> Of course this HTML5 example is extremely simplified, but the functionality is the same and you can see just how much easier it is.

VIDEO CODECS
Video codecs are software that encode or decode video for a specific file format. Although the HTML5 specification initially mandated support for the Theora Ogg video codec, this requirement was dropped from the specification after it was challenged by Apple and Nokia. Sadly, this means that different browsers support different codecs, which sounds like a bit of a pain and it is. Recently, however, the situation has improved so that you actually only need to provide your video content in two different formats: MP4/H.264 for Safari and Internet Explorer 9, and WebM for Firefox, Chrome, and Opera. Firefox also supports Theora Ogg, but it has supported WebM since version 4. There is, of course, a way to define more than one video file for your video content, but Ill cover that a bit later.

VIDEO ELEMENT
The video element, which you use to embed the video into your web page, can include several different attributes, some of which are outlined in this table. Attribute src autoplay controls muted loop Description Provides the URL of the video file. Indicates that the video should be started automatically, where possible. Tells the browser to display its default video control set. Sets the videos initial audio state to muted. (This attribute is currently not supported by any browser.) Indicates that the video should be played continuously in a loop. (Firefox currently doesnt support this attribute.)
63/68

Attribute poster width height preload

Description Sets a default image to display instead of the videos first frame. Specifies the width of the video element in pixels. Specifies the height of the video element in pixels. Suggests to the browser how it should attempt to preload the video in question. It can have three possible values: - none: dont perform any preloading - metadata: only load the videos metadata, for example, duration - auto: lets the browser decide for itself (this is the default)

For example, if you want a video to play automatically and for the browser to provide the controls, you simply use: <video src=myVideo.mp4 autoplay controls></video>

THE SOURCE ELEMENT


The examples used in the previous sections use only one video file in one format, MP4. So how do you go about also serving a WebM video file? This is where the source element comes in. A video element can contain any number of source elements, which let you specify different sources for the same video. The source element has three attributes, as shown in this table. src type media The URL of the video source. The type of the video source; for example, video/mp4 or video/webm. The actual codec used can also be specified within this string. The intended media type of the video. Specified using CSS3 Media Queries, this attribute enables you to specify different videos (that are smaller in size and resolution, for example) for handheld devices.

To specify both an MP4 and WebM source for the same video, you could use the following code: <video autoplay controls> <source src=myVideo.mp4 type=video/mp4> <source src=myVideo.webm type=video/webm> </video> When a browser attempts to play the video, it will check the list of sources until it finds one that it can play. So Firefox will skip the MP4 source as it is unable to play it, but it will happily play the WebM source file. Note that in the previous example Ive removed the src attribute from the video element itself since the src attributes in the source element are being used instead. If you did specify the src attribute in the video element, it would override any src attributes in the source elements. If you wish, you can specify the exact codec that was used to encode the video file. This helps the brows64/68

er decide whether it can play the video or not. Its generally a better idea to simply provide the type and let the browser decide for itself, as often youre not sure of what codec was actually used. Should you wish to include the codec, you can do so as follows: <video autoplay controls> <source src=myVideo.mp4 type=video/mp4; codec=mp4a.40.2> <source src=myVideo.webm type=video/webm; codec=vp8> </video> Note how the codec is added to the type attribute, specifically the quotes used and the separation of the type and codec by a semicolon. When adding the codec to the type definition, its relatively easy to misplace the quotes, which will make the video unplayable because the browser will be unable to parse the source element. So, if you decide to specify the codecs explicitly, be careful.

LEGACY FALLBACK
Of course, youll also need to provide a solution for those users who continue to use a browser that doesnt support HTML5, such as Internet Explorer 8 and below. Since browsers ignore what they dont understand, legacy browsers such as Internet Explorer 8 will ignore the video and source elements and simply act as if they dont exist. You can take advantage of this behavior to provide an alternative method of displaying your video, either via a simple download link, or a third-party plug-in such as Flash Player. Building on the earlier example, you might provide a link to the same video as follows: <video autoplay controls> <source src=myVideo.mp4 type=video/mp4> <source src=myVideo.webm type=video/webm> <a href=myVideo.mp4>Download the video</a> </video> The legacy browser will only display the link to the video file download. Adding support for Flash Player is just as easy: <video autoplay controls> <source src=myVideo.mp4 type=video/mp4> <source src=myVideo.webm type=video/webm> <object type=application/x-shockwave-flash data=player. swf?videoUrl=myVideo.mp4&autoPlay=true> <param name=movie value=player.swf?videoUrl=mVideo mp4&autoPlay=true> </object> <a href=myVideo.mp4>Download the video</a> </video>

65/68

With this example, an older browser such as Internet Explorer 8 will display the video in Flash Player (if Flash Player is installed on the system) and also the download link. By providing a download link as well as a Flash Player fallback, youre giving users who dont have Flash Player installed a way access the video by downloading it and viewing it from their desktop.

Digital rights management


If youre concerned about people being able to download and freely share your videos, then HTML5 video may not be right for you. When you use any of the methods described in this article, you enable users to access the direct URL to your video files, which they can then freely download. There is currently no way to prevent this with HTML5. At some point in the future a standard method may emerge to handle digital rights management (DRM) in HTML5 itself, but currently there is no such method. For more information on HTML5 and DRM see the W3Cs HTML FAQs on this topic.

Video subtitling
The provision of subtitling for HTML5 video was initially part of the HTML5 specification. A file format called WebSRT was defined, and this format could be used to specify video subtitles using the popular SRT file format. Later renamed to WebVTT (Web Video Text Tracks), the subtitling specification was taken out of the HTML5 specification and given a specification of its own. A WebVTT file is a specially formatted text file with a .vtt file extension. The file itself must be UTF-8 encoded and labeled with the type/vtt MIME type. The file must begin with a WebVTT string at the top. Lines within the file are terminated by a carriage return (\r), a new line (\n), or a carriage return followed by a new line (\r\n). The file consists of a number of cues, which are used to specify the text and timing location within the video file of the subtitle in question. The basic format is as follows: WEBVTT [unique-cue-identifier] [hh]mm:ss.msmsms --> [hh]mm:ss.msmsms [cue settings] Subtitle text 1 [Subtitle text 2] ... The unique-cue-identifier is optional. It is a simple string that helps identify the cue within the file. The cue timing is given in a straightforward format, with the hour portion optional. Each cue can also have a number of cue settings, which are used to align and position the text. These are described in more detail below. Next follows the actual text of the subtitle, on one or more lines.
66/68

The individual cues for different time locations within the video file are set up in this way, with each cue block separated by a new line. Here is a short example: WEBVTT 1 00:00:10.500 --> 00:00:13.000 Elephants Dream 2 00:00:15.000 --> 00:00:18.000 At the left we can see... You can use the cue settings to specify the location and alignment of the subtitle text that is overlaid on the video. There are five such settings, as shown in this table. Cue setting D:vertical | vertical-lr L:value A:start | middle | end T:value S:value Description The text direction: vertical right-to-left or vertical left-toright. The line position, either in percentage values or a specific line number. The alignment of the text relative to the line. The text position, in percentage, relative to the video frame. The text size, in percentage.

For example, to position text at the end of the line, 10% from the top of the video frame, you would use the following cue settings: 2 00:00:15.000 --> 00:00:18.000 A:end L:10% At the left we can see... You can see how the WebVTT file can be built up in this way to add subtitles to an entire video. You may be wondering how you link your WebVTT file to your video. The answer is the track element. This element, which was also introduced in HTML5, lets you specify external text tracks for media elements such as video. Its attributes are shown in the following table. Attribute kind src srclang Description The type of content for the track definition. Can be one of: subtitles, captions, descriptions, chapters, metadata. The URL to the text track, in this case the WebVTT file. The language of the text track data.
67/68

label default

A user-readable label for the text track. If present, indicates that this text track is the default.

For example, consider a WebVTT file named english-subtitles.vtt that you want to attach to the video example used above. You could do this using the following code: <video autoplay controls> <source src=myVideo.mp4 type=video/mp4> <source src=myVideo.webm type=video/webm> <track src=english-subtitles.vtt kind=subtitles srclang=en label=English subtitles> </video> This ties the WebVTT file with English subtitles to your video. You can, of course, have multiple track elements within the video element. With the srclang attribute you can specify multiple WebVTT files that are in different languages to add subtitle support in multiple languages. (The default attribute can then be used to identify the track to use if the users preferences to not indicate a more appropriate track.) Unfortunately, no browsers currently support WebVTT directly, but there are a number of JavaScript libraries available that enable you to use the WebVTT file format and provide subtitles for your videos, including: - Playr - Captionator (CaptionCrunch version) - LeanBack Player - MediaElement.js All of these solutions support video subtitles, and some offer additional features. Browsers are beginning to add support with both Safari and Firefox making advancements towards support, and Microsoft have recently posted a demo on WebVTT which shows how serious vendors are about supporting WebVTT in the near future. You have seen how easy it is to add HTML5 video to your web pages and provide a fallback method using Flash Player to serve video content to legacy browser users. As powerful as it is, HTML5 video is not currently advisable for those wishing to protect their video content, as it provides no DRM capability. You also saw, briefly, how you will be able to add subtitles to your videos in the future, and how you can do it now via JavaScript libraries.

appliness

HTML5 multimedia components Part III: AUDiO

In this ARTICLE I cover the audio element, its attributes, and the different types of audio files that can be used with HTML5. Many of the concepts and techniques covered in the previous article for video apply to audio as well.

THE AUDIO ELEMENT


In the first article of this three-part series on working with HTML5 multimedia components, I focused on embedding video in web pages using HTML5. Of course, most videos include audio, and if you want to embed audio files into your web pages you can achieve this with HTML5 just as easily. In this article I cover the audio element, its attributes, and the different types of audio files that can be used with HTML5. Many of the concepts and techniques covered in the previous article for video apply to audio as well, so if youve read it then youll notice some similarities in this one.

d n u o laygr

APPLINESS FOCUS GROUP

Difficulty
- rookie - intermediate - expert

- HTML5 - Audio - DRM

Todo list
encode listen protect

by Ian Devlin

69/72

Serving aN AUDIO FILE: A quick comparison of two techniques


Before HTML5, if you wanted to embed an audio file into your web page, you had to use a third-party plug-in such as Flash Player. For example, to embed an MP3 audio file in your web page and make it available via Flash Player, you might use the following code: <object type=application/x-shockwave-flash data=player.swf?audioURL=myAudio.mp3&autoPlay=true height=27 width=320> <param name=movie value=player.swf?audioUrl=myAudio.mp3&autoPlay=true> </object> Using HTML5, you can you can be more succinct: <audio src=myAudio.mp3 controls autoplay></audio> This snippet of HTML5 code achieves the same result as the more verbose code for Flash Player: It embeds an audio file into a web page to play automatically. You can see just how much easier and neater HTML5 code can be.

AUDIO CODECS
I covered video codecs in Part 1 of this series, and it will come as no surprise to learn that many of the ideas carry over to audio codecs. The HTML5 specification initially had made support for the Ogg Vorbis codec mandatory, but Apple and Nokias challenge put an end to this. Browsers today support more audio codecs than video codecs, so you have more choices when deciding what to use: - Firefox supports Ogg Vorbis and WAV. - Safari supports MP3, AAC, WAV, and MP4. - Internet Explorer 9 supports MP3, AAC, and MP4. - Opera supports Ogg Vorbis and WAV. - Chrome supports all of the above. To cover all browsers that support HTML5 audio, you need to serve your audio in only two different formats: Ogg Vorbis and MP3. Its not advised to use the WAV file format as it doesnt compress very well if at all and therefore the file size can be quite large.

THE AUDIO ELEMENT


As youve seen, the audio element is used to embed audio files within a web page. Like the video element, it can have a number of attributes, some of which are listed in this table: Attribute src autoplay Description Provides the URL of the audio file. Indicates that the audio should be started automatically, where possible.

70/72

Attribute controls muted loop preload

Description Tells the browser to display its default audio control set. Sets the initial audio state to muted. (This attribute is currently not supported by any browser.) Indicates that the audio should be played continuously in a loop. (Firefox currently doesnt support this attribute.) Suggests to the browser how it should attempt to preload the audio in question. It can have three possible values: - none: dont perform any preloading - metadata: only load the audios metadata, for example, duration - auto: lets the browser decide for itself (this is the default)

For example, with the audio element and its attributes, you can use the following code to embed an MP3 audio file that starts playing on load, has a default set of controls, and loops repeatedly: <audio src=myAudio.mp3 autoplay controls loop></audio> I must point out that this example would likely be quite annoying to your users. Automatically playing a looping audio file is generally considered to be bad Internet etiquette.

USING THE SOURCE ELEMENT


As I noted earlier, youll need to provide audio files for at least two different codecs to cover all browsers that support HTML5. As with the video element, you use the source element to accomplish this. An audio element can contain multiple source elements, so you can provide your audio in multiple formats. Extending the previous example, you can specify both an Ogg Vorbis and MP3 source for the same audio content as follows: <audio autoplay controls> <source src=myAudio.ogg type=audio/ogg> <source src=myAudio.mp3 type=audio/mp3> </audio> When the browser parses the audio element, it will proceed through the list of source elements sequentially until it finds a file format that it can play. Once it does, it plays it and ignores any subsequent elements. In this case, Firefox and Opera would play the Ogg file. Chrome would also play the Ogg file, even though it is also capable of playing the MP3 file. Safari and Internet Explorer 9 would play the MP3 file. You can also specify the exact codec that was used to encode the audio file. This can help the browser decide whether it can play the content or not. Its generally a better idea to simply provide the type and let the browser decide for itself, as often youre not sure what codec was actually used. If you want to include the codec, you can do so as follows: <audio autoplay controls> <source src=myAudio.ogg type=audio/ogg; codec=vorbis> </audio>
71/72

Note how the codec is added to the type attribute, specifically the quotes used and the separation of the type and codec by a semicolon. As with specifying the video codec, its not difficult to make a formatting mistake here that will render the audio unplayable. So, if youre specifying the codecs explicitly, be careful with the syntax.

LEGACY FALLBACK
Not everyone uses a browser that supports HTML5. Older versions of Internet Explorer (version 8 and below), for example, are still quite popular. To support users who are using these browsers, you can use a third-party plug-in such as Flash Player to embed audio files, just as you would have before the arrival of HTML5 and native multimedia. Browsers disregard what they dont understand, so your HTML5 audio and source elements will be completely ignored by older browsers such as Internet Explorer 8. For example, you might use the following code to add a link to the audio file: <audio autoplay controls> <source src=myAudio.ogg type=audio/ogg> <source src=myAudio.mp3 type=audio/mp3> <a href=myAudio.mp3>Download the audio file</a> </audio> Older browsers will simply display the Download the audio file link and ignore the rest. To add fallback support via Flash Player (as well as the download link) you can use the following code: <audio autoplay controls> <source src=myAudio.ogg type=audio/ogg> <source src=myAudio.mp3 type=audio/mp3> <object type=application/x-shockwave-flash data=player. swf?audioUrl=myAudio.mp3&autoPlay=true> <param name=movie value=player.swf?audioUrl=myAudio. mp3&autoPlay=true> </object> <a href=myAudio.mp3>Download the audio file</a> </audio> Older browsers will display Flash Player and the download link, so users can choose how they want to access the audio. If a user doesnt have Flash Player installed they can still access your audio file via the download link. Note that you can use the same MP3 audio file with Flash Player, since it is fully capable of playing MP3 files.

Digital rights management


HTML5 currently does not support digital rights management (DRM). As a result, if you dont want users to be able to download your audio files, then HTML5 audio is probably not the right solution for you. HTML5 exposes the links to your audio files, so they are openly available for users to access the content. There is currently no way to prevent users from downloading HTML5 audio content, although its possible that in the future there will be.

appliness

HTML5 multimedia components Part IV: custom components

If you want to achieve a uniform look across browsers for your media controls, you can use the handy HTML5 media element API. You can create and style your own media control set using standard HTML and CSS and then use the media element API to hook it up to the audio and video elements you want to control.

THE MEDIA ELEMENT


This is Part 3 in a three-part series of articles on HTML5 multimedia. In Part 1 and Part 2, I covered the video and audio elements, respectively, and briefly showed how adding the controls attribute to these elements informs the browser to add a set of default controls to the media element in question. If you tried out the code for those tutorials, you may have noticed that the controls look different depending on the browser you are using. If you want to achieve a uniform look across browsers for your media controls, you can use the handy HTML5 media element API. You can create and style your own media control set using standard HTML and CSS and then use the media element API to hook it up to the audio and video elements you want to control. This tutorial describes the steps needed to gradually build up a custom media player, adding various features and functionality in the process, and using different API attributes, events, and methods. You can see the completed media player by downloading and exploring the sample files for this article.

d n u o laygr

APPLINESS FOCUS GROUP

Difficulty
- rookie - intermediate - expert

- HTML5 s t n e n o p m - co t p i r c S a v a J -

Todo list
- play - pause - rewind

by Ian Devlin

73/79

Getting started
To begin with, youll need to define a video element to use with the yet to be created media player: <video id=video controls> <source src=grass-in-the-wind-sma.mp4 type=video/mp4> <source src=grass-in-the-wind-sma.webm type=video/webm> </video> Youll notice that the controls attribute has been defined for the video, even though youre going to create your own. Since your custom controls will be built in JavaScript, youre going to turn the default controls off via JavaScript. That way, if a user has JavaScript turned off, theyll still be served with the browsers default control set. To turn the default controls off, you simply set the video elements controls attribute to false: <script> // Grab a handle to the video var video = document.getElementById(video); // Turn off the default controls video.controls = false; </script> And with that, youre ready to move on!

Adding play and pause functionality


The first and most basic requirement for any media player is the ability to play and pause the media in question. For this example, youll use a single button, which will serve as a play button when the video is paused (or stopped) and a pause button when its playing. <div id=controls> <button id=playpause title=play>Play</button> </div> Next, you need to create a JavaScript function that will do the work of changing the button title and starting or pausing the media. In this example, the function is named togglePlayPause(). Take a look at the full implementation below; a line-by-line explanation follows. function togglePlayPause() { var playpause = document.getElementById(playpause); if (video.paused || video.ended) { playpause.title = pause; playpause.innerHTML = pause; video.play(); } else { playpause.title = play; playpause.innerHTML = play; video.pause(); }}
74/79

To have this function invoked every time the play/pause button is clicked, you add it to the onclick event of the button: <button id=playpause title=play onclick=togglePlayPause()>Play</button> The first line of the togglePlayPause() function obtains a handle to the play/pause button itself, and assigns it to the variable playpause: var playpause = document.getElementById(playpause); Next, it checks the status of the video to see if its paused or ended, via the two attributes paused and ended. If the video is in either of these states, it then sets the buttons title and innerHTML attributes to pause and calls video.play() to start playing the video. If the video is not currently paused or ended, then you can assume it is already playing. In this case, the function sets the buttons title and innerHTML to play and calls video.pause() to pause the video. The buttons default text is play. When the button is clicked for the first time, the video will start playing and the buttons text will be changed to pause. Subsequently, when the pause button is clicked, the video will pause and the buttons text will be changed back to play. As youll see, the remaining functionality that youll add in this tutorial follows the same basic format: listen for an event from the video element, check the elements status, and then act on it via API methods.

Adding volume and mute buttons


Another vital piece of functionality for a media player is the ability to control the volume, including the ability to mute it altogether. To add a volume control, youll use one of the new HTML5 input types: range. This input type is usually rendered by the browser as a slider, which the user can move from left to right and vice versa, so its ideal for a volume control. You specify the minimum and maximum values for the range input via the min and max attributes. You use the step attribute to set the amount you want the sliders value to change when the sliders position changes. To create a volume control slider with a range between 0 and 1, and a step size of 0.1, you can use the following code: <input id=volume min=0 max=1 step=0.1 type=range /> When the slider is moved, you want to invoke a JavaScript function that will adjust the volume, so add an onchange event handler: <input id=volume min=0 max=1 step=0.1 type=range onchange=setVolume() /> Next, create a JavaScript function named setVolume(): function setVolume() { var volume = document.getElementById(volume); video.volume = volume.value; } This simple function obtains a handle to the volume slider and assigns its value to the video elements volume attribute.
75/79

Note: Firefox 7 doesnt support the range input type and displays a text field instead. Typing a new value in this text field (between 0 and 1) and moving the focus away from the text field will alter the volume in this browser. Adding a mute button is just as easy. Again, you start by defining a new button, this time with an onclick handler: <button id=mute onclick=toggleMute()>Mute</button> Next, create a function named toggleMute(): function toggleMute() { video.muted = !video.muted; } This function simply sets the video elements (Boolean) muted attribute to be the opposite of its current value. This toggles the mute status of the button. Easy!

Adding a progress bar


When a video is playing, users are accustomed to checking the progress bar to see how much has played and how much is left to play. To add a simple progress bar to your media player, you can use a div element and a span element. Specifically, you increase the width of the span element as the video progresses, using it to represent the amount played. <div id=progressBar><span id=progress></span></div> Of course, youll want to style these elements with simple CSS so that the progress can be seen easily: #progressBar { border:1px solid #aaa; color:#fff; width:295px; height:20px; } #progress { background-color:#ff0000; // red height:20px; display:inline-block; } Next, define a function that will update the progress bar by changing the width of the span element: function updateProgress() { var progress = document.getElementById(progress); var value = 0; if (video.currentTime > 0) { value = Math.floor((100 / video.duration) * video.currentTime); } progress.style.width = value + %; }

The first line of this function obtains a handle to the progress span element itself. It checks the value of the video elements currentTime attribute, which defines the current playback position, in seconds. If currentTime is greater than 0, and therefore the video has advanced, it calculates the current progress as a percentage using the video elements duration attribute, which contains the videos total length in seconds. Finally, it sets the CSS width of the progress span to this calculated value. With the play, pause, mute, and volume controls you used events such as onclick and onchange to invoke the appropriate functions. You cant use this approach with a progress bar, because it updates in response to video progress, not user interaction. The HTML5 media element API, however, raises a number of events that you can listen for and act upon instead. One of these is the timeupdate event, which fires every time the medias currentTime attribute is changed. (This attribute changes as the media is played.) In the JavaScript initialization code of your web page, add an event listener that invokes the updateProgress function when the timeupdate event fires: video.addEventListener(timeupdate, updateProgress, false); Now your progress bar will be updated as the video plays.

Listening for Events


The media element API defines a number of events that you can use in implementing a media player. For a complete list, see the W3Cs summary of media element API events. The following table shows several of the more commonly used events. Event name playing ended timeupdate play pause volumechange Description Raised when playback of media is ready to start after having been previously paused Raised when the media has stopped playing as it has finished Raised when the medias current playback position has changed Raised when the media that was previously paused is no longer paused and playback has resumed Raised when the pause() method has returned and the media has been paused Raised when the medias volume or muted attribute has changed

When youre adding custom controls, its good practice to listen for some of the available events to make sure your controls are always synchronized with the state of the video. How might the controls lose synchronization? Recall that you removed the default control set via JavaScript. It is possible, however, for a user to reenable these controls and use them to interact with the video. For example, in Firefox, a user can right-click the video, select Show Controls, and click Play or Pause. If a user did this and started a video playing, then the text on the play/pause button that you created would no longer accurately reflect the medias current state. Regardless of what mechanism is used to control the video, the appropriate events will still be raised. So you can listen for the pause and play events and act on them accordingly to keep your buttons in synch; for example:

video.addEventListener(play, function() { var playpause = document.getElementById(playpause); playpause.title = pause; playpause.innerHTML = pause; }, false); video.addEventListener(pause, function() { var playpause = document.getElementById(playpause); playpause.title = play; playpause.innerHTML = play; }, false); You should also listen for the ended event, so that when the video ends, the play/pause button is also kept up to date. You can do this by calling the pause() method on the video when the ended event is raised: video.addEventListener(ended, function() { this.pause(); }, false); Note: The reason you call the pause() method here is that it automatically causes the pause event to be raised which will in turn cause the code weve written above for the pause event handler to be called. You could indeed duplicate the code in the ended event handler, or, if you wanted to do something different or extra, you would define it here.

Adding a playlist
The final feature to add is a media playlist, which the user can use to change the video played in the media player. This is actually quite simple. First of all you define your playlist; for example: <ul id=playlist> <li><a href=# onclick=playlistClick(grass-in-the-wind-sma);>Grass blowing in the wind</a></li> <li><a href=# onclick=playlistClick(tree-in-the-wind-sma);>Trees blowing in the wind</a></li> </ul> There are two items in this playlist, and each calls a function named playlistClick() when clicked. This function takes a single argument: the stem of the video file it is to play (that is, the file name without the file extension). This function is defined as follows: function playlistClick(file) { var v = document.createElement(video); if (v.canPlayType(video/mp4) != ) { changeSource(file + .mp4); } else if (v.canPlayType(video/webm) != ) { changeSource(file + .webm); } return false; } This function first creates a temporary video element and then calls the canPlayType() method for each of the supported video types, which in this case are MP4 and WebM. After determining which file type the browser is capable of playing, it calls changeSource() with one argument, the file stem that

was passed into the function concatenated with the appropriate file extension. This function also returns false to prevent the element from following the link to the value of its href attribute. The changeSource() function is defined as follows: function changeSource(src) { resetPlayer(); video.src = src; video.load(); } This function calls resetPlayer(), which youll look at next, and then sets the video elements src attribute to the new video file that has been passed as an attribute. Finally, it calls load() to load the new video source into the video element. Note: Not all browsers require the load() method to be called, but Safari does. Therefore its a good idea to call it. The resetPlayer() function resets a few of the players components in preparation for loading a new video: function resetPlayer() { var playpause = document.getElementById(playpause); playpause.title = play; playpause.innerHTML = play; if (video.currentTime > 0) video.currentTime = 0; updateProgress(); } First, it sets the play/pause button text to play. Next it resets the video elements currentTime variable to 0 if its not already at 0. Finally it calls the updateProgress() function, which will reset the progress bar back to the start. (The progress bar uses the video elements currentTime attribute, which was just set to 0.)

Where to go from here


Thats it! Youve seen all the steps necessary to create a simple HTML5 media player. It is admittedly not the most attractive player available, but you can use CSS to style it and improve its appearance. To see more of the media element API, its events, and its properties in action, check out the W3Cs HTML5 Video Events and API demonstration page, which plays videos with basic controls and displays API properties and events.

Picture by Ade Oshineye

PAMELA FOX

To me, programming wasnt about math, it was about making apps that people could interact with, and thats what was so cool about it.

80/83

ee why this twenty-something-year old shy girl is asked to speak at conferences and user groups around the world...that is, when shes not reading, writing, coding or just generally horsing around.

Hi Pamela, its a great honor that you have agreed to an interview for the second issue of Appliness magazine (BTW, our first, of hopefully many, women interviewees). Can you introduce yourself to our readers? I'm a twenty-something-year-old living in San Francisco. I suppose I would be best described as a web developer, though I've never identified as one. I just like making stuff, and coding is my means to that end.

What do you think are some roadblocks in the way of developers effectively deciding on a mobile strategy? In preparing a talk on mobile app strategies a few months ago, I researched the different mobile app platforms out there and discovered that there are a huge number of them, with a variety of input languages, optimal use cases, and pricing models. But, the fact that there are so many of them and that theyre so new makes it hard for developers to pick one. A platform might look promising from the landing page, but it may play out very differently. Does it breakdown when you try to customize it? Does it perform horribly? Does with their support suck?

I graduated from USC in 2007 with a bachelors and masters in Computer Science, with minors in Linguistics and 3-D animation. After that, I spent 5 years in Google Developer Relations working on the widely successful Maps API, and the went ill-fated Wave API. (Hey, you win some, I you lose some). I recently left Google to PhoneGap and I When Im thinking of using a new platpursue my own projects and see what form, I take to Twitter and ask my followthey might turn into. I've been working achieve my goal of ers what they think of it, and Ill usually on a nutrition-tracking service (eatdifre-usability... get a handful of responses reporting on ferent.com) for almost a year now, and the good and the bad of it. But Im in since I offer both web (Python/AppEnthe fortunate situation of having a sizable number gine) and mobile (PhoneGap/HTML5) interfaces for of followers to ask, and most developers arent. it, it's been a great learning experience. On my blog a few months ago, I proposed what I called a yelp for developers - a review site for developer platforms, so you could see, at a glance, It sounds like you got an early start in the world of what other developers think about the platform beprogramming. How old were you when you really got fore you start developing with it. Id argue its more interested in computers and programming? important to have a yelp for developers than a yelp for restaurants, because hey, a meal only lasts a few On one fateful Mothers Day, I realised I did not hours, but an app can last months. Maybe Yelp will have a gift for my mum, and since we lived approxipivot. :) mately in the middle of nowhere, I didnt have an easy way to obtain a physical gift. We did have a What are some of the hidden gotchas when develT1 line in our house though (my dads a computer oping in the wide world of HTML5 and how have you scientist), and I was very aware of the internet - so learned to work around some of those issues? I decided Id make her a webpage. I Yahood for webpage making instructions and promptly preOne of the tricky parts of HTML5 is how varied its sented my mum with her digital gift. As soon as my support is. Its not like with a usual API, where you dad saw that I was interested in programming, he can say all features from version X onwards are spurred me on to learn more (real) languages like supported instead, you have this situation where Perl and Java. From then on, I was hooked, and the each browser supports a different subset of fearest is history. tures. Even the oft-maligned IE supports some features that other browsers dont - its not behind on How did you come to select PhoneGap for your everything. Worse, even when a browser technically supports an HTML5 feature, it may still perform mobile app strategy? How many other mobile app quite badly with it, like in the case of the Android platforms did you review in the process? Webkit browser and CSS3 gradients. In deciding how to build the mobile apps for EatDifferent, my goal was re-usability. I wanted to reuse as much of my app logic and assets as possible, and I wanted to re-use as much of my existing web development knowledge as possible. I didnt want to start from scratch on either front, and didnt feel like I had the time or motivation to become an expert Android Java and Apple iOS developer. So, I went with PhoneGap and I achieved my goal of reusability - about 90% of my code is shared across the web and mobile apps, and that means its easier for me to add new features to all the platforms at once. So, if youre a developer trying to use HTML5, you need to use something like Modernizr to check whether a feature exists, you need to use libraries that abstract on top of the feature across the different browsers, and you need to actually test your app in all the browsers and see both if it works and if it works fast enough. Two invaluable resources for HTML5 developers are the Modernizr wiki on HTML5 polyfills (https:// github.com/Modernizr/Modernizr/wiki/HTML5Cross-browser-Polyfills) and caniuse.com with upto-date browser support tables.

81/83

Do you think that cross-platform development makes sense? When should you go native instead of using web standards? It depends. Are you building an app that a user would only want to access on a mobile device? Or is it an app that users would want to access everywhere? Does the app need to be usable by everyone to be useful, or can you use it by yourself or with strangers? An app like Draw Something is very mobile-specific - someone is bored, they have their phone, they start a game with some random other person, and they draw with their touch screen. It makes sense for them to go the native route, as they dont have to target every platform, and they can then take advantage of native touch capabilities. But an app like Twitter needs to be cross-platform - people want to tweet from everywhere, and they want to tweet with everyone. It makes sense for them to go the route of web standards, since they can then serve apps on any platform that has a web browser and a way of entering text, and they dont need to worry about excluding users. I personally prefer apps that are accessible everywhere (I would totally Draw Something on my laptop), but each developer needs to decide for themselves how much to prioritize cross-platform development given their limited resources. Youve had a number of different roles in the developer/IT world, what are some of the highlights that were most beneficial to giving you the perspective for where you are today?

Now that Ive left that role and Im a free-range developer, I can appreciate the perspective that developer relations has given me, and when Im interacting with 3rd party APIs, I can put myself in their shoes. When I run into a bug, I try to actually post in their forum instead of simply ranting on Twitter, because I realize that they are busy too and they can get it fixed faster if its reported properly. Before I make a feature request, I try to think to myself whether that request is actually in line with their core mission and will be sustainable for them, and not just a niche request that would only satsify me. Basically, by being able to balance both perspectives in my head, I can be a more productive and useful developer of a 3rd party API. Weve been hearing a lot lately about User Experience. Can you share your thoughts on Developer Experience? How important is it, really, for companies, such as Facebook and others enjoying their view from the top, to provide a good developer experience with their APIs? Were now in a time when there are many companies out there that are purely dedicated to developer products - hosting platforms like Heroku and App-Forge, functional APIs like SendGrid and Twilio, services like Loggly and Pingdom. For those companies, their success depends solely on the success of their developer products, so they need to provide the best developer experience possible... and they generally do. But there are also many companies that provide both user-facing products and developer-facing products. Sometimes, the success of the user product is directly dependent on the success of the developer product. For example, Twitter might not be as popular as it is today if there werent so many alternative, 3rd-party clients built for it.

Actually, Ive technically only had one job in my life: Google Developer Relations. But, that job was probably the best possible job that I could get in terms of how much I learnt across so many different aspects. There was the technical knowledge: JavaScript, Maps/GIS, Flex, Python, App Engine, NonBut othertimes, its not obvious how much the user Relational Datastores, and even a bit of Java. But product depends on the developer product. Would even more valuable was the not so tangible Facebook still be the worlds biggest soknowledge: how to deal with developers in cial network today if they didnt provide a community (the good, the bad, the ugly), My first applet an API? Quite possibly, yes. And unforhow to prioritize feature requests, how to tunately, when a company is in the posiwas a virtual handle a bug that breaks thousands of tion of owning the social graph on the sites, how to organize events, how to write dress-up doll... web and theyre the only ones that can the most universally useful documentation, provide a reasonable API to that social how to give entertaining yet educational graph, then social app developers dont really have talks, the list goes on. a choice but to use the Facebook API, regardless Developer Relations is a mix of many jobs in one - something like 10% software engineer, 30% support engineer, 30% community manager, 20% evangelist, 10% product manager. Its a great role for someone starting out because it exposes you to everything at once, and it can help you figure out what aspects you like the most. And hey, if you like it all, you can work in developer relations for life. of the developer experience. Facebook has a monopoly, and they know it.

But, hey, if a company comes along that has a reasonable slice of the social pie and provides an amazing developer experience for their social graph API, they may be able to compete with Facebook. The web moves fast, well see!
82/83

How do you perceive Adobe and the work it has done in creating tools for developers now and throughout the years?

Okay, so Im going to steal the next 2 questions from your interview with your mum, What was the first line of code you ever wrote? That depends if were counting HTML as code... Asssuming not, my first script was a Mad Libs game written in Perl. My dad and I celebrated one New Years eve by writing the script, and running it just as the clock struck midnight. Yes, I come from a geeky family.

Now that I think about it, Ive been using Adobe or Adobe-acquired products since I was a kid, though not always for programming. When I was in middle school, I used to draw advertisements for my parents college classes using Aldus Freehand, the vector drawing program. In high school, I used AdoSo, in that case, my first line was probably: be Pagemaker and InDesign to layout the school #!/usr/local/bin/perl newspaper. At computer camp one summer, I discovered Adobe Flash and started making animations and Flash websites (and yes, they had aweHow do you think the fundamental differences in men and women play out in the IT industry? some intros). In college, I minored in 3-D animation and continued using Flash for animations and fun Well, I think its good to clarify that there are aclittle web toys, plus spent a year using PhotoShop tually fundamental differences between men and as a graphic designer for our on-campus events. women. It seems like people try to pretend that At Google, I was working on the Maps API team were the same in all regards, but were not. We when they came out with the Maps API for Flash, evolved to be optimized for different tasks, both which was significantly more powerful than the Jaour minds and bodies. vaScript API in many ways at that time, and I spent a year Men are generally better at math, seeing what I could do in Flex/ women are generally better with Pams Pams Eat AS4. And now, Im using the people - so in the IT industry, youll Blog Projects often find men playing the part of Different recently acquired PhoneGap for building mobile web apps. the engineer and women playing the part of the community managSo, wow, I think Adobe has er. If we want to see more women in the engineer been with me more than any other company, and role, then perhaps one way is to show women that curiously, the Adobe line of products has evolved engineering isnt *just* math. at the same rate as my personal interests. But now the web is moving faster and faster while Adobe is For example, I first learnt programming via Java getting bigger, so... applets, and my first applet was a virtual dress-up doll that I uploaded and shared with my friends. To me, programming wasnt about math, it was about In what ways is there still work to be done to make making apps that people could interact with, and HTML5 a valid solution for developing applications? thats what was so cool about it. When it comes to using HTML5 for making mobile web applications, were in need of better, faster debugging tools. We now have really amazing developer tools for desktop debugging, particularly in Chrome and Firefox, but when it comes to mobile, it sometimes feel like debugging in IE6. There are a few tools for remote debugging, like weinre and iOS remote inspector, and theres talk of better Webkit remote debugging in the future (http:// www.webkit.org/blog/1875/announcing-remotedebugging-protocol-v1-0/), but theyre still not on par with desktop tools - and there are times when all you can do is console.log or even alert. We also need a better testing solution for mobile web apps. We have great ways of running integration tests in the browser on our desktop, using tools like Selenium, but were not quite there when it comes to mobile (particularly mobile apps with embedded browser views, like PhoneGap). Once again, there are developers working on this, so theres hope for the (near?) future. So, when I teach people how to program, I try to show them the many ways that it can be used, because you never know what their mind will be most excited by. And I think thats how we can increase the diversity of the IT industry. Or one way, at least. What would you like to shout out to the developer world for a successful 2012? We all want to make the world a better place somehow, whether that means making an app that lets people play games with their friends or making an app that improves government efficiency. The faster we can make those apps, the faster we can reach our own idea of what a better world looks like. We can all make it easier for each other to build what we want if we share our knowledge and our code with eachother. So, please, when you learn something: share it, and when you write a bit of useful, reusable code: opensource it. Sharing is caring. :)

appliness

IS A WARM GUN

e want to showcase in this section the best mobile applications built with web standards. If you want to showcase your application, contact us by email - contact@appliness.net. This month, find clothes that match your tastes, discover cuuuuuute animals and build muscle thanks to PhoneGap.

Colour Match

by Anansi Web Development


The purpose of the app is to allow users to pick any colour using a colour picker tool and display clothing & accessories that match the colour from Online Shopping USA database. Features of the app include a colour picker, a selection of most popular colours for easy browsing, favourites where users can save their favourite products and email, facebook and twitter sharing. Anansi used jQuery Mobile 1.0.1, PhoneGap and PHP for the backend. They used three native APIs provided by PhoneGap: Twitter, ChildBrowser and the EmailComposer. It took about 4 weeks from the start of the project to the day the app became available on iTunes app store. Great performance and great design.

The colour picker works very well. Good usage of jQuery Mobile.
84/85

Michal

Christophe

Piotr

Cutest Paw
by Ho Man Cheung
Cutest Paw iPhone App is designed for those who love to see new cute animal pictures everyday. You will love the seamless way we display the pictures on your iPhone. User can search the cute animal pictures by keywords or categories. User can register a new account, and login to upload their cute animal pictures. You can take a picture or choose any pictures from your photo library. You can also track your uploaded pictures. Oh my god! Its so CUUUUUTE. The main screen is incredibly beautiful. A dynamic compisiting that really make a difference. The developer used jQuery Mobile and PhoneGap.

I was surprised at how much of a distraction this turned out to be. Great job!
Holly Greg Alan

Bit Timer
by Peiter Buick
This app is designed for the no-frills, hard-core workout. This is the first interval timer youll see with a set up that is this fast and easy. Your workout should be intense, not your workout set up. The clean design and simplicity of Bit Timer make it the perfect app for exercise enthusiasts. One of the best feature is that music automatically fades, allowing you to hear interval tones. The app uses smart drag and drop gestures to define the Work, Rest and Repeat parameters. The developers used PhoneGap to control the sound of the device.

Greg

Andy

Michal

As a techie who enjoys some cycling, this is app is a must-have!

WHICH ELEMENT ?

One of the main challenges we see in building semantic content is picking what tag to use when. WhichElement.com seeks to help with that. Now, lest we seem all judgy and preachy let me get a few beliefs out there: - A perfectly semantic site does not exist. - Even if it did, someone would disagree with its semantics. - Therefore semantics for semantics sake is pointless.

However, semantics are about more than just semantics for semantics sake. Semantics can be about accessibility, SEO, or just good developer to developer communication of intent. They can be used to create better hooks for CSS and DOM manipulation. Therefore we approach this site with the following in mind:

- Semantics exist along a continuum, something can be more or less semantic. - We encourage semantics, but not at the cost of reasonableless.

Our goal is to suggest things to help you make a good decision about what you should do to be semantic. We certainly dont think we have any authority to command you to do things to be absolutely semantic. by Terry Rian and Ray Camden Visit WhichElement.com

? . . . . . . .

<aside> or <blockquote> ?

Pull Quote

A pull quote is a fluffed up copy of a bit of the content on the current page. Its usually bigger and more visually distinctive than the rest of the body copy. A pull quote in most cases is used to emphasize a theme or point of a piece. The idea is that by presenting this block quote, readers can determine more quickly if they want to read the piece. Its a stylistic addition to a page that emphasizes content without actually adding concrete content.

Candidates
- <aside> - <blockquote> - Highlighted with CSS and HTML5, no semantic reference. The first issue to clear is, Is this a quote or a pull quote? An easy rule of thumb here is If you are repeating something that is on this exact page, its pull quote. Since it is not a quote, <blockquote> is inappropriate. The W3C specifically points out in their definition of <aside> that is intended for pull quotes: The element can be used for typographical effects like pull quotes or sidebars, for advertising, for groups of nav elements, and for other content that is considered separate from the main content of the page.

86/87

That should be an open and shut case. Shouldnt it?

However Maykel Loomans makes a great case in his article Pull Quotes with HTML5 and CSS that pull quotes are a display issue and not a content issue. If you buy into it, it means adding extra markup, and repeating content just to show a pull quote is semantically wrong. He makes a compelling case for it, and has an awesome solution. Just using HTML5 and CSS to style a pull quote. The article is great reading.

Verdict

The semantic nitpicker in me loves to point to Highlighted with CSS and HTML5. It might be a little kludgy on the CSS side but from a semantic and content point of view, its very elegant. That being said, the W3C says you can use <aside> which might be a bit more flexible in terms of styling.

Further Reading
Wikipedia > Pull Quote

Smashing Magazine > Block Quotes and Pull Quotes W3C > The aside element

Maykel Loomans on design, the web and other stuff nerds like > Pull Quotes with HTML5 and CSS

? . . . . . . .
MORE INFORMATION

Comments

Comments are basically just big lists of individual comments.

Candidates
<div> <dl> <ol> <section> <ul>

At first glace, one of the lists makes a good candidate. This is a big honkin list of comments. Semantically, the <ol> makes a strong showing as comments are usually listed in chronological order. You can choose to have the numbers part of the display of the items or style them away. Note, however, that it is hard to style the <ol> numbers independent of the text. It can be done, but involves adding more elements to the content. The <ul> is also a reasonable choice here. The <dl> might be semantically correct, but seems like youre just showing off your use of obscure elements. Not that there is anything wrong with that. You could go with a <div>. The w3c discourages using a <div> when there is a more specific element to use, and in this case you have several. A <section> refers to a group of related bits of content. A list of comments in a blog definately fit the bill.

Verdict
We recomend the <section>, containing either <ul> or <ol>.

Further Reading
Macrofolio > Style your lists

>

>

appliness

VIDEO TUTORIAL

phonegap and the file api

raymond camden demonstrates how to use the html5 file API with phonegap to start working with the file systems of mobile devices.

d n u o laygr

- PhoneGap m e t s y S e l i F - Storage

Difficulty
- rookie - intermediate - expert

Todo list
- store stuff - read & write - shave
by Raymond Camden

appliness

VISUAL AND JUICY

DECISION PATH TO PHONEGAP

in this article, i wont explain what is phonegap. Ill focus on where this technology fits in the mobile solutions landscape and when phonegap is relevant.

MOBILE

GROWING

WEB

IS

2013

2012

First, you need to choose the userexperience for your app. A classic page by page navigation or an application UX with tabs, footers...

x
Which mobile user-experience do you need?

The mobile Web is growing eight times the speed of the Internet

Classic Web UX
Links, Pages, navigation, text & images

ANSWERS

Application UX
Menu, Header, buttons, footer, tabs

- Responsive Design - Progressive enhancement - HTML5 & CSS3

ANSWERS

There are three ways to code a mobile app user experience, inside or outside the browser.

Web-app
DESCRIPTION

Hybrid
Hybrid apps are executed in the web view component of a native app (think of a headless browser). The app is coded with webStandard (HTML5, JS...). Hybrid apps are distributed as native apps on market places.

Native
A native application is coded with the native language of the mobile operating system (ObjectiveC for iOS, Java for Android...)

A Wep-app is executed in the browser of the mobile device. Its coded with web standards (HTML5, JS...)

ACCESS

To access a web-app, the user launches the web browser and types a URL.

Native apps are distributed on market places (app store, google play, appWorld...).

LIMITATION

Very limited access to HW features and APIs. You cant take a picture, store persistant data...

Full access to HW fea- Full access to HW and tures and APIs thanks native APIs. to native extensions (or plug-ins). The developer calls the native APIs with JavaScript commands. Developers need couple a mobile HTML framework (jQuery Mobile) and a mobile container framework such as PhoneGap to access native APIs with JS. Each platform provides specific SDK and IDE: ObjectiveC and Xcode for iOS, Java and Eclipse for Android...

SOLUTIONS

Developers need to use a mobile HTML framework such as jQuery Mobile.

?
GAME
inspired by Emmanuel le Valensi

Hybrid apps look cool. So whats the most challenging step?

In my opinion, the biggest challenge is to find a HTML framework that will simulate the user-experience of a native app. jQuery Mobile is a good candidate. Then, PhoneGap will expose native APIs in JavaScript (take a picture, accelerometer, File API...) and run your HTML code in a web-view (a kind of headless browser).

WHICH ONE IS NATIVE, HYBRID OR A WEB APP ?

PATH

FACEBOOK

LINKEDIN

same?

These 3 mobile apps have very similar user-experiences. They are all using application UI patters: menu, header, icons, tabs... But just one of them is native and written with ObjectiveC. Its Path, one of the most beautiful social application. Facebook is Hybrid, it has been written with HTML and JS. They used a distribution of PhoneGap to run it as a mobile application outside the browser and distribute it on app stores. LinkedIn is a pure web application. A wonderful HTML development that you can try on mobile. linkedin.com. That said, they just released an Hybrid app too. They just had to reuse their existing HTML code and package it as an mobile app with a technology such as PhoneGap.

What is PhoneGap?

a set of UI components to build mobile apps with HTML and JS

PhoneGap crosscompiles HTML and JS code to native code

a platform that allows you to author native applications with web standards

= Hybrid

a hack to the mobile web browsers to call native APIs

Workflow
Build your app once with web-standards
Based on HTML5, PhoneGap leverages web technologies developers already know best... HTML and JavaScript. Pick the HTML framework of your choice (jQuery Mobile, Sencha Touch...) and build your application. At the end, your HTML app must look like a native one.

to build hybrid apps


Wrap it with PhoneGap
Using the free open source framework or PhoneGap build you can get access to native APIs: access to the camera, to the accelerometer, to the list of contacts, to the File API... APIs that are not available in the mobile web browser

Deploy to multiple platforms!


PhoneGap uses standards-based web technologies to bridge web applications and mobile devices. You can deploy your application on iOS, Android, Windows Mobile, Bada, BlackBerry, WebOS and Symbian!!!

d n u o laygr

s p p a d i r b y - H p a G e n o h P - Browser

Difficulty
- rookie - intermediate - expert

Todo list
- user XP - Xcode - Xplatform
by Michal Chaize

appliness

WTFJS?!*%

WTFJS!!! false advertising


HEY DUDE

JavaScript is a language we love despite it giving us so much to hate. wtfjs.com by brian leroux is a collection of those very special irregularities, inconsistencies and just plain painfully unintuitive moments for the language of the web.

Answer: do you think this constructor returns for new Dude(Bob)? Doug or Bob? function Dude(name){ this.name = name; return {name: Doug}; } Answer: var bob = new Dude(Bob); // { name: Doug } bob instanceof Dude // false Huh!? So you can just slip in anything? What about arrays? function Dude(name){ this.name = name; return [1, 2, 3]; } new Dude(Bob); // [1, 2, 3] That cant be! What about... function Dude(name){ this.name = name; return 3; } new Dude(Bob); // { name: Bob } Wah? No way! So, if you try to return a primitive type from a constructor(number, string, date), it will ignore the return value and return the originally initialized object, but otherwise, the returned value overrides.

d n u o laygr

t - JavaScrip - Array - Objects

Difficulty
- rookie - intermediate - expert

Todo list
- laugh - have fun - sleep

by Toby Ho

appliness

BLEEDING EDGE

Generating Color Palettes from HTML5 Video


CRAZY RAY WILL SHOW YOU HOW TO USE YOUR WEBCAM and webrtc to define a color scheme. very creative.

One of the more interesting aspects of PhoneGap development is that the features it provides open up interesting possibilities when combined with other products. So for example, you can combine PhoneGaps camera support with existing JavaScript libraries that manipulate images. HTML5 is much the same way. By broadening what the browser can do, all of a sudden you see multiple new opportunities for mashups and unique new creations. Today Im going to demonstrate one simple example of this. I mentioned PhoneGap earlier because these particular demos are based on an earlier application I built that utilized an excellent JavaScript library called Color Thief. Color Thief gives you the ability to examine images and determine either the dominant color or get a palette of prominent colors. For my PhoneGap application, I made use of the Camera API to allow you to take pictures and generate a color palette from the result. I thought it might be interesting to apply similar logic to a desktop application making use of live video streams. In order to test this you will have to use Chrome 19 (still in beta) or higher and you must enabled WebRTC. WebRTC is a project aimed at giving browsers a way to perform real time communication with other clients. It involves quite a bit of moving parts and is very much a work in progress, but you can begin experimenting with it now. Note that before you do so, you must enable the feature. Details on how this is done may be found here: Testing WebRTC on Chrome. The first demo makes use of the web cam and combines it with the ColorThief library to provide a live view of the colors from the camera. You have a screenshot of my demo on the left.

91/95

This code is based on a simple demo by Greg Miernicki. Lets look at the code, and then Ill explain whats happening.
<!DOCTYPE html> <html> <head> <script src=js/jquery-1.6.2.min.js></script> <script src=js/quantize.js></script> <script src=js/color-thief.js></script> <script> $(document).ready(function() { if(!navigator.webkitGetUserMedia) return; navigator.webkitGetUserMedia(video, gotStream, noStream); var video = $(#monitor)[0]; var canvas = $(#tempCanvas)[0]; var img = $(#tempImage); img.load(function() { console.log(load); try { var p = createPalette(img,5); for(var i=0; i<p.length; i++) { $(#p+i).css(background-color,rgb(+p[i][0]+,+p[i][1]+,+p[i] [2]+)); } var dom = getDominantColor(img); $(#domColor).css(background-color,rgb(+dom[0]+,+dom[1]+,+d om[2]+)) } catch(e) {}; setTimeout(doSnapShot,1500); }); function gotStream(stream) { video.src = webkitURL.createObjectURL(stream); setTimeout(doSnapShot, 1500); video.onerror = function () { stream.stop(); streamError(); }; } function noStream() { document.getElementById(errorMessage).textContent = No camera available.; } function streamError() { document.getElementById(errorMessage).textContent = Camera error.; }
more on next page
92/95

function doSnapShot() { canvas.width = video.videoWidth; canvas.height = video.videoHeight; canvas.getContext(2d).drawImage(video, 0, 0); img.attr(src,canvas.toDataURL()); } }) </script> <style> #monitor { width:640px; height:480px; } #tempCanvas, #tempImage { width: 640px; height: 480px; position:absolute; left:-1000px; top:-1000px; } div#domColor { width: 640px; height:50px; } div#palette { width: 640px; } div#palette div { width:20%; height:50px; float:left; } </style> </head> <body> <div id=errorMessage></div> <video id=monitor autoplay></video> <div id=domColor></div> <div id=palette> <div id=p0></div><div id=p1></div><div id=p2></div><div id=p3></div><div id=p4></div> </div> <canvas id=tempCanvas></canvas> <img id=tempImage></img> </body> </html>

93/95

Theres quite a bit here, so lets tackle it in pieces. First - notice our jQuery $(document).ready block checks to see if the feature, webkitGetUserMedia, exists, and if not, immediately leaves. Normally Id present some form of message to the user. Being a proof of concept though we can be mean like that. The magic begins with a request for the web cam. This is as simple as: navigator.webkitGetUserMedia(video, gotStream, noStream); noStream is a simple error handler, so lets focus on gotStream. gotStream handles two distinct things. First, it hands off the video data from the media stream to the actual video tag we have in the DOM. Secondly, it automatically runs a function, doSnapShot. That function then handles getting a still from the video source and drawing it to a canvas. (And again, I want to credit Greg Miernicki. All of this logic comes from his demo.) Heres where things get interesting. Once we have an image, we can use ColorThief on it. But ColorThief only works on fully loaded images. Youll notice we write to an image addressed by the JavaScript variable img. This was set earlier in a jQuery selector. Because Ive got a handle to the image object in the DOM, I can attach an event handler specifically for the load event of the image. Once a load event occurs, I then turn to ColorThief. I mentioned earlier that it supports getting both a dominant color as well as a palette of used colors. I call both of those and draw them out to some divs below the video. Note the use of try/catch. I encountered errors with ColorThief when it first started hitting the video so I simply try/catch to avoid the initial problem. By the way - why the use of setTimeout - and why 1500 milliseconds? Because ColorThief has quite a bit of work to do, I thought it best to go for slightly slower than real time updating. Obviously this could be tweaked a bit. Another issue is the use of the image passed to ColorThief. I use CSS to hide this image offscreen. If you look at the source of ColorThief though you will see it actually creates a canvas out of the image. So Ive actually got a canvas item sourcing an image sourcing a canvas. That could be optimized. So while running this demo and noticing the colors seemed pleasant (entirely due to my snazzy clothing selections), I wondered what could be done with this on a bigger scale. Remember how we hid the image used to source the color operations? What if we hid everything! Why? Imagine a web site that changes its main theme based on what you wore. Thats a bit over the top - but possible. Consider the following simple Bootstrap based site on the next page:

94/95

>
By grabbing the webcam again and selecting the dominant color, you can end up with something like the screenshot on the right. Of course, this assumes a user wearing a bright red shit - I used a handy Imperial Guard action figure I had nearby . The code for this version is much like the previous one - but simply uses jQuery to update Bootstrap CSS: img.load(function() { try { var dom = getDominantColor(img); $(.navbar-inner).css({background-image:none,backgroundcolor:rgb(+dom[0]+,+dom[1]+,+dom[2]+)}); om[2]+)}); $(h1,h2,p).css({color:rgb(+dom[0]+,+dom[1]+,+d

} catch(e) {}; setTimeout(doSnapShot,1500); });

Obviously this is a bit of a contrived example, but the idea is that once you have access to the web cam, theres the possibility of doing much more than chat or taking silly pictures.

ABOUT THIS ARTICLE


Meet Raymond Camden. He is a 38 year old married father of three living in beautiful Lafayette, Louisiana. Ray is a developer evangelist for Adobe where his primary technical focus is ColdFusion, jQuery, Flex, AIR and the mobile space. http://raymondcamden.com/ @cfjedimaster

ONLINE RESOURCES Color Thief http://lokeshdhakar.com/projects/color-thief/ Rays blog http://raymondcamden.com/ WebRTC http://webrtc.org/

appliness

BLEEDING EDGE

Thanks to Molly Holzschlags tweet, I learned there was an Editors Draft of CSS Variables.

CSS VARIABLES DRAFT

Let me first say that I think its awesome that the W3C is taking this on. I think that variables in CSS will ultimately be a good thing. It will make it easy to reuse colors and other CSS properties. It will make large amounts of redundancy go away. It will make CSS files smaller, and therefore give less toehold to bugs. That being said, I have a major complaint with the implementation of--in a word data. See, here is how CSS variables are supposed to work according to the draft. I create a property in the root named data-header-color. :root { data-header-color: #06c; }
This Gist brought to you by Github variableset.css view raw

Then to refer to that color elsewhere, I use a construct that looks like a function named data() to retrieve it as so: h1 { background-color: data(header-color); }
This Gist brought to you by Github variableget.css view raw

96/98

As far as I can tell, the only explanation in the draft for why this is, is that it is trying to match the HTML specification for data: The naming here is loosely based on the form of custom data attributes in HTML5. However, as defined here, the syntax for variable usage is different from the syntax for variable definition (i.e. data-foo for definition, data(foo) for usage). Some have suggested that the syntaxes should should match, using functional syntax in both cases. Others have suggested using a prefixed symbol instead of functional syntax (e.g. $foo) for both the property and usage. Well at least they are aware that some might object to this format. So let me add my voice. I object. Variables are a pretty standard construct, people know how they work. Make them work like variables in other languages. I have a bunch of reasons here: Two different syntaxes for creation and consumption seems confusing. It looks like youre calling a function, but youre not. Youre referring to a variable. Thats confusing. CSS and HTML dont have a lot of overlap in syntax, why is adding some a good thing? My preference here is that I can just use plain old words as a variable, then consume them as plain old words. That being said, I would be okay with a prefixed symbol, like a $ if it comes down to some sort of parsing issue. Thats my major problem with the draft, but I have one other issue with the behavior on invalid variables. Like if you set the margin to #FFFFFF. Basically if you have this code:

p { background-color: red; } p { background-color: Behold I am not a valid color at ALL!!!! }


This Gist brought to you by Github errorwithoutvariables.css view raw

Then the p comes out as red, but if you have this code:

:root { data-not-a-color: Behold I am not a valid color at ALL!!!! } p { background-color: red; } p { background-color: data(not-a-color); }
This Gist brought to you by Github errorwithvariables.css view raw

The p comes out transparent. This sort of change in behavior might be pretty confusing. The explanation makes some sense: The invalid at computed-value time concept exists because variables cant fail early like other syntax errors can, so by the time the user agent realizes a property value is invalid, its already thrown away the other cascaded values. I think attr() needs to rely on it as well, as its behavior is almost identical to variables.

97/98

But I imagine this is something that browser manufacturers can handle as they control the behavior of throw[ing] away the other cascaded values. They could hold on to cascaded values until they are done computing variables. But maybe Im missing something here. But its also worth considering if this will make invalid CSS easier to track down. I doubt it, but until a browser implements these, it will be hard to determine if that is true. Anyway. The good news here is that this is the editors draft, not the recommendation. This means that now is the time to start analyzing this spec and commenting on it. So what do you think?

Aside on W3C Drafts Its important to note that a Working Draft is a pretty early stage of the W3C recommendation process. W3C follows these steps when advancing a technical report to Recommendation. 1. Publication of the First Public Working Draft. 2. Last Call announcement. 3. Call for Implementations. 4. Call for Review of a Proposed Recommendation. 5. Publication as a Recommendation.

I believe we are between steps 1 and 2 at the moment. Also relevant: Purpose: The publication of the First Public Working Draft is a signal to the community to begin reviewing the document. So to be clear, were supposed to be commenting at this stage.

ABOUT THIS ARTICLE


Terrence Ryan is a Worldwide Developer Evangelist for Adobe. His job basically entails traveling the world and talking about the developer tools and technologies that Adobe has to offer or that evangelists support. To find out more, see about his Job. http://www.terrenceryan.com/ @tpryan

ONLINE RESOURCES
Editors Draft of CSS Variables http://dev.w3.org/csswg/css-variables/ HTML Specification for data http://www.whatwg.org/specs/web-apps/... CSS Variables Draft Comments https://gist.github.com/2136922 98/98

appliness

HELTER SKELTER NEWS

Fresh news about HTML and Javascript collected by Brian Rinaldi - remotesynthesis.com
WebStorage: Persistent client side data storage. via John Allsopp Experimenting with CSS Exclusions. via Ryan Stewart How to do content folding for your responsive web design using CSS Regions. via Chris Coyier

What is the meaning of this? via Douglas Crockford Device-agnostic and content-centric approach to responsive web design. via Thierry Koblentz How to create the popular infinite scroll pagination effect using jQuery via Mohd Hadihaizil Din

How to make Dreamweaver add code coloring and hinting with the Sass and Less CSS preprocessors via Greg Rewis

Tutorial on Underscore.js via Siddharth

How to create an Autocomplete in jQuery Mobile by Ray Camden

appliness

HELTER SKELTER NEWS

Toying With the HTML5 File System API via Ivaylo Gerchev Build animated CSS3 content tabs. via Ring Wing Understanding MVVM - A Guide For JavaScript Developers via Addy Osmani

Stop Nesting Functions! (But Not All of Them) via Jeremy McPeak Extending JavaScript The Right Way. via websanova

DIRECTION-AWARE HOVER EFFECT WITH CSS3 AND JQUERY via MARY LOU

JavaScript motion detection via Romuald Quantin

Persisting Backbone Collections via Eric Feminella Object types in JavaScript by Keith Peters

MORE NEWS ON remotesynthesis.com

appliness

THE TEAM
Contribute and join Appliness

Appliness is a free digital magazine edited by passionate web developers. We are looking for contributors. Contact us and join the adventure. Youll find on our website appliness.com a feedback form. You can also follow us on twitter, facebook and Google+.

MICHAEL
Michal Chaize is a Developer Evangelist at Adobe where he focuses on Rich Internet Application and Mobile applications. Based in Paris, he works with large accounts that need to understand the benefits of rich user interfaces, leverage the existing back-ends to add a rich presentation layer and measure the impact on the existing IT teams. He believes that intuitive user experiences in the Enterprise are key to successful developments of effective, efficient, engaging, easy to learn and error free applications. Before joining Adobe, Michael founded a software company and taught RIA languages such as Flex and PHP in IT engineering schools. Hes the editor in chief of Appliness.

CHAIZE

R AY M O N D

Meet Raymond Camden. He is a 38 year old married father of three living in beautiful Lafayette, Louisiana. Ray is a developer evangelist for Adobe where his primary technical focus is ColdFusion, jQuery, Flex, AIR and the mobile space. Hes been invited to speak at many conferences over the years, including CFUNITED and Adobe MAX .

CAMDEN

IAN CHRISTOPHE
Christophe is a Developer Evangelist for Adobe where he focuses on Web Standards, Mobile, and Rich HTML Applications with a special focus on Enterprise Integration. In this role, Christophe has helped some of the largest financial services companies design, architect and implement some of their most mission critical applications. He was one of the initial members of the Flex Product Team in 2003. In his previous role at Macromedia, Christophe worked on JRun, the companys J2EE application server. Before joining Macromedia, Christophe was managing Java and Internet Applications Evangelism at Sybase and Powersoft. Christophe has been a regular speaker at conferences worldwide for the last 15 years.

COENRAETS

Ian Devlin is an Irish web developer, blogger, and author who enjoys coding and writing about emerging web technologies such as HTML5 and CSS3. In addition to front-end development, Ian also builds solutions with back-end technologies such as .NET and PHP. He has recently written a book titled HTML5 Multimedia: Develop and Design.

DEVLIN

Keith has been programming professionally for over a decade and as a hobby for a while longer. He has written or contributed to a dozen books on programming and maintains his personal site at www. bit-101.com.

PETERS

B R I A N
Brian Rinaldi is as a Content and Community Manager for the Adobe Developer Center team, where he helps drive content strategy for HTML5 and JavaScript developer content. Brian blogs regularly at http://remotesynthesis.comand and is a unreformed twitter addict.

RINALDI

He lives near Boston, MA in the USA, and is the Engineering Guru at Infrared5.

T E R R E NC E
Terrence Ryan is a Worldwide Developer Evangelist for Adobe. His job basically entails traveling the world and talking about the developer tools and technologies that Adobe has to offer or that evangelists support.

R Y A N

Ryan Stewart is a Web Developer Evangelist for Adobe Systems. After graduating from the University of Pennsylvania with a degree in Economics he started on the Flash Platform by building eLearning rich Internet applications in Flex 1.5 and ColdFusion 7 for the Wharton School of Business. He is a long time blogger and had a prominent blog on ZDNet where he covered all sides of rich Internet applications. He has spoken at a number of industry conferences including Web 2.0 Expo, Adobe MAX, 360|Flex, SXSW, PHP Tek, and Web Design World. When not working with the latest Adobe technology you can find him in Seattle where he enjoys making beer, mountaineering, and spending as much time as possible in the outdoors.

STEWART

A N D R E W
Andrew Trice is a Technical Evangelist with Adobe Systems. Andrew brings to the table more than a decade of experience designing, implementing, and delivering rich applications for the web, desktop, and mobile devices. He is an experienced architect, team leader, accomplished speaker, and published author, specializing in object oriented principles, mobile development, realtime data systems, GIS, and data visualization.

T R I C E

M A I L E
Maile is the assistant editor for Appliness magazine and has worked with Adobe both as an employee and consultant for 8 years now. Mailestarted with Adobe on the Technical Marketing team as a technical trainer for the Adobe LiveCycle Enterprise Suite (most recently Adobe Digital Enterprise Platform). She then went on to work with the Adobe Enterprise Evangelist team to support great Flex developer resources such as Tour de Flex and Flex.org. Maile is excited to jump into the world of digital publishing and dig deeper into leading edge HTML and related technologies.

VALENTINE

Greg is a Developer Evangelist at Adobe Systems focusing on the use of Adobe technologies in enterprise applications. Technologies include HTML, JavaScript and related technologies, Flex, AIR, data services, digital publishing, and anything mobile, tablet and desktop app development related. Prior to joining Adobe, Greg architected and developed many largescale applications at Verizon, Motorola, NASA/Boeing and others.

W I LS O N

Appliness is a digital magazine written by passionate web developers. You can follow our activity on Facebook, Twitter or Google+.

O W FO LL
o t t n a w ? u e Yo ribut t n co

U S

If you want to contribute writing articles or showcasing your app, feel free to contact us. We are permanently looking for new contributions and content to cover all the aspect of application development with web standards. We are also opened to suggestions. The Give us feedback form on our website is the best way to contact the team.

GIVE US FEEDBACK

CLICK HERE TO CONTACT US

CO

TR I

BU

TE

Вам также может понравиться