Você está na página 1de 136

appliness

#3 - JUNE 2012

Chris H

Exclusi

ve inte rview

eilmann

The digital magazine for web app

DEVELOPERS

TUTORIALS
HTML5, EMBER.JS, jQUERY, PHONEGAP, SVG, REQUIRE.JS...

INNOVATION
BUILD YOUR MOBILE APPS IN THE CLOUD

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 THIRD issue of this magazine.

(
VISUAl and juicy INTERVIEW CHEAT SHEET FEEDBACK SHOWCASE video tutorial BLEEDING EDGE TEAM

TABLE OF CONTENTS

ten features I like about coffeescript


by Karl Seguin

DONt WORRY, BE APPLI

multitouch with hammer.js


by Michal Chaize

flame on! a beginners guide to ember.js


by Andy Matthews

DEPENDENCY MANAGEMENT WITH REQUIREJS


by Aaron Hardy

Getting started with HTML mobile app development using jQmobile, RequireJS and BackboneJS
by Mark Dong

Simple Offline Data Synchronization for Mobile Web and PhoneGap Apps
by Christophe Coenraets

HTML5 Application Cache How To


by Greg Wilson

Working with svg maps


by Antanas Marcelionis

CSS3 animation property


by Francisco Granados

DATA VISUALIZATION WITH WEB STANDARDS


by Andrew Trice

ADOBE SHADOW
by Holly Schinsky

INTERVIEW OF CHRISTIAN HEILMANN


by Michal Chaize

CSS SELECTORS
by Ben Howdle

ROOM 112 - PHONEGAP EXPLORATION


by Jesse Freeman

Three GREAT APPLICATIONS BUILT WITH WEB STANDARDS


by Michal Chaize

phonegap BUILD
by Piotr Walczyszyn

WHICHELEMENT.com

THE ADRESS ELEMENT


by Terry Ryan & Ray Camden

LIBRARY OF THE MONTH

MANAGE YOUR DATA IN THE CLOUD WITH SIGNALBOX


by Michal Chaize

Example of getUserMedia and CSS Filters


by Raymond Camden

Face detection with getUserMedia


by Raymond Camden

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

VISUAL & JUICY

Ten Features I Like About CoffeeScript

CoffeeScript has a number of other nice features, and its always evolving. Its less verbose and improves readability. here are my top 10 features. My name is Karl Seguin, Im a software developer and amateur writer. I contribute to various open source projects, run a few side projects and enjoy learning new technologies.

#1

Its pretty common that youll want to build a string based on one or more variables. With CoffeeScript, variables can cleanly be placed inside of as string:
level greater than #{maxPowerLevel} level greater than + maxPowerLevel +

With well-named variables, string interpolation is easier to read and maintain. Of the three main ways to do this (the third being via some type of formatting function like sprintf), string interpolation is by far, the best, for both simple and complex cases.

d n u o laygr

String interpolation

Difficulty
- rookie - intermediate - expert

- Coffee t p i r c S a v a J - Templates

Todo list

- dring tea

- code faster - readable code

by Karl Seguin

#2

Statement Modifiers

Ill admit that statement modifiers are a pretty minor thing, but as trivial as they are, Ive always found them useful for simple statements:
applyChanges = (elements) -> return if elements.length == 0 ... applyChanges = function(elements) { if (elements.length === 0) { return; } ...

#3

Callback Handling

Whether you are doing client-side development or server-side development, callbacks and JavaScript go hand-in-hand. And, although I dont mind braces, Ive always found JavaScripts syntax to be far too verbose. CoffeeScript helps in two ways. First, optional parenthesis, which I generally dislike, except when dealing with callbacks. Second, blocks via indentation. Compare:
$(#data).on click, tr, (e) -> id = $(this).data(id) ... $(#data).on(click, tr, function(e) { id = $(this).data(id) ... });

I find this particularly useful to help minimize the clutter caused by node.js callback soup. On the downside, it isnt great when you have a parameter after the callback, such as with setInterval or $.get and $.post.

#4

Comprehensions

Looping over arrays and hashes is pretty fundamental, and the more we can enhance the experience, the better. Even if you dont leverage comprehensions as-is, simply having a for loop that exposes the value+index of an array, or the key+value of a hash, is a nice addition.
books = [ {name: Dune, rating: 5} {name: Old Mans War, rating: 4} {name: Foundation, rating: 3} ] good = (b.name for b in books when b.rating > 3) books = [ {name: Dune, rating: 5}, {name: Old Mans War, rating: 4}, {name: Foundation, rating: 3} ]; good = []; for(var i = 0; i < books.length; ++i) { if (books[i].rating > 3) { good.push(books[i].name); } }
4/7

#5

The Fat Arrow

In JavaScript, the meaning of this isnt always intuitive. Consider this CoffeeScript code:
class DataTable constructor: (element) -> this.element = $(element).on click, tr, this.clicked clicked: (e) -> this.highlight() highlight: -> ....

One might expect that this in the clicked method to be our DataTable instance, but instead, itll be the row which is clicked. This means that the call to highlight will fail, since the html row element doesnt have a highlight method. That clicked exists as a method of DataTable doesnt mean much.

To solve this, CoffeeScript lets you define a method with a fat arrow =>. Using => binds the function to the expected scope:
class DataTable constructor: (element) -> this.element = $(element).on click, tr, this.clicked clicked: (e) => this.highlight() highlight: => .... __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; function DataTable(element) { this.highlight = __bind(this.highlight, this); this.clicked = __bind(this.clicked, this); this.element = $(element).click(this. clicked); } DataTable.prototype.clicked = function(e) { this.highlight(); ... }; DataTable.prototype.highlight = function() { ... };

Sometimes youll want the normal JavaScript behavior (via a slim arrow), and sometimes youll want to fat arrow behavior. In general, I find myself using slim arrows more often in client-side code, and fat arrows more often on server-side code.

#6

@ Alias

Speaking of this, CoffeeScript has a shortcut for it, the @ symbol. Its easy to write this off as meaningless syntactical sugar, but it is useful. First, constructor parameters prefixed with @ are converted into properties:
5/7

class User constructor: (@id) ->

function User(id) { this.id = id; }

Beyond this though, its a nice way to define class method:


class User constructor: (@id) -> @findById: (id) => ... function User(id) { this.id = id; } User.findById = function() {};

Neither @ nor the fat arrow mean that you dont have to worry about the current meaning of this (or its alias @). They arent silver bullets, which isnt to say that they dont add value.

#7 #8 #9

SCOPING

CoffeeScript takes care of properly scoping your variables. This means that you dont use the var keyword and dont have to worry about having an inner variable shadow an outer one. One top of that, all CoffeeScript output is wrapped inside an anonymous functions, which means you wont leak any global objects. If you do want to expose something globally, say like our User class above, you need to attach it to a global object, like window. Of course, on the node.js side, you can simply export it.

CLEAN JAVASCRIPT OUTPUT

One of the nicest things about CoffeeScript is that it generates clean and readable JavaScript. This makes it both easy to learn and debug. In fact, one of the best ways to learn CoffeeScript is to go to the official website, click the Try CoffeeScript button at the top, and type away. Seeing the instant translation to JavaScript is pretty useful.

CLASSES

Weve seen examples of it as a side effect of other features, but CoffeeScript classes are cleaner and more intuitive than their JavaScript counterparts. And the only reason Im not showing how to inherit via extend is because I dont want to include all the necessary JavaScript...

6/7

class User constructor: (@id) -> @findById: (id) -> @findByEmail: (email) -> save: =>

function User(id) { this.id = id; this.save = __bind(this.save, this); } User.findById = function(id) {}; User.findByEmail = function(email) {}; User.prototype.save = function() {};

#10

OPERATORS

In CoffeeScript, == and != translate to === and !==, which you probably always want to be using. This alone removes a common pain point. In addition to that, theres the existential operator. In its simplest form, it checks for undefined and null:
if (typeof name === undefined || name === null) { return null; }

return null unless name?

But it can also be used in chains:


class Unicorn is_rookie: () -> vampire?.kills > 0 Unicorn.prototype.is_rookie = function() { return (typeof vampire !== undefined && vampire !== null ? vampire.kills : void 0) > 0;

CoffeeScript has a number of other nice features, and its always evolving. I understand that some people simply dont like it, which is fine, since a lot of what it offers is subjective. However, Im baffled that people dismiss as being nothing but syntactical sugar. Almost anything in the programming world can be described as syntactical sugar which sits on top of a more fundamental concept. Its less verbose and improves readability. Thats a win in my books. Of course, as someone who believes that knowing C is critical, I agree that new developers should first learn JavaScript and then spend a day learning CoffeeScript. But thats pretty much as much of a debate as I plan on having about it.

ABOUT THIS ARTICLE


My name is Karl Seguin, Im a software developer and amateur writer. I contribute to various open source projects, run a few side projects and enjoy learning new technologies. http://openmymind.net/ @karlseguin

ONLINE RESOURCES Understanding CoffeeScript Comprehensions http://openmymind.net/2012/1/15/Understanding-CoffeeScriptComprehensions/ CoffeeScript http://coffeescript.org/ Karls blog http://openmymind.net/

appliness

DONT WORRY, BE APPLI

Multitouch with hammer.js

hammer.js is a very simple but very powerful library to enable multitouch experiences on touch devices.

why using multitouch?


As a mobile application developer, Im always dealing with the frontier between native apps and web apps. Tablet and mobile users are used to multitouch gestures: pinch to zoom-in, rotation, natural drag and drop... Now, these gestures are not reserved to native apps. Thanks to Hammer.js, you can easily implement touch events in your web apps: tap, double tap, hold, drag and transform gestures. It became natural reflexes. Display a picture on a tablet and notice that the first thing that will do the users is to zoom-in. To introduce this library, Ive extended some Hammer samples found on GitHub. Ive built a classic polaroid manipulation app. Ill share with you some tips Ive used, but of course youre invited to download the full code of this sample and start playing with Hammer.js. In my sample Im using the Drag gesture, pinch to rescale the pictures and the rotation gesture using two fingers. By the way, do you know why the library is called Hammer.js? Its a tribute to MC Hammer, the singer of U Cant Touch This. Well guess what, now we CAN. Let me add a YO! here. Cool, now I think its time to start a little gangsta.

d n u o laygr

Difficulty
- rookie - intermediate - expert

- jQuery - Hammer - CSS

Todo list
- pinch - rotate - wash fingers
by Michal Chaize

My sample application
Im just playing with three pictures. You can drag, rescale and rotate them. The Polaroid look and feel is produced by a CSS. This is pure HTML and JavaScript powered by Hammer.js:

Getting started
Ok it looks cool and its pretty responsive. Now lets see how to play with Hammer. First, you need to download the library from GitHub: https://github.com/eightmedia/hammer.js If you plan to use jQuery in your project (yes, in some cases, there is a JavaScript life without jQuery), then dont forget to download and import the dedicated jquery.hammer.js also available in the GitHub repository. In my sample, Im using jQuery, Ive put the JavaScript logic in a separate file and Ive created a CSS. My imports look like this: <head> <meta name=viewport content=width=device-width, initial-scale=1.0, user-scalable=no> <script src=jquery-1.7.2.min.js></script> <script src=hammer.js></script> <script src=jquery.hammer.js></script> <script src=myLogic.js></script> <link href=http://fonts.googleapis.com/css?family=Bree+Serif rel=stylesheet type=text/css> <link href=style.css rel=stylesheet type=text/css> </head>

9/13

Then Ive declared three DIV to display the pictures. The pictures are contained in a zoomwrapper DIV element. <body> <div class=welcome> <p>This sample is using Hammer.js.<br/> Drag and drop the pictures, zoom with pinch and rotate them.</p> </div> <div id=zoomwrapper> <div id=zoom class=zoomProps > <div class=polaroid> <img src=pic1.jpg alt= width=200 height=200 /> <span>Coco</span> </div> </div> <div id=zoom2class=zoomProps > <div class=polaroid> <img src=pic2.jpg alt= width=200 height=200 /> <span>Axo</span> </div> </div> <div id=zoom3 class=zoomProps> <div class=polaroid> <img src=pic3.jpg alt= width=200 height=200 /> <span>Gwo</span> </div> </div> </div> </body> There is nothing particular to notice in the CSS. The zoomwrapper DIV has an overflow property set to hidden. And here is the code to imitate the Polaroid effect: #zoomwrapper { height: 377px; width: 600px; overflow: hidden; } .polaroid{ text-align: center; padding: 10px 10px 25px 10px; background: #eee; border: 1px solid #fff; -moz-box-shadow: 0px 2px 15px #333; -webkit-box-shadow: 0px 2px 15px #333; border: 1px solid #dfdfdf; border: 1px solid rgba(96,96,96,0.2); font-family:Imitation; font-size:24px; color:#000; padding-bottom:10px; text-shadow:#333; }
10/13

drag pictures
The DragView function contains the logic to handle drag events. For each picture, you must associate a DragView call and bind the drag events: var dragview = new DragView($(container)); container.bind(dragstart, $.proxy(dragview.OnDragStart, dragview)); container.bind(drag, $.proxy(dragview.OnDrag, dragview)); container.bind(dragend, $.proxy(dragview.OnDragEnd, dragview)); setInterval($.proxy(dragview.WatchDrag, dragview), 10); Lets look at the OnDragStart method declared in DragView. this.OnDragStart = function(event) { var touches = event.originalEvent.touches || [event.originalEvent]; for(var t=0; t<touches.length; t++) { var el = touches[t].target.parentNode; if(el.className.search(polaroid) > -1){ el = touches[t].target.parentNode.parentNode; } el.style.zIndex = zIndexBackup + 1; zIndexBackup = zIndexBackup +1; if(el && el == this.target) { $(el).children().toggleClass(upSky); this.lastDrag = { el: el, pos: event.touches[t] }; return; } } } It stores the touch events in an array and make sure that were dealing with the DIV element with a polaroid class attached. If not, then we need to play with its parent node. Its due to the structure of my HTML elements. If you tap the title of the picture, then you also want the picture to move. Im also playing with the zIndex property to put the picture at the top when you drag it. Then, thanks to the toggleClass method (jQuery), I assign the upSky class to the element: its just setting an intense white background.

zoom-in and zoom-out


To initialize the pinch gesture, Im calling the ZoomView method on each picture. Then you can listen to transformstart, transform and transformend events on your elements. The transformstart event lets you define what is the cssorigin point of transformation. container.bind(transformstart, function(event){ //We save the initial midpoint of the first two touches e = event
11/13

tch1 = [e.touches[0].x, e.touches[0].y], tch2 = [e.touches[1].x, e.touches[1].y] tcX = (tch1[0]+tch2[0])/2, tcY = (tch1[1]+tch2[1])/2 toX = tcX toY = tcY var left = $(element).offset().left; var top = $(element).offset().top; cssOrigin = (-(left) + toX)/scaleFactor +px + (-(top) + toY)/ scaleFactor +px; }) The transform state fires the transform method, passing the transform event and setting the scaleFactor. You can specify the minimum and maximum zoom thanks to the MIN_ZOOM and MAX_ZOOM constants. container.bind(transform, function(event) { scaleFactor = previousScaleFactor * event.scale; scaleFactor = Math.max(MIN_ZOOM, Math.min(scaleFactor, MAX_ZOOM)); transform(event); }); The transform() method uses simple CSS transformations that are hardware accelerated on mobile devices to get the best performance on touch devices. As the transform event powered by Hammer also contains information about the angle of rotation of your element, you can use the rotateZ property to enable rotation. function transform(e) { //Were going to scale the X and Y coordinates by the same amount var cssScale = scaleX(+ scaleFactor +) scaleY(+ scaleFactor +) rotateZ(+ e.rotation +deg); element.css({ webkitTransform: cssScale, webkitTransformOrigin: cssOrigin, transform: cssScale, transformOrigin: cssOrigin,

}); }

Thats very efficient and easy to implement. Now go to the next page to discover the full code of this sample.

12/13

source code: HTML & JAVASCRIPT

<<< YOU CAN SCROLL DOWN THE CONTENT OF THIS FRAME >>> <<< YOU CAN SCROLL DOWN THE CONTENT OF THIS FRAME >>>

appliness

DONT WORRY, BE APPLI

flame on! a beginners guide to ember.js

In this tutorial youll become more familiar with the basics of Ember.js as you build a working Twitter timeline viewer.

background of mvc frameworks


Sophisticated JavaScript applications can be found all over the place these days. As these applications become more and more complex, its no longer acceptable to have a long chain of jQuery callback statements, or even distinct functions called at various points through your application. This has led to JavaScript developers learning what traditional software programmers have known for decades: organization and efficiency are important and can make the difference between an application that performs great and one that doesnt. One of the most commonly used architecture patterns to achieve this organization and efficiency is known as Model View Controller (or MVC). This pattern encourages developers to separate distinct parts of their application into pieces that are more manageable. Rather than having a function that makes a call directly to the database, you create a Model to manage that for you. Instead of having an HTML file sprinkled with output and logic statements, a simple template, or View, allows you to streamline your display code. Finally a Controller manages the flow of your application, helping the various bits and pieces talk to each other more efficiently. Using this pattern in your application makes it easier to add new functionality. As part of the recent explosion of Internet-based software development, a dizzying array of MVC frameworks with names like Ember.js, Backbone.js,

d n u o laygr
- MVC - Ember.js t p i r c S a v a - J

Difficulty
- rookie - intermediate - expert

Todo list

- modules - components - maintain

by Andy Matthews

Knockout.js, Spine.js, Batman.js, and Angular.js have emerged. Written in JavaScript and designed for JavaScript development, these libraries have filled the void between beginner and intermediate developers on one side, and hardcore programmers on the other. They offer various features and functionality that will suit different developers of varying skill levels based on their needs.

introducting ember.js
Ember.js (under that name) is one of the newest members of the JavaScript framework pack. It evolved out of a project called SproutCore, created originally in 2007 and used heavily by Apple for various web applications including MobileMe. At emberjs.com, Ember is described as a JavaScript framework for creating ambitious web applications that eliminates boilerplate and provide a standard application architecture. It comes tightly integrated with a templating engine known as Handlebars, which gives Ember one of its most powerful features: two-way data-binding. Ember also offers other features such as state management (is a user logged out or logged in), auto-updating templates (when the underlying data changes so does your UI), and computed properties (firstName + lastName = fullName). Ember is already a powerful player after a solid years worth of development. Ember has only one dependencyjQuery. The boilerplate HTML setup for an Ember application should look something like the code below. Note that both jQuery and Ember are being pulled from a CDN (content delivery network). This speeds up your users page load if they have already downloaded these files as a result of earlier visits to other websites that require them. <html> <head> <script src=http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery. min.js></script> <script src=http://cloud.github.com/downloads/emberjs/ember.js/ember0.9.6.min.js></script> <script src=js/app.js></script> </head> <body> </body> </html>

Defining mvc
Before you proceed with this tutorial it would probably be a good idea to more clearly define MVC. The concept has been around since 1979 and since that time a number of different variations on the pattern have emerged. The most common flow usually goes something like this: 1. A user performs an action such as typing on the keyboard or clicking a mouse button. 2. The Controller receives that input and fires off a message to the Model. 3. The Model changes its content based on the message (deletes a row or updates shopping cart quantities). 4. The View watches for a change in the Model and updates the user interface accordingly. Understanding how the MVC pattern works can make your application flow more easily. And, because code is split into distinct pieces, its easier for teams of developers to work together without interfering with each other.
15/25

how ember does mvc


JavaScript is a flexible and powerful language but it also has its shortcomings. Out of the box it doesnt offer the sort of functionality that lends itself to MVC style development. So Ember has extended the base language with a slew of extras. When building your Ember application there are four main pieces that youll be working with: Application, Model, View, and Controller. The following sections review each of these pieces. Application Every Ember application requires an instance of Ember.Application. Its the basis for the entire rest of your code, and provides useful functionality as well as a namespace (a way of grouping the rest of the pieces of your app). Defining an Ember application is simple: Songs = Ember.Application.create({ mixmaster: Andy }); This code defines an application named Songs with a property named mixmaster set to Andy. You can call your application whatever you like, but Ember requires the variable name to begin with a capital letter so that the binding system can find it. There are additional built-in options that can be added when creating your application, and you can add any arbitrary property or method as well, but the main one beginning users might care about is the ready() method. This works exactly like jQuerys document. ready() block and can be implemented in the following manner: Songs = Ember.Application.create({ mixmaster: Andy, totalReviews: 0, ready: function(){ alert(Ember sings helloooooooooo!); } }); Models An application is nothing without data. Ember helps developers manage this data in a structured way using Models. In addition to holding data, Ember Models also model the data within them. In other words, if you wanted to store information about your MP3 collection, your Model might contain a title property, an artist property, a genre property, and so on. That Model might look something like this: Songs.Song = Ember.Object.extend({ title: null, artist: null, genre: null, listens: 0 }); Theres a few things to note about these few lines. Right away you can see your applications namespace in use. Songs is the name of the application, while Song is the name of the Model. When extending an object youre creating a blueprint for future instances of this Model. Because this is the master object all songs will be based on, it uses a capital letter. These naming conventions will make it easier down the road to tell what sort of object youre working with.
16/25

When creating your Model you can provide default values for each property. The title , artist , and genre properties will obviously be filled in later, and so are marked null (or nothing). The listens property defaults to 0 and its value will increase as you listen to your music collection. Now that the Song model is in place, you can add your first song. You used extend to initialize the Song model, but youll use create to add an instance of it. Heres what that looks like: mySong = Song.create({ title: Son of the Morning, artist: Oh, Sleeper, genre: Screamo }); Notice that the variable doesnt begin with an upper case letter, thats because its an instance of the Song model. The new song also isnt within the Songs namespace. Youll almost never create an instance of a Model within your application. Youre certainly welcome to do so, but generally youd place each instance of a Model within a larger collection of similar objects such as an ArrayController (more on that later). Views In an Ember application or any MVC style application a View is something the user can see and interact with. You define an inline template by adding raw HTML directly to the page. This template will be contained within script tags. You add it to the page wherever you want your content to appear. <script type=text/x-handlebars> Hello <b>{{Songs.mixmaster}}</b> </script> Notice that the script tag has a type of text/x-handlebars. This gives Ember something to grab on to when it loads up the page. Any HTML contained within this script tag is automatically prepared by Ember for use in your application. Placing these lines of code within your application will display the following text: Hello <b>Andy</b> Before moving on, take a peek under the hood. In your browser, right-click the bold text and inspect it using the browsers dev tools. You might notice some extra elements. In order to know which part of your HTML to update when an underlying property changes, Handlebars will insert marker elements with a unique ID; for example: <b> <script id=metamorph-0-start type=text/x-placeholder></script> Andy <script id=metamorph-0-end type=text/x-placeholder></script>

</b>

You can also define a View directly in JavaScript, and then display it to the page by using a view helper. Ember has generic views that create simple div tags in your application, but it also comes prepackaged with a set of views for building basic controls such as text inputs, check boxes, and select lists. You start by defining a simple TextArea View within your JavaScript file. Songs.ReviewTextArea = Ember.TextArea.extend({ placeholder: Enter your review });
17/25

Then display it to the page by referencing the path to the variable containing the view, prefaced by the word view . Running the following code in your browser displays a TextArea field with placeholder text of Enter your review. You can also specify rows and cols as additional properties in your definition. <script type=text/x-handlebars> {{view Songs.ReviewTextArea}} </script> Handlebars By now youre probably wondering what the {{ and }} in the code stand for, so this is a perfect time to talk about Handlebars, also known as mustaches. Turn your head sideways and youll see why theyre called Handlebars pardner. Handlebars is a templating engine that lets developers mix vanilla HTML and Handlebars expressions resulting in rendered HTML. An expression begins with {{ and ends with }}. As discussed previously, all templates must be placed within script tags with a type of text/x-handlebars. By default, any value contained within handlebars is said to be bound to its value. That means that if the value changes because of some other action within the application, the value displayed to the user will update as well. Consider the following code: <script type=text/x-handlebars> My songs have {{Songs.totalReviews}} reviews. </script> When your application first initializes the user would see the following text. My songs have 0 reviews. But through the magic of data bindings, that value would change in real time as additional reviews were added by updating Songs.totalReviews. Handlebars also supports flow control through the use of {{#if}} and {{else}}. These elements let you conditionalize your templates based on values in your application. You could change the previous example to display an alternate message to the user when there are no reviews: <script type=text/x-handlebars> {{#if Songs.totalReviews}} Read all my reviews! {{else}} There are no reviews right now. {{/if}} </script> If at any point in the life of the application, the Songs.totalReviews value changes, the view will update and display the other part of the message. Its also worth noting that the # and / symbols are merely there to tell Handlebars that this particular view helper has a closing part. Controllers Earlier, the Model was defined as a way to enable developers to manage data. Thats true, but only in a very narrow way. A Model only contains data about a single thing; for example, a song (but not songs) or a person (but not people). When you want to manage multiple pieces of the same type of data you need a Controller. With Ember you can use an ArrayController to manage sets of songs, people, widgets, or whatever. Each ArrayController has a built-in content property that is used to store data. This data can be simple strings or complex values such as arrays or objects. Additionally, ArrayControllers can contain functions that are used to interact with the data contained within them. What might an ArrayController for your Song collection might look like?

18/25

Songs.songsController = Ember.ArrayController.create({ content: [], init: function(){ // create an instance of the Song model var song = Songs.Song.create({ title: Son of the Morning, artist: Oh, Sleeper, genre: Screamo }); this.pushObject(song); } }); The init function isnt required, but comes in handy as it will be triggered as soon as songsController is ready. It could be used to populate the controller with existing data, and in this case youll use it to add a single song to the Controller to illustrate Embers data-binding. Add the previous ArrayController definition and the following inline template and run the code in your browser: <script type=text/x-handlebars> {{#each Songs.songsController}} <h3>{{title}}</h3> <p>{{artist}} - {{genre}}</p> {{/each}} </script> The Handlebars each helper receives a path to a set of data, and then loops over it. Everything inside the matching each blocks will be displayed on the page for every item in the controller. Notice that youre not providing a path directly to the content array, because as far as Ember is concerned the controller is the array. The resulting HTML output looks like this: <h3>Son of the Morning</h3> <p>Oh, Sleeper - Screamo</p>

Putting it all together: EmberTweets


At this point, you should have a good understanding of what Ember is and what it can do. You should also understand each of the pieces that enable Ember to work its magic: Application, Model, View, and Controller. Its time to put that knowledge to use in writing a real, working application. Youre going to skip the industry standard todo app and move on to something near and dear to many: Twitter. In the rest of this tutorial you will be building a Twitter timeline viewer. Before writing any code, it might be useful to see the final result. Creating your boilerplate files Using the boilerplate HTML page from the beginning of the article youll first build out the base HTML. Copy and paste the following code into a new HTML file named index.html. Youll need to reference the CSS file found in the sample files for this article. The sample files also contain a starting point for this project so feel free to use that as well.<!doctype html> <html> <head> <title>Tweets</title> <meta name=viewport content=width=device-width, initial-scale=1.0>

19/25

<link rel=stylesheet href=styles.css> <script src=http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery. min.js></script> <script src=http://cloud.github.com/downloads/emberjs/ember.js/ember0.9.6.min.js></script> <script src=app.js></script> </head> <body> <script type=text/x-handlebars> <div id=frm> <b>Load Tweets for: </b> </div> <div id=content> <div id=recent> <h3>Recent Users</h3> </div> <div id=tweets> <h3>Tweets</h3> </div> </div> </script> </body> </html> You can see there are three parts to this application: an input field, which allows users to input a Twitter username, the timeline viewer, which displays the selected Twitter users tweets, and a recent users list, which will store previous searches. The search box will appear at the top of the page, the recent users in a column to the left, and the tweets themselves will have the majority of the page on the right side. Next, create another file named app.js and add the following content. These comments helps you keep your code organized. Load this page up in your browser and make sure there are no errors. /************************** * Application **************************/ /************************** * Models **************************/ /************************** * Views **************************/ /************************** * Controllers **************************/ Application initialization The first thing youll need to do is to initialize your application. Directly under the comment block labeled Application, place the following code: App = Em.Application.create(); Notice that instead of saying Ember.Application, this line says Em.Application. The Ember team added this handy shortcut to reduce typing by allowing you to use Em in any place where you might use Em-

20/25

ber. Next youll add the TextInput view and the submit button. Directly under the comment block labeled Views add the following code: App.SearchTextField = Em.TextField.extend({ insertNewline: function(){ App.tweetsController.loadTweets(); } }); This block starts by using the App namespace, then extends one of Embers prepackaged Views, the TextField. In addition to allowing arbitrary properties and functions within Views, Ember also has built-in helper functions available for use. Thats what the insertNewLine() function is; it executes whenever the user presses the Enter/Return key on their keyboard while the cursor is within the input box. Creating template blocks Now that the TextField View is defined, youll add the corresponding view helper code to the HTML file. Switch to index.html and add the following code directly after the line that reads Load Tweets for. Remember that anything within {{ and }} is a template and will be used by Ember to output data. Additionally any template beginning with the word view refers to a View that has been defined within your JavaScript code. {{view App.SearchTextField placeholder=Twitter username valueBinding=App.tweetsController.username}} <button {{action loadTweets target=App.tweetsController}}>Go!</button> This portion of the template contains a view helper, and a button tag with an {{action}} helper. The TextField View, SearchTextField, begins with an attribute that is built into HTML5 text input fields, placeholder text. If the field is empty, the text within the placeholder attribute will be placed into the input field. When someone begins typing, the value goes away. Ember enables developers to use any HTML 5 standard attributes within its built-in views. The second attribute highlights the magic of Embers data-bindings. Ember uses a set of conventions to help it determine what youre trying to accomplish. Any attribute in a view (either within a template, or in a JavaScript file) that ends with the word Binding (note the capital letter) automatically sets up a binding for the attribute that precedes it. In this case Ember is binding the value of App.tweetsController.username to the input fields value attribute. Anytime the contents of the variable changes, the value contained within the input field will update automatically, and vice versa. The {{action}} makes it easier to add functionality to input driven elements. It has two options: the action name and the target. Taken together they form a path to a function contained within an Ember object. In the case of the above button the path would be App.tweetsController.loadTweets(), the same function called when a user presses the Enter key within the text field. Load index.html in your browser and click the submit button, or press the Enter key within the input field. If youre viewing the browser console youll see an error. This is because App.tweetsController is not yet defined. Preparing the Tweet storage object Now would be a good time to define App.tweetsController. Add the following code after the Controllers comment block in app.js. The code below should be familiar to you. Namespace, ArrayController, content arrayits all there. This time though youll be adding an arbitrary property (username), and a function ( loadTweets ). After adding the ArrayController, reload your browser. Type a word in the input box and then click the button. Youll get an alert box that echoes the word you typed. Feel free to remove the alert line at any time. Youll also see an error indicating that the addUser method is not defined.
21/25

App.tweetsController = Em.ArrayController.create({ content: [], username: , loadTweets: function() { var me = this; var username = me.get(username); alert(username); if ( username ) { var url = http://api.twitter.com/1/statuses/user_timeline.json url += ?screen_name=%@&callback=?.fmt(me.get(username)); // push username to recent user array App.recentUsersController.addUser(username); } } }); Take a closer look at the loadTweets function definition; it has some unfamiliar bits. The first line sets a scope for the rest of the function. By definition, the scope or this for all Ember objects is the current function, in this case App.tweetsController. However, youll be adding more functionality to the loadTweets function later in this tutorial. Setting the current scope now helps Ember understand the context youre using. As I noted previously, Ember offers a number of helper functions to make writing applications easier, and these include get() and set(). These two functions are built into every Ember object and provide quick access to any property or function. The next line uses the scope of the current object, App.tweetsController, and then calls the get() function, passing in the name of the property that you wish to get a value for. You might be curious about where the value of username is coming from to begin with. Remember that Embers data bindings are bidirectional. This means that as soon as you type a value into the input field the valueBinding attribute of the input field view updates the App.tweetsController object with a value. After the username has been retrieved, a test is run to make sure its not empty. At the moment there are only two statements within the if block, but that will change later. The first statement sets the URL to Twitters JSON file for a user. You might not immediately notice anything special about this until you look closer and see %@, and the .fmt() at the end. The .fmt() function performs a handy string replacement with the %@ as the marker. Since the design of the application calls for storing a running list of searches, youll have to somehow store your search term. The final line performs that function, pushing the username value into the App.recentUsersController ArrayController. Since this object doesnt exist yet, running the code will result in an error. Storing previous searches In this next section youll create the object used to store recent searches. Take the following code and add it after the App.tweetsController object. App.recentUsersController = Em.ArrayController.create({ content: [], addUser: function(name) { if ( this.contains(name) ) this.removeObject(name); this.pushObject(name); }, removeUser: function(view){ this.removeObject(view.context); }, searchAgain: function(view){ App.tweetsController.set(username, view.context); App.tweetsController.loadTweets();

22/25

});

}, reverse: function(){ return this.toArray().reverse(); }.property(@each)

Youre already familiar with creating an ArrayController and adding an empty content array, but this object has a few new elements starting with the addUser function. This will check the existing array ( this ) using a built-in Ember function named contains(). If it finds a result it removes it by using the ArrayControllers function removeObject(). This function has an opposite named pushObject(), which is used to add individual objects to the content array. Both functions also have pluralized versions that handle multiple objects: pushObjects() and removeObjects(). This code first removes an existing term before adding it so that the same search term isnt displayed more than once. Since you already know how to remove an object from the content array, the only new element in the removeUser() function is the argument. When a function is called using the {{action}} helper, Ember implicitly passes in a reference to the current view. In the case of App.tweetsController, the view has a context that is essentially the item that is currently being iterated over. This context is used to remove the selected item from the array. The searchAgain() function also receives the current view as an argument. When a user clicks a previously searched term, this function populates App.tweetsController.username with the selected username, then triggers the loadTweets() function, offering a single-click view for previous searches. By default, Ember displays contents to the page in ascending order. Array index 1 is first, array index 2 is second, and so on. The design of this application calls for displaying recent searches in descending order. This means that the array must be reversed. While this isnt built-in functionality you can see how easy it is to add. Reverse() first converts the Ember content array into a plain vanilla array using the Ember toArray() function, reverses it, and then returns it. What makes it possible to use this function as a data source is the property() function tacked on at the end. The property() function takes a comma-delimited list of properties required by the specified function. In this case the property() function is implicitly using the content array itself, addressing each element within that array using the @each dependant key. Youll see how to implement the reverse() function in the next section. Displaying previous searches Now that youre storing your previous searches, its time to display them on the page. Copy the following template and add it after the h3 tag labeled Recent Users. {{#each App.recentUsersController.reverse}} <li> <a href=# title=view again {{action searchAgain target=App.recentUsersController}}>{{this}}</a> <a href=# title=remove {{action removeUser target=App.recentUsersController}}>X</a> </li> {{/each}} </ol> You should be familiar with all of this code at this point. The each block points at the content array and the HTML contained within it will be applied for every item within the App.recentUsersController variable. Its not necessary to explicitly point to the content array, but in this case this code points to the reverse function, which provides the data in reverse order. The {{action}} helper lets users click on each anchor tag and trigger the indicated function. The only element that might not be familiar is {{this}}. When iterating over a content array, Ember keeps a reference to the current index in the {{this}} variable. Because the value of each item is only a string, you can directly output the value of the current item using {{this}}. Clicking on a Twitter username will load that users tweets again, while clicking on their name will remove them from the recentUsersController. <ol>

23/25

Loading tweets Saving search terms is good, but how about actually performing the search? Next youll be adding the pieces that will retrieve the JSON packet from Twitter and display it to the page. Take the following Ember Model and add it directly after the comment block labeled Model. Remember that Ember Models are a blueprint for the data they will contain. App.Tweet = Em.Object.extend({ avatar: null, screen_name: null, text: null, date: null }); In app.js locate the line that reads App.recentUsersController.addUser(username); and add the following code directly after it: $.getJSON(url,function(data){ me.set(content, []); $(data).each(function(index,value){ var t = App.Tweet.create({ avatar: value.user.profile_image_url, screen_name: value.user.screen_name, text: value.text, date: value.created_at }); me.pushObject(t); }) }); If youve used jQuery before you might have used the .get() function to retrieve data. The .getJSON() function does the same thing except it expects a JSON packet as a result. In addition it takes the returned JSON string and converts it into executable JavaScript code for you. Once the data has been retrieved, the content array is emptied removing all existing tweets. The next line takes the packet of data and wraps it in a jQuery object so that the .each() method can loop over the resulting Tweets. Within the each block a copy of the Tweet Model is populated with data, and then pushed into the ArrayController. Finally, youll need to add the following display code to index.html. Copy and paste it directly after the h3 tag labeled Tweets. <ul> {{#each App.tweetsController}} <li> <img {{bindAttr src=avatar}} /> <span>{{date}}</span> <h3>{{screen_name}}</h3> <p>{{text}}</p> </li> {{/each}} </ul>

24/25

Ember makes it easy to output data to the page using plain {{Handlebars}} but theres a catch. Remember how Ember wraps outputted values in script tags? Thats not an option when youre working with HTML attributes. So Ember provides the {{bindAttr}} helper. Any attribute placed within this helper will output as normal, but still retain bindings. Go ahead and run your application now. Input a username

and watch the Tweets fly in.

Where to go from here


In this article you learned the basics of Ember.js functionality. You learned how Ember implements MVC using its Models, Views, Controllers, and of course the Application object. You created templates with view helpers and action helpers using Handlebars. You learned how to create blueprints for your data using Models, store that data in collection sets with Controllers, and display the data to the page using Views. Finally, you used Ember to build an entire application with data bindings, computed properties, and auto-updating templates. Your mother would be so proud of you! For further reading on Ember, check out a few of the following links: Ember.js Ember.js documentation The Emberist Tom Dale at the Ember.js Meetup Andy Matthews blog Cerebris blog code 418 holy moly blog

MORE INFORMATION

>

ABOUT THIS ARTICLE


Andy is currently a Senior Web Developer for Dealerskins, Inc. and runs commadelimited. com. Hes the author of open source ColdFusion libraries: PicasaCFC, & ShrinkURL. Hes written an HTML/JS Adobe AIR Application called Shrinkadoo (in AIR Marketplace), & speaks at RIA User Groups or conferences. http://andymatthews.net/
@commadelimited

ONLINE RESOURCES Ember.js official website http://emberjs.com/ Ember.js Documentation http://docs.emberjs.com/ Emberist http://www.emberist.com/

>

appliness

DONT WORRY, BE APPLI

Dependency management with RequireJS

This article provides an introduction to RequireJS and how you can use it to help manage JavaScript projects.

introduction
In most software development languages, applications are built using dozens, hundreds, or even thousands of files. In JavaScript, however, developing inside only a small handful of fileseach containing hundreds or thousands of lines of codehas traditionally been more commonplace. Expert or beginner, comprehending the scope and intricacies of such files can be a daunting task. Making sure your code stays clean and modular is an even taller order. Then why are large, complex JavaScript files so common? The most commonly cited reasons are:

Thats the way JavaScript development has been done in the past. Loading many JavaScript files requires many HTTP requests resulting in longer load times. Dependency management is hard in JavaScript. While the first excuse is true, relying solely on whats been done in the past is the death of progression. The second point is a legitimate concern, and the third point used to be much more of a problem than it is today. Fortu-

d n u o laygr

Difficulty
- rookie - intermediate - expert

- Require S J n o m m o C - AMD

Todo list

- maintain

- call modules - organize

by Aaron Hardy

nately, there are fantastic libraries and standards that can help developers overcome both these problems. In fact, overcoming them is imperative. The scalability of JavaScript applications and the sanity of the engineers who develop them depend on it. This article provides an introduction to RequireJS and how you can use it to help manage JavaScript projects.

File splitting and file management headaches


A common first step is to split the JavaScript code from one large file into many smaller files. Even after creating just a handful of files, you have to start keeping track of which files depend on each other and making sure theyre loaded in the correct order. This soon becomes a long list that gets easy to mess up later down the line. For example: <script <script <script <script <script <script <script <script <script <script <script <script <script src=script3.js></script> src=script1.js></script> src=script13.js></script> src=script7.js></script> src=script6.js></script> src=script12.js></script> src=script4.js></script> src=script11.js></script> src=script5.js></script> src=script9.js></script> src=script8.js></script> src=script10.js></script> src=script2.js></script>

You can assume there are some dependencies here, but what are they? How do you find out? If Im new to the team, I wouldnt want to touch the order of these with a ten-foot pole. What if there was a better way? What if each file could declare its own dependencies so you didnt have to maintain this brittle master list? What if the relationships declared by each file could be understood by a loader of some sort that could load dependencies on demand, and the dependencies of those dependencies, and so on?

Introducing modules, AMD, and RequireJS


Lets get nostalgic for a moment. A few years back, using JavaScript on the server was just starting to get hot. Server-side libraries and JavaScript engines were being deployed but they didnt have a good, standard API for working with one another and defining dependencies. Getting one library to work with another required finagling and it was obvious that if JavaScript was going to scale it would need some common APIs. In January 2009, Kevin Dangoor wrote a blog post titled What Server Side JavaScript Needs outlining just thatwhat server-side JavaScript needed. As a means to fulfill these needs, he created a Google group named ServerJS where like-minded folk could collaborate. Soon enough, the group realized that many of its goals werent necessarily limited to the server and renamed the group to CommonJS. One of the standards that CommonJS worked toward was the module. A module is a self-contained piece of code (hows that for vague?) that defines that it is a module itself and, optionally, which other modules it depends on in order to function. Module B might call for module G and module M, and module G might call for modules D and W. By having a module standard, dependency management becomes easier. Rather than keeping some sort of implicit master list that must be kept in order, each module just defines its own dependencies. That mapping can be used to determine required resources and the order

27/32

in which they must be loaded. AMD The module concept was great for server-side development as it addressed how to load modules based on dependency definitions, but the browser-side JavaScript developers got a bit jealous. Why should such a useful mechanism be confined to the server? Sure, browsers would need to load modules asynchronously rather than synchronously, but that didnt mean the concept of modules and dependency definitions couldnt apply. The Asynchronous Module Definition, or AMD, was born for this purpose. It takes the module and dependency definition API from the server side and applies it to the asynchronous paradigm of the browser. RequireJS So what does RequireJS have to do with this? Well, even though you can define your modules and their dependencies with AMD, you need something smart that can take this dependency map, load the modules, and execute the modules in order. Thats the role RequireJS plays. Both RequireJS and AMD are open source, popular, and well-curated by James Burke.

Defining and requesting modules


At this point, lets jump straight into some code to help solidify some of these concepts. A module is almost always defined within a single file. Likewise, a single file only contains a single module definition. Defining a module, at its core, is as simple as the code below. The following definition is within a file named book.js. define({ title: My Sisters Keeper, publisher: Atria }); This code defines a book module using define(), an AMD function exposed by RequireJS. When you call it, youre essentially saying, Register what Im passing you as a module. In this case the module is the book object starting and ending with curly braces. By default, RequireJS assumes the module name is the file path following the base URL (explained below) excluding the extension. Because the file is named book.js, book is the default module name. When other code asks RequireJS for the book module, RequireJS will return the object defined above. Now you can make a bookshelf module in a new file named bookshelf.js and see how you can request the book module into it. define([ book ], function(book) { return { listBook: function() { alert(book.title); } }; }); Notice this ones a bit different than the book module. The book module didnt have any dependencies so it was simpler. This code passes an array of dependencies for bookshelf into define(). In this case, the only dependency is book. The second parameter is a callback function. If the book module hasnt been registered with RequireJS yet (in other words, book.js hasnt been loaded into the app yet), RequireJS will fetch it from the server.

28/32

Once book.js is loaded and the book module is registered, RequireJS will execute the callback function and pass the module (the book object defined previously) in as a parameter. The argument name isnt technically significant. You could have just as easily used function(a1337Book) or whatever name you wanted. In this case, it makes sense to have the argument name match the module name since its consistent and easy to understand. Finally, whatever object is returned from this callback function will be registered with RequireJS as the bookshelf module. In this case, its an object with a listBook() method that just invokes alert() on the books title. RequireJS tries to be as efficient as possible when loading multiple modules. For example, if multiple dependencies are listed, RequireJS will load all the dependencies in parallel.

Setting up the application


To get started with RequireJS and the new modules, set up a basic HTML page. Heres how it might look: <!DOCTYPE html> <html> <head> <title>RequireJS Example</title> <script data-main=js/main src=js/libs/require.js></script> </head> <body/> </html> Quite literally, you can build a large, single-page application without adding anything else to your HTML file just by manipulating the bodys content using JavaScript and loading HTML templates, which you can also do with RequireJS. For now, just take note the data-main attribute. This tells RequireJS where the bootstrap file isin this example, the file is main.js and it is located in the js directory (it assumes main has a js extension). Here is an example main.js file: require([ bookshelf ], function(bookshelf) { bookshelf.listBook(); }); Because you specified this file as your data-main in the HTML file, RequireJS will load it as soon as possible and it will be immediately executed. Youll notice some similarities with the previous module definitions, but instead of calling define() this code calls require(). The define() functionat least when dependencies are definedcompletes three steps: Loads the specified dependencies Calls the callback function Registers the return value from the callback function as the module The require() function only completes steps 1 and 2. The main.js file is just a bootstrap file. I dont need to have a main module registered with RequireJS because no other module will be calling for it as a dependency. The main.js file lists the bookshelf module as a dependency. Assuming the bookshelf module hasnt already been registered with RequireJS, it will load bookshelf.js. Once it loads bookshelf.js, it will see that bookshelf has the book module listed as a dependency. If the book module hasnt already been regis-

29/32

tered, it will then load book.js. Once thats done and book and then bookshelf have registered their respective objects as modules with RequireJS, the callback in main.js will be executed and bookshelf will be passed through. At that point you can do whatever you want with bookshelf. If needed, you can list multiple module dependencies and they will all be passed into the callback as soon as theyre all loaded and registered with RequireJS.

Configuring URLs and paths


I mentioned base URLs earlier. By default, the base URL is whatever directory contains the bootstrap file. In the example above, main.js is in the js directory along with book.js and bookshelf.js. This means the base URL is /js/. Instead of placing all the js files directly under the js directory, you could move book.js and bookshelf.js to /js/model/. The main.js file would need to be updated to look like this: require([ model/bookshelf ], function(bookshelf) { bookshelf.listBook(); }); Now main knows the correct location of bookshelf.js. Likewise, bookshelf.js would list the book dependency as model/book even though book and bookshelf are in the same directory. This leads into RequireJS configuration. I usually perform my configuration at the top of my bootstrap file. My main.js might look like this: require.config({ baseUrl: /another/path, paths: { myModule: dirA/dirB/dirC/dirD/myModule templates: ../templates, text: libs/text, } }); require([ bookshelf ], function(bookshelf) { bookshelf.listBook(); }); In this case, Ive manually changed my base URL to something completely different. Personally, Ive never needed to configure this but its there to demonstrate one of the many configuration options available. For more details, see the RequireJS documentation on configuration options. The code above also demonstrates how to configure paths. A path acts as an alias for a specific directory or module. In this case, rather than having to type out dirA/dirB/dirC/dirD/myModule when listing dependencies throughout my modules, I can now just type myModule. Ive also set up a path for accessing a templates directory that is a sibling to my js directory. Lastly, Ive set up a path for accessing the RequireJS text plug-in more easily throughout my modules. Although not covered in this article, you can easily load HTML templates using this text plug-in. For more details, see the text plug-in documentation.

30/32

Constructor modules
So far, the modules youve seen have all been object instances; bookshelf was an object and book was an object. In reality, modules are often constructors (similar to classes in classical languages). In this example, you may want to make the book module a constructor. Library could then create and store multiple book objects. The book module would now look something like this: define(function() { var Book = function(title, publisher) { this.title = title; this.publisher = publisher; }; return Book; }); Notice here that youre passing a function into define() instead of an object. When you pass a function instead of a regular object, the function will get executed by RequireJS and whatever is returned from the function then becomes the module. Here the book constructor is returned. The bookshelf module would now look like this: define([ book ], function(Book) { var books = [ new Book(A Tale of Two Cities, Chapman & Hall), new Book(The Good Earth, John Day) ]; return { // Notice Ive changed listBook() to listBooks() now that // I am dealing with multiple books. listBooks: function() { for (var i = 0, ii = books.length; i < ii; i++) { alert(books[i].title); } } }; });

Optimizing for deployment


Assuming youve appropriately broken your code into granular modules, you potentially have hundreds of files and unless you do some optimization your code will be making hundreds of HTTP requests. Fortunately, you can use the RequireJS optimizer to solve this problem. Generally, you set up the optimizer to run during your deployment process. The RequireJS optimizer discovers which files are used within your app by scanning the code for modules and their dependencies. It then minifies the files (shortens your code to make the files really small) and concatenates them (smashes them together to make a single file). In the end, it outputs a single JavaScript file that contains all of your app code. This single file should then take the place of main.js when you deploy.

31/32

When a user loads index.html, it will in turn load RequireJS, which will then load the main.js file. The main. js file, this time, will not only contain your usual main.js bootstrap code but also all the minified, concatenated code of the rest of your app. All the modules in the file will register themselves with RequireJS at that time. When main starts asking for dependencies and those dependencies start asking for dependencies, RequireJS will recognize that all the required modules have already been loaded and forego loading them from the server again. Of course, the optimizer has its own set of options. You can optimize your app down to a few different files representing sections of your app instead of a single large file. You can also use different minifier libraries, exclude files from concatenation, or even minify CSS. This article has covered a great deal of ground, but theres plenty more to learn about dependency management. The RequireJS website is a great place to start.

ABOUT THIS ARTICLE


Aaron Hardy architects dynamic, online apps at big companies, little companies, and everything in between. Hes been bestowed fancy titles at said companies and earned his 1337 status in Information Systems Management from Brigham Young University. http://aaronhardy.com @Aaronius

ONLINE RESOURCES His blog about JavaScript http://aaronhardy.com/ RequireJS http://requirejs.org/ Documentation http://requirejs.org/docs/api.html

appliness

DONT WORRY, BE APPLI

Getting started with HTML mobile application development using jQuery mobile, RequireJS and BackboneJS

In this introductory tutorial, I will cover BackboneJS, jQuery Mobile and RequireJS, to help web developers to build a modular mobile application. With using PhoneGap , it will be very easy for you to package and deploy the application to multiple platforms.

We will build a simple sample application step by step. With this progressive enhanced demo application, we will introduce: How to modularize application using BackboneJS,jQuery Mobile and RequireJS; How to use Backbone View, Collection/Model and Routers. How to decouple mobile view and model/collection using Backbone events.

SAMPLE APPLICATION
The demo application has 2 views:Home View and List View. The Home view features a list of categories for IT books, when the List View actually lists the books available in the store.

d n u o laygr

- Backbone - rookie s .j e r i u q e R - intermediate e l i b o M y r e - jQu - expert

Difficulty

Todo list

- modules - MVC

- mobile dev

by Mark Dong

You can test the application here:

JAVAscript library and css


This tutorial will help you start combining jQuery mobile , Backboen.js and Require.js to build an mobile application with separation of concerns. The javascript libraries we will use are listed as below: jQuery: http://jQuery.com/ Require and plugin: require.js: http://requirejs.org/ require plugin text.js:http://requirejs.org/docs/download.html#text Backbone and Underscore: UnderscoreJS removed AMD (require.js) support since version 1.3.0. And Backbone.js was affected as well. Fortunately, James Burke maintains an AMD compatible version of underscoreJS and backboneJS. That is why the download links of underscore and backbone below are not pointed to the official sites. amd-underscore: https://github.com/amdjs/underscore amd-backbone: https://github.com/amdjs/backbone jQuery Mobile: http://jQuerymobile.com/

34/45

Project structure

bootstrap application ENTRY POINT APPLICATION CONTROLLER MODEL

VIEWS AND TEMPLATES

IDEA
In a jQuery Mobile application, each view on the mobile device is a page and is declared with an element using data-role=page attribute. So in this tutorial, when we say view, it means page of jQuery Mobile. Multiple pages could be organized inside the body of html page and jQuery Mobile will manage them automatically, just like multi-page template structure described in jQuery Mobile doc. But we all know, loos coupled architecture is better. Using Require.js and Backbone.js, we can divide the pages into separate files as View modules with templates. It allows modular development and testing. It is also easier to extract the model and logic of view into behavior objects. Lets start building this modular application step by step.

index.html

index.html is just a shell page. <!DOCTYPE html> <html> <head> <title>DEMO APPLICATION</title> <meta name=viewport content=width=device-width, initial-scale=1/> <meta http-equiv=Access-Control-Allow-Origin content=*/> <link rel=stylesheet href=css/jquery.mobile-1.1.0.css /> <link rel=stylesheet href=css/style.css /> <!-- we will use cordova to package the mobile application--> <script src=js/vendor/phoneGap/cordova-1.6.0.js></script>

35/45

<!-- require.js: data-main attribute tells require.js to load js/main.js after require.js loads. --> <script data-main=js/main src=js/vendor/require/require.js></script> </head> <body> </body> </html>

Once require.js is loaded, it will take the value of data-main attribute and make a require call. In main.js, we usually configure path settings for require.js.

entry point: js/main.js


In main.js, we configure require and jQuery mobile and then bootstrap application. require.config({ //path mappings for module names not found directly under baseUrl paths: { jquery: vendor/jqm/jquery_1.7_min, jqm: vendor/jqm/jquery.mobile-1.1.0, underscore: vendor/underscore/underscore_amd, backbone: vendor/backbone/backbone_amd, text: vendor/require/text, plugin: plugin, templates: ../templates, modules: ../modules, model: ../model } }); //1. load app.js, //2. configure jquery mobile to prevent default JQM ajax navigation //3. bootstrapping application define([app,jqm-config], function(app) { $(document).ready(function() { console.log(DOM IS READY);// Handler for .ready() called. }); app.initialize(); }); Require.js will load and evaluate app.js and jqm.config.js first as the the dependencies of the module. App.js is mapped to app so that we can call app.initialize() to bootstrap Backbone application.

Disable jQuery Mobile AJAX navigation system: jqm-config.js


We all know that there are routing conflicts between jQuery mobile and Backbone.js. There are several ways to workaround it. I like the magic from Christophe Coenraets (Using Backbone.js with jQuery

36/45

Mobile:http://coenraets.org/blog/2012/03/using-backbone-js-with-jQuery-mobile/) . In jqm-config.js, we disable the default jQuery Ajax navigation system. Then, use Backbone router to control application and manually call changePage() function to switch between the views. We also remove the hide page from DOM so there is only one view in the DOM every time. define([jquery], function($){ use strict; $(document).bind(mobileinit, function () { $.mobile.ajaxEnabled = false; $.mobile.linkBindingEnabled = false; $.mobile.hashListeningEnabled = false; $.mobile.pushStateEnabled = false; // Remove page from DOM when its being replaced $(div[data-role=page]).live(pagehide, function (event, ui) { $(event.currentTarget).remove(); }); }); });

Setup application router: router.js


We use Backbone router as the nav system of the application. Every time user clicks a link, jQuery mobile will change the hash segment which will trigger Backbone to navigate user to the right view thru Backbone router. Here is router.js. The root url () is mapped to showHome() function, the same with /#home hash. define([jquery, underscore, backbone,modules/home/home, model/book/bookCollection, modules/list/books, jqm], function($, _, Backbone,HomeView,BookCollection,BookListView) { use strict; var Router = Backbone.Router.extend({ //define routes and mapping route to the function routes: { : showHome, //home view home: showHome, //home view as well list/:categoryId : showBooks, *actions: defaultAction //default action }, defaultAction: function(actions){ this.showHome(); }, showHome:function(actions){ // will render home view and navigate to homeView }, }); return Router;
37/45

});

Bootstrapping application : app.js


app.js will create backbone router object and then expose the function to allow bootstrap backbone application. define([jquery,underscore, backbone,router],function ($, _, Backbone,Router) { use strict; var init=function(){ //create backbone router var router=new Router(); Backbone.history.start(); }; }); return{ initialize:init }

Home View
Now, we are ready to render the first view : home view. 1. Define a module for home view: home.js To render homeView using template, we create a object by extending Backbone.View. Here are homeView codes: js/modules/home/home.js : define([jquery, underscore, backbone, text!modules/home/homeViewTemplate.html], function($, _, Backbone, homeViewTemplate){ var HomeView = Backbone.View.extend({ //initialize template template:_.template(homeViewTemplate), //render the content into div of view render: function(){ //this.el is the root element of Backbone.View. By default, it is a div. //$el is cached jQuery object for the views element. //append the compiled template into view div container this.$el.append(this.template()); //return to enable chained calls return this;

38/45

} }); return HomeView;

});

text.js, a RequireJS plugin, can help us load text-based template file through text! prefix so we can separate the template from script file. modules/home/homeViewTemplate.html will be loaded automatically and then passed to the module function as the argument homeViewTemplate. Inside the module function, we use the template engine of Underscore.js to compile the template, and then append the result html segment into views container: this.el, which is a div by default. So we have rendered the view but have not inserted it into DOM. 2. Define the template for home view: homeViewTemplate.html The template for homeView is a static page: modules/home/homeViewTemplate.html <div data-role=content > <div class=content-primary> <p class=intro> <strong>Welcome.</strong> It is a simple demo to show how to build mobile application using JQuery Mobile, Backbone.js and Require.js . </p> <ul data-role=listview data-inset=true > <li data-role=list-divider class=listTitle>IT BOOKSTORE</li> <li data-theme=a><a href=#list/1>JavaScript</a></li> <li data-theme=a><a href=#list/2>NodeJS</a></li> <li data-theme=a><a href=#list/3>IOS</a></li> </ul> </div><!-- /content --> </div> As we can see, in our example application, the template of HomeView has no Header and Footer. All contents are place into content div with data-role=content specified. jQuery Mobile uses HTML5 data- attributes to allow for markup-based initialization and configuration of widgets. Inside content container, we add a listview with using data-role=listview . Each item has a hardcoded link which will change the hash segment of the url. For example, #list/1 , 1 is categoryId, so we will use it to fetch book data from matching json file later. We will add the mapping in the routes of router.js later to allow Backbone to invoke mapping functions to response users interaction. 3. ShowHome in router.js We use showHome() to insert the view into DOM and present HomeView.The updated router.js is as below: define([jquery, underscore, backbone,modules/home/home, model/book/bookCollection, modules/list/books, jqm], function($, _, Backbone,HomeView,BookCollection,BookListView) { use strict; var Router = Backbone.Router.extend({ //define routes and mapping route to the function routes: { : showHome, //home view home: showHome, //home view as well list/:categoryId : showBooks,

39/45

*actions: defaultAction //default action defaultAction: function(actions){ this.showHome(); }, showHome:function(actions){ // will render home view and navigate to homeView var homeView=new HomeView(); homeView.render(); this.changePage(homeView); }, init:true, showBooks:function(categoryId){ //create a collection var bookList=new BookCollection(); //create book list view and pass bookList as the collection var bookListView=new BookListView({collection:bookList}); //need to pass this as context bookListView.bind(renderCompleted:Books,this.changePage,this); //update view bookListView.update(categoryId); }, changePage:function (view) { //add the attribute data-role=page for each views div view.$el.attr(data-role, page); //append to dom $(body).append(view.$el); if(!this.init){ $.mobile.changePage($(view.el), {changeHash:false}); }else{ this.init = false; }

} }); });

return Router;

First, add one more dependency for router.js: modules/home/home, which is a module defined in home. js; and then pass it to router module function as argument HomeView. In showHome function, we create homeView object and render the view content, then pass homeView to changePage function. The changePage(view) is responsible for setting jQuery Mobile data-role attribute of views root element (view.$el) and appending it into DOM. Now, we have a html document containing one jQuery mobile page div. This is the first page of our demo application. jQuery mobile will find and enhance the pages in the DOM and transition to the first page automatically once the DOM is ready. So it is not necessary to call jQuery mobile $.mobile.changePage() manually for initial page.
40/45

4. Run Open the browser and run the application by http://localhost/ (assuming you deploy your application on the root of your web server) , you will see the first view of the application:

LIST VIEW
When user clicks any item in the list, the application will navigate to the second view:book list view, to show the books of the selected category. 1. Prepare json data To make this demo application as simple as possible, we emulate backend service using local json data. For the list view, we need 3 local json data files mapping to the category item: JavaScript, NodeJS and IOS. The name of json file should follow the format of category + id + .json, like data/category1.json, data/category2.json and data/category3.json. For example , category1.json looks like as following : [ { id: 1001, name: JavaScript & jQuery: The Missing Manual }, { id: 1002, name: JavaScript: The Definitive Guide }, { id: 1003, name: JavaScript: the best parts }, { id: 1004, name: JavaScript: The Good Parts }, { id: 1005, name: JavaScript Patterns }, { id: 1006, name: Head First JavaScript } ]

2. Define a module for model (bookModel.js) and collection (bookCollection.js) Before we get into the list view, we need to define the model of book and the collection.
41/45

Book model is very simple. We just extend Backbone.Model and define the default value for the attributes.

define(function(){ var Book=Backbone.Model.extend({ //default attributes defaults:{ id:, name:, category: } }); return Book; });

Using Book model, we define the collection of book: bookCollection.js define([jquery, underscore, backbone,model/book/bookModel], function ($, _, Backbone,Book){ var Books=Backbone.Collection.extend( // Book is the model of the collection model:Book, //fetch data from books.json using Ajax //and then dispatch customized event fetchCompleted:Books fetch:function(categoryId){ var self=this; var tmpItem; //fetch the data using ajax var jqxhr = $.getJSON(data/category + categoryId+.json) .success(function(data, status, xhr) { $.each(data, function(i,item){ //create book for each item and then insert into the collection tmpItem=new Book({id:item.id,category:categoryId,name:item.name}); self.add(tmpItem); }); //dispatch customized event self.trigger(fetchCompleted:Books); }) .error(function() { alert(error); }) .complete(function() { console.log(fetch complete + + this); }); }

});

return Books; });

42/45

Add dependency for BookCollection. BookModel is passed to the module function as the argument Book.The item of collection is Book. So we set collections attribute model as Book.

For bookColllection, we will add a function fetch to read the json file and fill into the collection. Once we get the book list successfully, we will trigger a customized event : fetchCompleted:Books. Later, we will bind the event listener on this event in the book list view. 3. Create dynamic template for list view: bookViewTemplate.html Book list view is also rendered with the template. However, it is a dynamic template and is different with homeViews template. We use <%...%> to add script and then Underscore template can execute arbitrary JavaScript code inside <% ... %>. In the following template, the variable data will be passed from template function. Of course, you can use any variable name you prefer. <div data-role=header data-position=fixed> <h1>Books</h1> <a href=#home data-icon=home data-iconpos=notext data-direction=reverse>Home</a> </div> <div data-role=content> <ul data-role=listview data-inset=true > <!-- data is passed from template engine, and templat engine will execute the scripts inside <% %> --> <% for (var i = 0; i < data.length; i++) { %> <% var item = data[i]; %> <li> <a href=#detail/<%=item.name%>/<%= item.id%>> <%= item.name %></a> </li> <% } %> </ul> </div> 4. Define a module for list view: book.js We have already prepared model, collection and template. Now its time to make a view: book.js define([jquery, underscore, backbone, text!modules/list/bookViewTemplate.html], function ($, _, Backbone, bookViewTemplate) { use strict; var BookListView = Backbone.View.extend({ template: _.template(bookViewTemplate), update:function(categoryId){ //set callback of the event fetchCompleted:Books this.collection.bind(fetchCompleted:Books,this.render,this); this.collection.fetch(categoryId); }, render: function(){ this.$el.empty();

43/45

} });

//compile template using the data fetched by collection this.$el.append(this.template({data:this.collection.toJSON()})); this.trigger(renderCompleted:Books,this); return this;

return BookListView; }); First, add text dependency bookViewTemplate . BookListView has two functions: update(categoryId) and render() . The update(categoryId) will call collections fetch function to get book list of selected category by categoryId. Before that, we need to bind the render() function as eventListener for the event fetchCompleted:Books. Once we get the data successfully, we will render the view with using template. In the render function, we use Underscore template engine to compile the template and the data to produce the html segments and then insert into views div container. We also trigger the event renderCompleted:Books to notify router that the view is ready and please change page. In the real case, it is better to cache the template and the view to improve performance. 5. Add routes mapping in router.js Now back to router.js. We will tell router.js how to route application once user clicks category item of HomeView. The same with other modules, we need to add dependencies first. routes: { : showHome, //home view home: showHome, //home view as well list/:categoryId : showBooks, *actions: defaultAction //default action },

Now, once user clicks the item and changes hash segment of url, Backbone will call showBooks() and pass the category id. The following codes are what we will add in router.js. init:true, showBooks:function(categoryId){ //create a collection var bookList=new BookCollection(); //create book list view and pass bookList as the collection var bookListView=new BookListView({collection:bookList}); //need to pass this as context bookListView.bind(renderCompleted:Books,this.changePage,this); //update view bookListView.update(categoryId); },
44/45

//4. argument view is passed from event trigger

changePage:function (view) { //add the attribute data-role=page for each views div view.$el.attr(data-role, page); //append to dom $(body).append(view.$el); if(!this.init){ $.mobile.changePage($(view.el), {changeHash:false}); }else{ this.init = false; }

As the codes shows, we add an attribute init, which is a flag attribute. Like we mentioned before, for the initial page of jQuery Mobile application, jQuery mobile will enhance and present it automatically. So we should not call $.mobile.changePage() manually. In the function showBooks() , we create BookCollection and bind it with BookListView. Before updating the view (which will call bookCollections fetch function) , we bind the changePage() function with the event renderCompleted:Books. So when the view is rendered , we will call changePage() to insert it into DOM and then enhance page and transit to the new page. In the function changePage(), if it is not the initial page, we manually call jQuery mobile function $.mobile.changePage() to load new page and apply transition effect.

CONCLUSION
It is just a very beginning application and far away from a real one. Actually, there are lots of things we can improve, like caching template and view, or even separating the control logic from router. RequireJS+BackboneJS+jQuery Mobile is a powerful combination and an easy to use technology. Especially, with requireJS and BackboneJS, we can modularize the application development and make the application clean and clear. In this introductory tutorial, weve only scratched the surface of jQuery mobile, BackboneJS and requireJS. If you want to learn more, you can go to the official sites of these libraries and frameworks. Thank you for taking your time to read this tutorial!

MORE INFORMATION

>

ABOUT THIS ARTICLE


Mark Dong works in Adobe! for 6 years in China. Flex, JavaScript and Java developer with much experience on enterprise RIA architect and project manager in FSI and Energy industry. Mark is also the author of The road of Flex master.

ONLINE RESOURCES JQuery Mobile official website http://jquerymobile.com/ JQuery UI http://jqueryui.com/ Touch Punch https://github.com/furf/jquery-ui-touch-punch

>

appliness

DONT WORRY, BE APPLI

Simple Offline Data Synchronization for Mobile Web and PhoneGap Applications

Being able to work offline is an expected feature of mobile applications. For data-driven applications, it means that you the developer will have to store (a subset of) your application data locally, and implement a data synchronization mechanism that keeps your local and server data in sync.

In this article, I describe a simple data synchronization strategy that uses the devices (or browsers) SQLite database. The implementation currently leverages the Web SQL API (even though the W3C is no longer actively maintaining the spec) because both iOS and Android support it, but they dont support IndexedDB, the official alternative. However, the API described below getLastSync(), getChanges(), applyChanges() defines a generic synchronization contract, and the solution can be expanded and made pluggable: You could create different synchronization objects, each providing a different implementation of these methods. You could then choose which object to plug in based on the context and the platform your application is running on.

d n u o laygr

- PhoneGap - SQLite - SQL

Difficulty
- rookie - intermediate - expert

Todo list

- get online - get offline - sync content

by Christophe Coenraets

Try it in the Playground

Before looking at the code, you can try some offline syncing in this a hosted playground: 1. Open the Offline Client Playground in Chrome or Safari (they both support Web SQL). 2. Click the Synchronize button. 3. Look at the log (the textarea in the middle of the screen): Because its the first time you use the application, all the employees have been downloaded from the server and inserted in your local SQLite database. 4. Clear the log, click the Synchronize button, and look at the log again: because you now have an upto-date local version of the data, the server didnt return any change and your local database remains unchanged. 5. In another tab, open the Server Admin PlayGround. 6. Modify an existing employee and click Save. (Dont worry, its using your own session-based data set). 7. Go back to the Offline Client tab, click Synchronize, and notice that the server returned one change, and that it was applied to your local database. 8. Go back to the Server Admin tab and modify (create, update, delete) other employees. Switch back to the Offline Client tab, click Synchronize, and see how these changes are applied to your local database.
47/50

9. You can also use the Resources Tab in the Chrome Developer Tools to inspect your local database.

Server API
The only piece of infrastructure you need at the server side is an API that returns the items that have changed (created, updated, or deleted) since a specific moment in time expressed as a timestamp. Here is the RESTful API call used in my application: http://coenraets.org/offline-sync/api/employees?modifiedSince=2012-03-01 10:20:56 The format of the data returned by the server is up to you and is part of the contract between the client and the server. In this application, the server returns the changes as an array of JSON objects. The serverside technology (RoR, PHP, Java, .NET, ) and database system (SQL, NoSQL, ) you use to generate the list of changes is also totally up to you. I provide a simple PHP implementation as part of the source code. That implementation manages a session-based data set that provides an isolated and transient playground. In a real-life application, youd obviously get the data from some sort of database.

Client API
At the client side, our synchronization API consists of three methods. getLastSync() A method that returns a timestamp to be used as the query parameter for the next synchronization request. A common practice is to persist a timestamp after each synchronization request. But things can go wrong and the timestamp itself can get out-of-sync. I prefer to recalculate the lastSync timestamp before each synchronization request. getLastSync: function(callback) { this.db.transaction( function(tx) { var sql = SELECT MAX(lastModified) as lastSync FROM employee; tx.executeSql(sql, this.txErrorHandler, function(tx, results) { var lastSync = results.rows.item(0).lastSync; callback(lastSync); } ); } ); } getChanges() This is a wrapper around an Ajax call to the server-side API that returns the items that have changed (created, updated, or deleted) since a specific moment in time defined in the modifiedSince parameter. getChanges: function(syncURL, modifiedSince, callback) { $.ajax({ url: syncURL, data: {modifiedSince: modifiedSince}, dataType:json, success:function (changes) { callback(changes); }, error: function(model, response) {

48/50

});

alert(response.responseText);

applyChanges() A method that persists the changes in your local data store. Notice that SQLite supports a convenient INSERT OR REPLACE statement so that you dont have to determine if you are dealing with a new or existing employee before persisting it. applyChanges: function(employees, callback) { this.db.transaction( function(tx) { var l = employees.length; var sql = INSERT OR REPLACE INTO employee (id, firstName, lastName, title, officePhone, deleted, lastModified) + VALUES (?, ?, ?, ?, ?, ?, ?); var e; for (var i = 0; i < l; i++) { e = employees[i]; var params = [e.id, e.firstName, e.lastName, e.title, e.officePhone, e.deleted, e.lastModified]; tx.executeSql(sql, params); } }, this.txErrorHandler, function(tx) { callback(); } ); }

Synchronization Logic
With these server and client APIs in place, you can choreograph a data synchronization process as follows: sync: function(syncURL, callback) { var self = this; this.getLastSync(function(lastSync){ self.getChanges(syncURL, lastSync, function (changes) { self.applyChanges(changes, callback); } ); });

49/50

Final Notes
This solution currently supports unidirectional (server to client) data synchronization. It could easily be expanded to support bidirectional synchronization. This solution currently implements logical deletes: items are not physically deleted from the table, but the value of their deleted column is set to true. As mentioned above, you could replace the Web SQL implementation with another data access strategy. For example, take a look at Brian Leroux Lawnchair for another local persistence solution.

Source Code
The source code is available in this GitHub repository.

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 PhoneGap official website http://phonegap.com/ Client Playground http://coenraets.org/offline-sync/client-app/ Sample Source https://github.com/ccoenraets/offline-sync

>

appliness

DONT WORRY, BE APPLI

HTML5 Application Cache How To

There are a lot of great blog posts, articles, and videos about HTML5 Application Cache, but because its fairly new and the spec is still evolving, its hard to get your head around all of the intricate details.

What is it?
The Application Cache is a new HTML5 capability that is different from the normal browser cache that weve had for years. The normal browser cache maintains copies of recent files that you have accessed and keeps copies of those files on your computer so that when you need the same file again, it wont have to re-download it. Other than some simple browser settings to control the overall cache size and a few meta tags to turn it on and off, you really dont have any useful control over how its used. The application cache is a web-application-specific cache, the content and behavior of which is controlled by the application itself. The application cache is persistent and provides full off-line capabilities. It is currently supported in Chrome (v4.0+), Safari (v4.0+), Firefox (v3.5+), and Opera (v10.6+). Its not currently supported in any shipping version of Internet Explorer, but it is coming in IE10.

d n u o laygr

Difficulty
- rookie - intermediate - expert

- HTML5 - offline - javascript

Todo list

- store stuff - manage cache - offline apps

by Greg Wilson

Try it now with an offline-enabled website:


Go to http://phraffle.com using Chrome, Firefox, Safari or Opera. Youll see a simple one-page site that I created that people use to raffle off giveaways at speaking events. Nothing special, right? Now disconnect from the Internet and go to the site again using the same browser. It still works in your browser as if you were still connected! Your browser now has a copy of the website cached in the application cache and it will remain cached there until the user removes it.

Looking under the hood from Chrome browser:


If you are using Chrome, you can check out what was downloaded at chrome://appcache-internals/:

52/58

You can also see the files being downloaded from Chromes JavaScript console:

The console after hitting the same site for a second time:

More information about cache-related events is below.

Try an offline-enabled HTML5 Web app on an iPhone or iPad:


If you have an iPhone, iPad or iPod Touch, go to http://phraffle.com using Safari. Tap on the share icon and select Add to Home Screen (you will see a popup pointing to the share button shortly after the page loads thanks to a cool JavaScript lib at http://cubiq.org/add-to-home-screen). Youll now see what looks like a regular app on your home screen with my custom icon. Now, tap the icon to run the app from your home screen (with or without Internet). Notice that the app is running full-screen with no Safari browser controls. This is an iOS HTML5 web app.

Ill show you how to set this up later in this article.

53/58

Setting up application caching:


Here are the exact steps I used to set up the above example: I modified the <html> tag to reference my soon-to-be-created HTML manifest <html manifest=phraffle. appcache> This should be added to each HTML file that will be cached so that the users browser will be instructed to cache the files regardless of which HTML file was used as an entry point to your site. I then created my cache manifest file called phraffle.appcache in the web root folder. This file contains a list of files required to run my site offline. You can view mine here. Notice that it contains all of my HTML, JavaScript, CSS and image assets. The manifest file name can be named anything, but .appcache seems to be an established convention. CACHE MANIFEST # Version 1.5 NETWORK: * CACHE: index.html jquery-1.7.2.min.js jquery.backgroundPosition.js jquery.spritely.js raffle.js images/reel_blur_numbers.png images/reel_blur.png images/reel_dash.png images/reel_normal_numbers.png images/reel_normal.png images/reel_normal.psd images/reel_x.png My web server has no idea what a .appcache file is so, by default, it will serve it up as a regular text file. In order for app caching to work properly, the cache manifest file needs the MIME type set to text/ cache-manifest. Im using Apache web server, so I simply created a .htaccess in my web root folder that has the following line: AddType text/cache-manifest .appcache If you are using IIS or another web server, youll need to do a quick web search to determine how to associate the mime type text/cachemanifest to your .appcache file extension. Thats all that is needed to cache the files. It works offline in any compatible browser, including mobile Safari, Android browser, desktop Chrome, Safari, Firefox, and Opera.

54/58

Breaking down the manifest file:


The first line is CACHE MANIFEST (without quotes) and is required. Comments start with # The CACHE: section contains a list of files to be cached. Wildcards are not allowed here. You must list each file that needs to be cached. In my file, it wasnt necessary to add the index.html line to the list of cached files since every file containing <html manifest=> is automatically cached, but its still good practice to include it. The NETWORK: section contains a list of online resources that are used by your app. This is the most misunderstood part of the manifest file. Cached apps do not have access to network resources unless those resources are listed in the NETWORK section of the cache manifest. Wildcards are allowed here (thankfully!). In my file above, I simply used * which basically means you can access anything you want. (You may be wondering what network resources my silly apps needs Im using TypeKit and Google Analytics, both of which require Internet access). If I omitted the NETWORK section of my manifest file, my app would still work, but the fancy TypeKit font I used would not be loaded so the boring backup font of Arial would be used, and Google Analytics would not record the page hit. Even if the user is online, access attempts to any network resource would be ignored as if the app were permanently offline. If a filename is listed in the NETWORK section (e.g. login.php), the current site URL will be prepended. So listing login.php in the NETWORK section is equivalent to listing http://mysite.com/ login.php. In this case, the login.php file will not be cached and any accesses to the http://mysite. com/login.php will be from the website itself, not the cache. You can see the specific rules on how the NETWORK section is handled in the actual spec (see bullet 30.) I recommend starting with a simple * when you first start playing around with this stuff. You can always change it to be more specific after you get everything working. The FALLBACK: section specifies fallback pages if an online resource is inaccessible. I did not need this feature in my app, but below is an example of what a FALLBACK section would look like. The first URI is the resource, the second is the fallback. Both URIs must be relative and from the same origin as the manifest file. Wildcards may be used. FALLBACK: *.html /offline.html *.jpg /images/missing.jpg

iOS Making the web app run full-screen without Safari controls:
After the above changes, I can use mobile Safari on my iPhone and iPad to access the page. After accessing it once, its saved for offline use. I wanted it to be more app-like, so I added the following meta tag to the index.html: <meta name=apple-mobile-web-app-capable content=yes/> This will make the cached app run in full-screen mode so the user doesnt see the Safari controls.

55/58

iOS Adding custom icons and a startup image:


By default, iOS will use a screenshot as the app icon. I wanted something a little nicer. I created the 3 required icon sizes (5757, 7272 and 114114) and added the following 3 lines to my index.htmls HEAD section: <link rel=apple-touch-icon href=icon57.png /> <link rel=apple-touch-icon sizes=72x72 href=icon72.png /> <link rel=apple-touch-icon sizes=114x114 href=icon144.png /> Youll notice that the images I used are square with no rounded corners (e.g. http://phraffle.com/icon144. png). The rounded corners, drop shadow, and reflection are added by the device automatically. You can avoid these enhancements by adding -precomposed to the filename (e.g. icon72-precomposed. png). Its also possible to add a startup image for a web app. I didnt do this on mine, but if you want to try it, heres all you need in your html: <link rel=apple-touch-startup-image href=startup.png> Last year, the Financial Times rolled out their new iPad webapp using this same technique to avoid the Apple app-store rules (specifically, Apples requirement to take 30% of any in-app purchase). Obviously this isnt a perfect solution for many apps, but its a good option to have in some cases. By the way, if you would like to build more sophisticated apps using HTML/CSS/JS, and take advantage of native APIs and true app-packaging, check out PhoneGap.

IMPORTANT Updating your app (updating the users cached files):


If you make any changes to your HTML, CSS, or other cached assets, you will need to modify the cache manifest file so that users with previously cached versions of the files receive fresh ones. The contents of the manifest file must change for it to be re-processed on the client side (simply updating the timestamp of the file isnt enough). Youll notice that in my phraffle.appcache file, I have a simple comment with an arbitrary version number. I simply increment the number each time I modify any files in the cache list to force previously cached files to be refreshed. Its not currently possible to update a single file in the cache list. Its all or nothing. When the browser sees a newly modified cache manifest file, it will re-download all files in the CACHE section again. This is obviously a bit of a shortcoming. Hopefully well see this addressed in the future. If any of the files listed in the manifest are not accessible, the caching will abort. The JavaScript console in Chrome will show the file caching activity, so you will quickly see any 404 or similar errors. I highly recommend validating your cache manifest using the following http://manifest-validator.com/ Double-reload needed when you access phraffle.com, your browser always checks the manifest file to see if its been updated (you will see this happen in the JavaScript console). If the manifest was updated, the browser will download all of the files in the cached file list, BUT, the original content will have already loaded at this point (remember that its already cached, so it loads super fast!). This means that you will not see the new content until you hit refresh again. This is a bit of a pain at times! There is a workaround that you can implement using the following JavaScript code: if (window.applicationCache) { applicationCache.addEventListener(updateready, function() { if (confirm(An update is available. Reload now?)) { window.location.reload(); } }); }

56/58

JavaScript Application Cache APIs:


There is an AppCache API that provides several hooks into the caching. Everything is defined in the applicationCache object. The two main methods are updateCache() and swapCache(). In addition, there are several cache events that you can listen for: checking - Fired once when the app reads the manifest file to see if it has changed. noupdate - The manifest file has not changed. downloading - Files are being downloaded progress - Fired once per each file downloaded. If you have 15 files, youll see 15 progress events. Unfortunately, the event itself doesnt contain information about which file just completed, so its fairly limited in its current form. cached - Files have finished downloading. updateready - A new copy of the cache is ready to be swapped in. obsolete - The manifest file is code 404 or code 410; the application cache for the site has been deleted. error - An error occurred when loading the manifest, its parent page, or a listed resource, or the manifest file changed while the update was running. The cache update has been aborted. If you want to see these fire, you can use the following code: function logEvent(event) { console.log(event.type); } window.applicationCache.addEventListener(checking,logEvent,false); window.applicationCache.addEventListener(noupdate,logEvent,false); window.applicationCache.addEventListener(downloading,logEvent,false); window.applicationCache.addEventListener(progress,logEvent,false); window.applicationCache.addEventListener(cached,logEvent,false); window.applicationCache.addEventListener(updateready,logEvent,false); window.applicationCache.addEventListener(obsolete,logEvent,false); window.applicationCache.addEventListener(error,logEvent,false); Although its not part of the applicationCache object, you might want to know how to programmatically check if the user is online or offline. This is done by simply checking navigator.onLine (boolean).

Google Analytics, Typekit and other services with Application Caching


When I first offline-enabled phraffle.com, I didnt have the NETWORK section in my cache manifest. All of the files were still cached, but to my surprise, my Typekit bello-pro font wasnt displaying and I was suddenly not recording hits on Google Analytics, even when I was online. Typekit, Google Analytics and many other services obviously require internet access, but my lack of a NETWORK section in my cache manifest meant that all external URLs were inaccessible. Once I added the NETWORK section, everything worked normally again (when I was online of course).

57/58

Other fun facts, quirks, and ramblings


I was unable to find any definitive information about the size limitations of the app cache. I did some testing with Chrome (v19), and it seems to be capped at around 50MB. When I tried a file over 50MB, it gave a simple error in the JavaScript console with no meaningful description. Ive read that Firefox allows over 500MB, but I havent confirmed this. Tobie Langel, one of the software engineers at Facebook, recently wrote a blog post listing several enhancements that Facebook would like to see as the spec moves forward. I think he covers it quite well! Do NOT add the actual cache manifest file to the list of files to cache in the manifest. Weird, endlessloop, recursive stuff will occur. From my extensive browsing on stackoverflow, I can tell you one of the most common mistakes to getting this working correctly is forgetting to change the MIME type for the cache manifest file itself or forgetting to put the colon on CACHE:. Weird iOS full-screen bugs There are some weird cache issues with full-screen, run-from-home-screen iOS web apps. At first I thought I was going nuts, because I would clear Safaris cache, yet I would still see old content until I re-ran the app a few times. I found many reports of others seeing the same thing. My advice is to add something to your page so you can confirm that the content did indeed refresh. It seems to be fine now that I have my config finalized, but it can really make development a challenge when you suddenly cant clear the cache. From iOS devices, you can see a list of websites that have saved data using app cache by going to SETTINGS, GENERAL, SAFARI, ADVANCED, WEBSITE DATA. This screen allows you to selectively delete the data on a site-by-site basis. You can also clear the entire Safari cache on the main advanced screen. Clearing Safaris cache also clears all app cache files for all sites. Android Application caching is supported on Android, but I couldnt find a way to run it full-screen without any browser controls. Let me know if you know how to do this. I suspect that youll need to make a full app out of it (using PhoneGap of course!).

Resources I used
Here are the resources I found while researching this: A Beginners Guide to using the Application Cache - HTML5Rocks.com tutorial Building and Offline Mobile Web Application by Christian Cantrell Offline Web Application Dive info HTML5 Take this Offline Appcache Facts - Good reference for the cache manifest file contents. This page claims that Firefox doesnt allow a simple * in the FALLBACK section, but my current version seems to work fine, so I suspect that it needs a minor edit. Storing Data on the Client (Apple) Configuring Web Applications (Apple covers Apple-specific meta tags, icons, splash screens, & more.) Building an Offline Mobile Web Application Configuring the Viewport (Apple important information on controlling the viewport) Application Cache is a Douchebag a colorful rant about some of the limitations of app caching. DOMApplicationCache Class Reference (Apple)

MORE INFORMATION

>

>

appliness

DONT WORRY, BE APPLI

Working with svg maps

I am the author of the charting and mapping tools, amCharts.com and amMap.com. I am currently working on an SVG version of amMap - an interactive mapping tool I made with flash some years ago. Until this product is released, you can follow this tutorial and do a lot of things yourself.

In this article I will try to explain how you can quickly create an interactive and zoomable map from a simple SVG map downloaded from Wikipedia (or anywhere else). I dont use any 3rd party libraries in this tutorial and will try to keep it very simple, so even if you are not JavaScript guru, it will be easy to follow.

Part I, Modifying SVG map


To start, lets save this SVG map of Europe: http://en.wikipedia.org/wiki/File:Blank_map_europe.svg

d n u o laygr

Difficulty
- rookie - intermediate - expert

- maps - vectors - SVG

Todo list

- zoom in

- draw regions - fill color

by Antanas Marcelionis

Below is the map without any modifications.

If you view the source of this SVG file with a text editor, you will see that its XML which you can modify: 1 <?xml version=1.0 encoding=UTF-8 standalone=no?> 2 <svg 3 xmlns:dc=http://purl.org/dc/elements/1.1/ 4 xmlns:cc=http://creativecommons.org/ns# 5 xmlns:rdf=http://www.w3.org/1999/02/22-rdf-syntax-ns# 6 xmlns:svg=http://www.w3.org/2000/svg 7 xmlns=http://www.w3.org/2000/svg 8 xmlns:sodipodi=http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd 9 xmlns:inkscape=http://www.inkscape.org/namespaces/inkscape 10 xml:space=preserve 11 width=680 12 height=520 13 viewBox=1754 161 9938 7945 14 version=1.0 15 id=svg2 16 sodipodi:version=0.32 17 inkscape:version=0.46 18 sodipodi:docname=Blank_map_europe2.svg 19 sodipodi:docbase=C:\Documents and Settings\Botek\Desktop 20 inkscape:output_extension=org.inkscape.output.svg.inkscape><metadata 21 id=metadata78><rdf:RDF><cc:Work 22 rdf:about=><dc:format>image/svg+xml</dc:format><dc:type 23 rdf:resource=http://purl.org/dc/dcmitype/StillImage /></ cc:Work></rdf:RDF></metadata><sodipodi:namedview 24 inkscape:window-height=691 25 inkscape:window-width=1014 26 inkscape:pageshadow=2 ...

60/68

So lets try it - lets make Lithuania (because I live there :)) green. Without looking into the structure of the document, I searched for Lithuania keyword first, but didnt find anything. So I searched for lt (iso country code of Lithuania), including quotes (otherwise I would find a lot of matches), and bingo - found the match on line 364: 362 style=fill: rgb(192, 192, 192); stroke: rgb(255, 255, 255); strokewidth: 8; fill-opacity: 1; 363 transform=translate(0.0005875, 7.53846e-05) /><path 364 id=lt 365 class=eu europe 366 d=M 7581.781,4394.3979 C 7584.6474,4391.5317 7584.6474,4385.799 I assumed that the XML node starting with <path whose attribute is my match (id=lt) referenced Lithuanias area on the map. I checked other attributes of path and found this one: style=fill: rgb(192, 192, 192); stroke: rgb(255, 255, 255); stroke-width: 8; fill-opacity: 1; And changed it to: style=fill: #00DD00; stroke: rgb(255, 255, 255); stroke-width: 8; fill-opacity: 1; (I like HEX color codes more, and guessed that SVG should understand it too). I then saved the file and opened it in browser:

As you see, you can easily modify SVG yourself. Sometimes coloring countries in different colors is all you need. In next part well dynamically change colors.

61/68

Part II. Changing SVG map with JavaScript


First, lets include our SVG map into a basic HTML page. Add the SVG element to the page using <object> tag. I get the contentDocument of this object so I can access SVG document later. Note, I do this only after SVG is loaded: <?xml version=1.0 encoding=UTF-8?> <!DOCTYPE html> <html xmlns=http://www.w3.org/1999/xhtml> <head> <title>SVG map tutorial</title> <script type=text/javascript> var svgDoc; function colorizeCountries() { svgDoc = document.getElementById(map).contentDocument; } </script> </head> <body> <object data=europe.svg onload=colorizeCountries() id=map type=image/svg+xml></object> </body> </html> Lets try to color another country with JavaScript. Since SVG elements represent countries using ISO country codes for the id, lets get the IDs and change the fill style: { function colorizeCountries() svgDoc = document.getElementById(map).contentDocument; var lithuania = svgDoc.getElementById(lt); lithuania.style.fill = #00CC00; var latvia = svgDoc.getElementById(lv); latvia.style.fill = #CC0000; var estonia = svgDoc.getElementById(ee); estonia.style.fill = #0000CC;

62/68

And here is the result:

Handling the click event


Lets say I want the map to zoom in when one of the colored countries is clicked. To do this, I add click event listeners to each of the countries and create methods to handle these events: function colorizeCountries() { svgDoc = document.getElementById(map).contentDocument; var lithuania = svgDoc.getElementById(lt); lithuania.addEventListener(click, lithuaniaClicked, false) lithuania.style.fill = #00CC00; var latvia = svgDoc.getElementById(lv); latvia.addEventListener(click, latviaClicked, false) latvia.style.fill = #CC0000; var estonia = svgDoc.getElementById(ee); estonia.addEventListener(click, estoniaClicked, false) estonia.style.fill = #0000CC;

63/68

} function lithuaniaClicked() { } function latviaClicked() { } function estoniaClicked() { }

Zooming the map


There are two ways to zoom in the SVG. One is using the viewBox attribute of SVG element, another would be to apply scale and translate transformations to the group of all the paths and other shapes in your SVG. We will use the first method. This may be the most difficult part in this tutorial, but its quite simple geometry, so dont be afraid. First, locate viewBox attribute in the svg: viewBox=7088 3766 950 917 The value settings for viewbox include: minxthe beginning x coordinate minythe beginning y coordinate widthwidth of the view box heightheight of the view box Just above viewBox attribute are the width=680 and height=520 attributes - well need these numbers too. You can modify them to change the size of your map, by the way. As you can see, the values of viewBox dont look like pixels, right? Actually we dont care too much about what they mean. All we want to do is to zoom in the map so that the clicked country is big. I grabbed a screenshot of the HTML page with the map and pasted it to Photoshop. Then, I marked the area to be enlarged (for better results, keep width and height proportional to width and height of your map window). Next, I checked the x coordinate (in pixels) of left and right borders and the y coordinate of the top and bottom borders. You can easily do this by selecting area from top/left corner - the size of selection will be displayed in the info panel.

64/68

OK, so now I have pixels but I obviously need something else, as these numbers dont look like the ones from viewBox attribute. My guess is that I need to calculate ratio of original viewBox width and width of the map, same with the height and then use ratio to convert my pixels to new viewBox values. Lets create a method called getViewBox: function getViewBox(x1, y1, x2, y2) { // viewBox data (from SVG file) var svgMinX = 1754; var svgMinY = 161; var svgWidth = 9938; var svgHeight = 7945; // actual size (from SVG, but can also be set in HTML) var width = 680; var height = 520; // width and height ratio var wRatio = svgWidth / width; var hRatio = svgHeight / height; // desired width in pixels var desiredWidth = x2 - x1; // desired height in pixels var desiredHeight = y2 - y1; // new viewBox values var newWidth = Math.round(desiredWidth * wRatio); var newHeight = Math.round(desiredHeight * hRatio); // initial minX and minY must be added var newMinX = svgMinX + Math.round(x1 * wRatio); var newMinY = svgMinY + Math.round(y1 * hRatio); wHeight; return newMinX + + newMinY + + newWidth + + ne}

To be sure its correct I simply called this method with values I measured using Photoshop: getViewBox(365, 236, 430, 296); and entered the values Ive got directly in my SVG file: viewBox=7088 3767 950 917

65/68

And the map now looks like this:

Lets make the same map using JavaScript (do not forget to bring old values back before proceeding). function lithuaniaClicked() { var viewBox = getViewBox(365, 236, 430, 296); svgDoc.getElementById(svg2).setAttribute(viewBox, view}

Box);

svgDoc.getElementById(svg2) gets the first node of the SVG document and sets new viewBox value (svg2 is the id of this first node in this example, so it might be different in your code). I did the same for other two countries with slightly different values and here is final code: <?xml version=1.0 encoding=UTF-8?> <!DOCTYPE html> <html xmlns=http://www.w3.org/1999/xhtml> <head> <title>SVG map tutorial</title> <script type=text/javascript> var svgDoc; function colorizeCountries() { svgDoc = document.getElementById(map).contentDocument; var lithuania = svgDoc.getElementById(lt); lithuania.addEventListener(click, lithuaniaClicked, false) lithuania.style.fill = #00CC00;
66/68

var latvia = svgDoc.getElementById(lv);

latvia.addEventListener(click, latviaClicked, false) latvia.style.fill = #CC0000; var estonia = svgDoc.getElementById(ee); estonia.addEventListener(click, estoniaClicked, false) estonia.style.fill = #0000CC;

Box);

function lithuaniaClicked() { var viewBox = getViewBox(365, 236, 430, 296); svgDoc.getElementById(svg2).setAttribute(viewBox, view} function latviaClicked() { var viewBox = getViewBox(366, 213, 445, 273); svgDoc.getElementById(svg2).setAttribute(viewBox, view} function estoniaClicked() { var viewBox = getViewBox(368, 191, 447, 250); svgDoc.getElementById(svg2).setAttribute(viewBox, view} function getViewBox(x1, y1, x2, y2) { // viewBox data (from SVG file) var svgMinX = 1754; var svgMinY = 161; var svgWidth = 9938; var svgHeight = 7945; // actual size (from SVG, but can also be set in HTML) var width = 680; var height = 520; // width and height ratio var wRatio = svgWidth / width; var hRatio = svgHeight / height; // desired width in pixels var desiredWidth = x2 - x1; // desired height in pixels var desiredHeight = y2 - y1; // new viewBox values var newWidth = Math.round(desiredWidth * wRatio); var newHeight = Math.round(desiredHeight * hRatio);

Box);

Box);

67/68

// initial minX and minY must be added var newMinX = svgMinX + Math.round(x1 * wRatio); var newMinY = svgMinY + Math.round(y1 * hRatio); wHeight; return newMinX + + newMinY + + newWidth + + ne}

</script> </head> <body> <object data=europe.svg onload=colorizeCountries() id=map type=image/svg+xml></object> </body> </html> Open the page and click on one of the three countries - the map should zoom in. Now try to extend this example and do the zoom with animation :) And this is it for this tutorial. I hope you enjoyed it and you will get some use from it.

MORE INFORMATION

>

ABOUT THIS ARTICLE


Antanas Marcelionis failed as a blogger and has decided he likes coding more. His company, amCharts, based in Vilnius, Lithuania had its beginnings in 2004 when Antanas created the first version of amMap. In 2006, Antanas left his job as a manager at a web development company & the rest is history. http://www.amcharts.com/ @marcelionis

ONLINE RESOURCES amCharts official website http://www.amcharts.com/ amCharts blog http://blog.amcharts.com/ SVG official website http://www.w3.org/Graphics/SVG/

>

appliness

DONT WORRY, BE APPLI

CSS3 animation property

The standard language for control the layout and graphic styles in this new version comes with a new powerful control over animations. Now in html5 we can include animations or transitions over properties and transformations with techniques like web keyframes and transitions

animations
There will be certain cases where you need to publish a web animation, sure you know Flash is an easy tool for create and deliver interactive content over the web. In the new mobile revolution, the content must be written in standard way. Tools like Flash are not the best choice for simple animations. With new plugins or third part tools, you can export a complex animation created in Flash, and publish in HTML5 with a canvas element container. But what can you do for a simple menu button? what about my share button or a simple logo moved around the header zone? the answer to that is CSS3 animation property. The CSS3 animation property - a different approach from css transitions - can make a great impact with just a few lines of code . The standard for animations being in W3Cs working Draft: - http://www.w3.org/2005/10/Process-20051014/tr#RecsWD - http:// www.w3.org/Style/CSS/current-work but we can start using it safety, in modern web browsers and mobile devices.

d n u o laygr
- CSS - W3C - animation

Difficulty
- rookie - intermediate - expert

Todo list

- move objects - goToAndPlay - call Disney

by Francisco Granados

In this article we introduce you to the world of web animation with CSS3 and their new concepts about keyframes. Well see how can define keyframes and their potential with others new effects part of CSS3.

keyframes, a different concept


Flash or After Effects animators, understand the concept for keyframes, but in web this concept its a little different. While in Flash you do a movement animation with symbols or transitions for a vector shape, in web the keyframes are points for a certain animation. Now the animations should have a name to refer in other places (in javascript or css), also we need define a block of @keyframes and inside of them different points of animations.

Syntax
The new elements we need for doing an animation in CSS3 are: // animation name // animation points // properties to change in each point // configuration and call for animation To start with the animation lets we write our block of @keyframes with a name /** example for syntax */ @keyframes name{ ... } Each time we need to start an animation we can look for its name, defined in the first line. Its important to notice we should name it without spaces.

time matters
Points of an animation are properly the keyframes. Each keyframe is a relative part of the whole animation. In this implementation of animations with keyframes we have the capacity to assign a variable time of reproduction each time we start the animation. We can set an animation for 4 seconds or 20 seconds and then play it. For example, if we have an animation of 4 seconds or 30 seconds the points of the animation are divided in relative parts expressed as percentages.

delay

from 0% 50%

to 100%

We move an element <div id=box></div> in vertical until 100px and come back. We can change the properties of style as we need in each block of the keyframes. In this example see how the property top is changed 3 times, from start the animation until the finish.
70/74

/** example for animation */ @keyframes my_animation { 0% { top: 0px; } 50% { top: 100px; } 100% { top: 0px; } } In the W3Cs working draft, we can use an alias for 0% & 100% /** example for animation with aliases */ @keyframes my_animation { /** works like 0%*/ from { top: 0px; } 50% { top: 100px; } /** works like 100%*/ to { top: 0px; } }

play the animation


Since we have now the design of our animation, the only thing we lack is the start moment. We will see how can start the animation in CSS through the property animation. #box { /** assign name */ animation-name: my_animation; /** duration in seconds*/ animation-duration: 5s; } Other properties than may be assigned would be: // timing function (ease | linear | ease-in | ease-out | ease-in-out ) / / number for repeat // direction (normal | reverse | alternate | alternate-reverse)
71/74

// delay (in seconds)

#box { animation-name: my_animation; animation-duration: 5s; animation-timing-function: ease-in; animation-iteration-count: 2; animation-direction: normal; animation-delay: 1s; } We just need to set this and the animation would start. Also, we can assign a class or a pseudo class like :hover #box:hover { animation-name: my_animation; animation-duration: 5s; animation-timing-function: ease-in; animation-iteration-count: 2; animation-direction: normal; animation-delay: 1s; }

the standard way...


This specification are in working draft, that means is not standard yet. But we can use it through the specific vendors properties. This feature is currently implemented in render engines like Mozilla Gecko and Webkit. We can have access to them with the prefix for each platform and also add the standard property for future support. I recommend the shorthand annotation. #box{ /** animation: name duration timing_function delay loops direction */ -webkit-animation: my_animation 5s linear 2s 4 reverse; -moz-animation: my_animation 5s linear 2s 4 reverse; animation: my_animation 5s linear 2s 4 reverse; } /** the prefix for webkit */ @-webkit-keyframes my_animation { from { top: 0px; } 50% { top: 100px; } to { top: 0px; } } /** the prefix for mozilla */ @-moz-keyframes my_animation {

72/74

from { top: 0px; } 50% { top: 100px; } to { top: 0px; } } /** the standard way */ @keyframes my_animation { from { top: 0px; } 50% { top: 100px; } to { top: 0px; } }

publish moment
CSS3 animations will establish a new way for doing movements and simple sequences, at this moment the W3C is completely aware for our needs in the web development. With features like this we can improve the experience of our visits and make the content better. Nowadays the web browsers which implements this way to do animations are: Chrome, Safari and Firefox and in mobile scene the Android Chrome and Safari mobile. Its very important to not put css animations in core functionality because the experience in our sites could be affected. If needed, I recommend Modernizr (http://modernizr.com/) for evaluate the browser support of this feature. /** in javascript */ if(Modernizr.cssanimations){ // have animations }else{ // do not, oh no... } A simple example I made for, is in the magazine source code bundle, I recommend to view the source code and take a look how I take just one definition for keyframes and set in several elements in HTML setting different durations or delays for each one.

73/74

go beyond
This are the basics for CSS3 animation properties an their use. I recommend this post to go deeper about this topic. // Taking Advantage of HTML5 and CSS3 with Modernizr // W3C Working draft // Keyframes and transforms I also recommend to learn about animations API in Javascript to control the play, stop or pause the animation, so you can start an animation with a behavior after a call in AJAX or after an event for jQuery or another one. I hope you enjoy this post and your next projects include this powerful feature of CSS3 web keyframes with web standards.

RUNNING SAMPLE and source code

SAMPLE

HTML CODE

ABOUT THIS ARTICLE


Francisco Granados is a mexican developer in javascript, as3, ruby and groovy. CoManager of RIActive Adobe user group in Mexico city. Instructor and CIO in Activ. Profesional diver and mountain bike enthusiast. Currently working in game development for web and mobile platforms. http://riactive.com/ @GzFrancisco

ONLINE RESOURCES W3C working draft http://www.w3.org/TR/css3-animations/ Keyframes and transform http://www.impressivewebs.com/mixing-css3-keyframe-animations/ Modernizr http://modernizr.com/

appliness

DONT WORRY, BE APPLI

Data Visualization With Web Standards

andrew explains how to use html, css and javascript to deliver first class data viz components to your users

Almost every enterprise application requires some form of data visualization. Whether it is a business dashboard, sales chart, performance comparison, or hierarchy viewer, there is always data, and there always needs to be an easy way to consume that data. Using web standards technologies (HTML, CSS, & JavaScript) there are 5 general techniques for visualizing data here is a brief overview:

<img>
You can embed images using the html <img> that have server-rendered data visualizations. This is nothing new They are very basic, but will certainly work.

Not interactive Requires online & round-trip to server No WOW factor lets face it, they are boring Example: Google Image Charts

d n u o laygr
- SVG - WebGL - Canvas

Difficulty
- rookie - intermediate - expert

Todo list

- build map

- draw lines - fill color

by Andrew Trice

HTML5 <canvas>
You can use the HTML5 <canvas> element to programmatically render content based upon data inmemory using JavaScript. The HTML5 Canvas provides you with an API for rendering graphical content via moveTo or lineTo instructions, or by setting individual pixel values manually. Learn more about the HTML5 canvas from the MDN tutorials.

Can be interactive Dynamic client side rendering with JavaScript Hardware accelerated on some platforms Can work offline Works in newer browsers: http://caniuse.com/#search=canvas Rgraph Open source charting library using HTML5 <canvas> One Million Points Scatter Plot Let the page load, then use the mouse to click and drag regions to drill into. This is a live visualization that shows a scatter plot with a histogram for massive data sets by manipulating individual pixels. This sample is rendering 50.000 points !

Simple Bar Chart in the canvas: And the source code:

76/78

<script> var data = [ 1,2,4,6,7,4,2,3,6,7,8,9,3,2,7,4,1,2,1,1,2 ]; function draw() { var canvas = document.getElementById( myCanvas ); var context = canvas.getContext( 2d ); //draw background grid; context.strokeStyle = #DDDDDD; context.lineWidth = 1; var xIncrement = canvas.width / data.length; var yIncrement = canvas.height / 10;

var padding = 2; context.strokeRect( 0,0, canvas.width, canvas.height ); for ( var yPosition = 0; yPosition < canvas.height; yPosition += yIncrement ) { context.moveTo( 0, yPosition ); context.lineTo( canvas.width, yPosition ); } context.stroke(); //now we can draw the data context.strokeStyle = #000000; context.lineWidth = 1; context.fillStyle = rgba(0,0,255,0.25); for ( var i = 0; i < data.length; i++ ) { var xPosition = (xIncrement * i) + padding; var dataHeight = canvas.height * (data[i]/10); var yPosition = canvas.height - (dataHeight-1); context.fillRect( xPosition, yPosition, xIncrement-2*padding, dataHeight ); context.strokeRect( xPosition, yPosition, xIncrement-2*padding, dataHeight ); } } </script>

Vector Graphics (SVG)


Vector graphics can be used to create visual content in web experiences. Client or Server-side rendering Can be static or dynamic Can be scripted with JS Can be manipulated via HTML DOM Works in newer browsers (but not on Android 2.x and earlier): http://caniuse.com/#search=SVG Demos: US Census Browser multi-platform PhoneGap application showing enterprise-class data visualization using web standards techniques. D3.js data visualization framework Raphael.js data visualization framework HighCharts data visualization libarary Sencha Touch Charts Kendo UI DataViz
77/78

HTML DOM Elements


Visualizations like simple bar or column charts can be created purely with HTML structures and creative use of CSS styles to control position, visual presentation, etc You can use CSS positioning to control x/y placement, and percentagebased width/height to display relative values based upon a range of data. For example, the following bar chart/table is created purely using HTML DIV containers with CSS styles. You can also see a very basic example of this technique:

Running sample: http://tricedesigns.com/portfolio/dataviz/HTML%20DOM%20Chart.html

WebGL
WebGL is on the bleeding edge of interactive graphics & data visualization across the web. WebGL enables hardware-accelerated 3D graphics inside the browser experience. Technically, it is not a standard, and there is varied and/or incomplete support across different browsers (http://caniuse.com/#search=webgl). There is also considerable debate whether it ever will be a standard; however there are some incredible samples out on the web worth mentioning: WebGL Globe Global Temperature Anomalies Realtime Color Histogram

ABOUT THIS ARTICLE


Andy Trice is a Technical Evangelist for Adobe Systems. Andrew brings to the table more than a decade of experience designing, implementing, and delivering RIA for the web, desktop, and mobile devices. http://tricedesigns.com/ @andytrice

ONLINE RESOURCES Blog post about data viz http://www.tricedesigns.com/2012/05/02/data-visualization-withweb-standards/ Andys Census app http://tricedesigns.com/census Andys blog http://www.tricedesigns.com

appliness

DONT WORRY, BE APPLI

Adobe Shadow

Adobe Shadow is a great new tool from Adobe that allows developers to design and develop their mobile web content quickly by providing a way to inspect and debug from their desktops wirelessly and synchronously across multiple devices.

about shadow
Shadow essentially allows a developer to browse web content on their desktops and see that same content displayed at the same time on multiple devices. At which point, the layout can be tweaked on-the-fly so results can be seen immediately. If you are a developer doing mobile development with HTML/JS or PhoneGap, you should definitely check it out. If you are wondering how it works, the Adobe Shadow desktop application listens for changes in a URL location in the browser, and when a change occurs, it pushes the new URL out to all wirelessly connected devices immediately so the changed content is seen on the devices immediately. Adobe Shadow consists of the following components and takes just a couple of minutes to get set up and running: Adobe Shadow Desktop Application Adobe Shadow Google Chrome plugin Adobe Shadow Mobile Clients (for iOS/Android devices) Take a look at this short video showing how it works followed by an explanation of the setup and how to use it.

d n u o laygr

- WEINRE - Debug e - Responsiv

Difficulty
- rookie - intermediate - expert

Todo list

- sync - debug css - Xplatform

by Holly Schinsky

Setup
Desktop 1. Install the Adobe Shadow desktop application from Adobe Labs. 2. Ensure you have the Google Chrome Browser installed (its free). 3. Open the Google Chrome browser and add the Adobe Shadow Google Chrome Extension from the Google Chrome Store. Mobile Devices Go to the AppStore on your iOS devices or Google Play (Android Market) on your Android devices and download the Adobe Shadow mobile device client apps Refer to Adobe Labs for further information on setup. IMPORTANT NOTE: Adobe Shadow runs wirelessly so you must ensure that all devices and computers have access to the Internet and run on the same network.

Mobile Inspection
Start-up the Adobe Shadow Desktop application. You should see the following upon execution:

80/86

Next, open the website or app to be inspected. In this case Ill use Google to keep things simple, but you could open any web content that you are currently working on.

Click on the blue Adobe Shadow icon in the top right corner of the Google Chrome browser toolbar. You will see a drop-down black box displayed that looks like the following:

81/86

If you forget to start your desktop Shadow application, you will get a reminder at this point that looks like the following, and the Shadow icon in the toolbar will be grey (rather than blue):

Now go to your devices and click on the Settings icon in the top left corner. You should now see any computer connections currently running Shadow. In my case I have my MacBook-AIR connection started and waiting, so I click on that to establish the connection back to the latop. I will be notified on my device when the connection is established, such as in the following, as well as any previous connections you may have made to other computers, as shown below:

82/86

Once the connection is established, you can go back into your Google Chrome Shadow icon on your desktop and see all the devices that have made a connection, such as in the following:

Next, you can either change the URL location on your desktops Chrome browser to see the synchronous browsing occur on your devices (or trigger the URL change with clicks within your app), or you can start doing remote inspection on a specific device and make other changes to your application (e.g., update CSS, etc.) to see the immediate effects. To start remote inspection on your device, click the double arrows on the black box next to the device you want to inspect:

83/86

You will be presented with a weinre screen. Adobe Shadow includes the open source weinre project as its core engine for remote inspection. (See below for more information about weinre).

From here, you can click on HTML elements and actually modify the CSS inline and see the results on the device immediately. For instance, in the next few screenshots you can see how I updated the background color of the main element on the Google web page on the fly and viewed the results directly on the iPad: This is Google before being viewed in an iPad Adobe Shadow application.

84/86

You can edit CSS directly on the desktop in Google Chrome:

Here is the result of the edit on the iPad:

85/86

You can also view things like storage resources, network activity and console messages from device interaction. For instance, below is the Resources tab for Google:

Here are some other things to note when using Adobe Shadow: Shadow will continue trying to reconnect on the device while open, and keep the device from sleeping, so you need to specifically shut it down when you are not using it or it will run your battery down more quickly due to the reconnection attempts. weinre Adobe Shadow is based on Weinre (Web Inspector Remote), which is technology that allows you to debug between devices. Weinre is composed of 3 programs or web pages running simultaneously: 1. target - the web page being debugged 2. client - the Web Inspector code running as a web page 3. agent - an HTTP server which allows the target and client to communicate. For more in-depth information of how this technology works, I highly recommend checking out this page by Patrick Mueller.

Resources
Here are some links to check out: Adobe Shadow FAQ Adobe Shadow video by Sr Product Manager Bruce Bowman

MORE INFORMATION

>

>

CHRISTIAN HEILMANN
PRINCIPAL EVANGELIST FOR MOZILLA

The mission of a web browser is to allow users to take part in the web.
87/100

E E IV W S E U I V L R C X TE IN

FOR THE GOOD OF THE WEB

WE ARE VERY HAPPY TO INTERVIEw christian whos one of the most active evangelists on the web. his mission is to promote standards, the open web and innovation at mozilla. he received us at the new mozilla space in london.

Hi Chris, were very happy and excited to interview you. Can you introduce yourself to our readers?
I am Chris Heilmann, @codepo8 on Twitter and I am the principal evangelist for Mozilla with focus on the Open Web and HTML5. My business card says online mythbuster which describes it a bit better. My job is to cut through sales talk and unearth the things people can use now to make the web better. Ive been working as a web developer for over 16 years and I use my experience to make sure we dont repeat mistakes of the past.

Mozilla is so unique. Can you explain to us the mission of Mozilla and whos behind it?
Mozilla is the only independent, non-profit organisation advocating for and creating an interoperable, standards-based Web that creates opportunity for all, regardless of how or where they access the Web. Thats the tagline. It means mostly that from day one of our inception Mozilla made sure that people are at the centre of innovation. We gave people a choice with Firefox. Without Mozilla and Firefox (and the history is well-documented on our Wiki) wed have been locked into Windows and Internet Explorer and I am certain the web would not be what it is now. Seeing how Microsoft was back then I am sure the web would still be a corporate thing and very expensive. And lots of grey boxes. We showed in 2003 that innovation on the web can be done by and for people by being open source and open in our documentation and communication. There are no secrets, there are no stakeholder meetings and the hierarchy in Mozilla is defined by how much you are responsible for. The larger part of our code is not written inside the organisation but by volunteers working with us. We localise Firefox to over 90 languages using volunteers. The trick is simple - we give and respect people who participate and we get back that way. It would be impossible to pay the time and effort put into our products. We pay our volunteers in partnering with them, supporting education and documentation and giving access to a vast amount of knowledge stored in the heads of our community.

88/100

I came from a large corporation when I started here and I found an incredible amount of passion, people working because they want to and an avalanche of innovative ideas and discussions. Where I had to ask for information in the past and got hindered by red tape in a lot of cases, I learned triaging information in Mozilla. It is quite a ride, but you are allowed to be yourself and speak your mind here much more than anywhere I have been before.

Youve had a pretty eclectic career path including working with people with disabilities for the Red Cross and as a radio producer. How did you get interested in web development?
Working at a radio station I was frustrated that I wasnt able to report on a lot of interesting issues when they didnt fit the financial goals of the station. I found it annoying that interesting and intelligent people werent allowed to be on the air. Obviously boring people reading soundbites from a sheet of paper their PR team had written for them were as they paid for the right to publish. Thats not right and not the job of the media. Having worked with a day group of people with learning disabilities in the Red Cross (instead of my national army service) I knew that everybody has an interesting story to tell. It is wonderful to see when people start being able to speak for themselves and gain independence and self-assurance from that. I always dabbled with computers since I was a kid (writing things on Commodore 64, later on creating games). When I realised that there is a new media emerging that has an incredibly low barrier to entry that allows anyone to publish world-wide, I was immediately sold. I built my own web site, quit my job and went on to become a web developer. As this was the right time and I was one of a very few people in my area doing that I got some contracts to build company web sites and got head-hunted to work on the intranet of BMW in 1997 or so. The rest is history.

In addition to evangelizing, youre a web developer and still coding a lot. What is a web developer in 2012? What has changed in the last few years?
The web is moving, both from being structured documents that link to each other towards apps and from desktops to mobiles and tablets. The internet connected fridge is almost clich by now but I can see it being a normal sight before long - except our phones will know what is in our fridge and not a computer built into it. This brings quite a few new challenges. As web developers we were always pitied by real developers who build in C++ and build huge systems in Java. Now we are not pitied any longer but these developers also want a slice of the pie that is web apps. As a web developer now you need to know your web standards and how to build sites but you should also be knowledgable about using APIs, talking to servers and architecting solutions. The web is under attack by native apps on mobile platforms. In order to keep it the biggest distribution platform and the main channel to reach millions of people we need to step up and stand our ground in an app world. We should build web apps, native to the web and wonderfully connected to battle the silo-ed world of native apps instead of trying to simulate their look and feel on the web.

89/100

The web has rapidly extended its scope to new playgrounds: server-side, mobile web apps, gaming, hybrid apps Do you feel that web developers should embrace everything, or focus on specific areas?
You should have an understanding of everything and partner with the right people who have a passion for the other pieces of the puzzle but it is very much fine to be an expert in a specific area. We move away from building everything by hand and from scratch to using frameworks, libraries and building blocks. This is hard to swallow for a lot of people but there is no glory in reinventing the wheel over and over again. Whilst the web world smugly points out that it is OK to omit semicolons in JavaScript native apps get rolled out in dozens on a weekly basis. We need to be more nimble and build on what works rather than being in our ivory tower of web developer awesomeness. I dont think being a jack of all trades works out, you should have one pet subject that you cherish and know by heart. But you should also be ready to not use that technology when another is easier to understand for everybody involved.

These days, a new JS library is launched every 6 seconds. It features the excitement around web technologies, but at the same time, developers can feel a little bit lost among all of the possibilities. In your opinion, what should be the top priorities of a web developer?
Get the job done, using reliable tools and leave code behind that is understandable and nimble. Ive spoken quite a lot about how sick I am of quick, small and clever solutions that fall by the wayside a few months down the line and grow into the bloated monsters they originally replaced. As a good web developer you write for the next person to inherit your code. Not for machines. Optimisation can be done with build and conversion scripts, it should not be the start of your work when it results in hard to grasp code.

What excites you the most when you start developing a web application?
The end goal - what do people get out of this app? How does it change their life? If the app doesnt do anything for the user, I have a hard time caring about it. We should write software to make the life of people easier. This can be frivolous things like blowing up pigs by flinging birds at them - it does not have to though. The same addictive and playful interaction could be used to learn things or to organise your life. Apps are different to web sites. With apps you should start thinking about the use case and the environment. The more natural it seems to use your app, the better. I am very excited that we can use touch, device orientation and soon cameras in our web apps. This allows us to create things that are more human to use than things you click with a mouse.

What is your development process and whats the role of design in this process?
There are quite a few different things in here: design as in visual design, design as in interaction design and designing your code solutions before you start writing them. All are equally important. I am not a designer, so I tend to partner with those who are. You can not create an amazing product if you are not engaged in the task. I found the best solutions are found when developers and UX people work together and brainstorm the heck out of an idea before we start developing it. There is a wonderful dynamic in that. The time of making mockups and designs in Photoshop and chucking them over the wall for the developer to implement is over - and good riddance.

90/100

What will it take to turn the possibilities of responsive and scalable mobile applications into a reality with web technologies?
Full access to the hardware from the browser. Right now web apps are treated by mobile platforms and hardware as second class citizens - simulated apps if you will. This is not fair and is very wrong and mostly based on mobile platforms making more money with native apps. The building blocks are there - local storage, offline storage, Drag and Drop, Canvas and WebGL for gaming, native video and audio are supported and WebRTC, Filereader, Web intents, Webcomponents and other innovations are in the making and incredibly exciting. Where it falls down is support from the native browsers on mobile platforms. A lot is incredibly broken which is especially annoying on platforms where the browser is not open source and things are not created in public. Open source doesnt mean releasing a product and making the code available two weeks later. It means building it in the open and taking on advice from those who use your products whilst building the next iteration. A big misconception is also that apps built with web technologies should feel the same and have the same functionality as native apps. To me this actually makes them less interesting. You can never get the same fidelity in a web app that you can get in a native app as you are not that close to the metal and the engine. You can however build a much smaller, easier to update and more connected app as you are not locked into the incredibly outdated world of fullsize downloads, installs and uninstalls. If anything, I think native apps should learn from the web - not the other way around.

Can you tell us some cases where this is happening already?


There are a few great examples out there. The Financial Times canned their iOS app after seeing the success of their HTML5 app and even realised they make more money with it. Mozillas Boot to Gecko project shows that when you build from the very start in the

I am a good dino. You can follow me: @mozilla

91/100

open you can create a web enabled smart phone for the price of a feature phone in a year from scratch. Boot to Gecko allows a JavaScript developer to get to make calls, send text messages, take photos and access the photo data, read the battery status and the network state. This is what we should have had from the very start on HTML5 enabled phones but we didnt. Now we have a stake in the ground and I want a lot more barriers to be broken down.

Do you feel that web standards are evolving faster and in the right direction to answer todays users needs?
They are certainly moving faster and much more in the open than they did in the past. When HTML5 started this was the breath of fresh air we needed. Nowadays they do still move fast but there is a weird undercurrent of things getting in faster when they benefit a platform rather than developers. A great example right now is the responsive image proposal using srcset. The developer community had a different proposal but this one got into the WHATWG specs. I can see quite some discontent or disillusion coming our way if we dont start demanding more discussion from the WHATWG in these matters. In terms of what the users need, yes, we do great work. The issue is that we lose a lot of users to native apps. I can see this turning around soon though. Native apps are getting bigger and sluggish and people are getting sick of having to upgrade to a new phone just to play a game.

How does Mozilla contribute to web standards? Can you detail its role in the process?
We propose a lot of new standards and have people in all the working groups of the W3C. We sponsor research into standards and implementations and with a browser that ships every 6 weeks and Nightly builds and Aurora preview builds we have a great platform to show that the proposals can work. A lot of the standards that made it in and get promoted a lot by other players were actually defined by Mozilla. Great examples of that are the requestAnimationFrame API or the fullscreen API.

92/100

How could developers get involved in the evolution of the web with Mozilla?
Test out beta browsers, Nightly builds, give feedback and take part in the discussions in the WHATWG and on the W3C mailing lists. Mozilla is you, there is no big barrier to entry. If you read the Mozilla Developer Network documentation and you find something that needs fixing, hit the edit button and fix it. If you have a great example that shows how to use the API we talk about hit edit and attach the example. Everything in Mozilla is open - even our conference calls and meeting notes. If you have something useful to contribute, your voice is as important as the one of the person paid by Mozilla. You can sign up at Mozillians.org to get direct access to a lot more people and if you work a lot with us even sponsorship to attend events for Mozilla. Above all - use what we publish. A lot of broken mobile web promises happen right now because developers follow documentation and examples that are build to target one browser and not the standards or all of them. This has to stop. The CSS that only works in webkit right now and renders an unreadable button on other browsers is no better than the best viewed in IE6 of the past. Another big wish of mine is to stay up-to-date before you complain. Almost daily I get people spouting truisms on Twitter that Firefox is slow or doesnt do things other browsers do just to find out that the complaint is based on a one year old article and applies to a Firefox that is 6 numbers behind the currently official one. It is easy to try something before calling it broken - lets do that more.

Are there special specifications youd like to promote or that youd like to see in all browsers as soon as possible?
The Web API spec (Battery status, Camera access, IndexDB, Vibration, Sending SMS) and the Web Runtime (installing HTML5 apps as full-screen, chromeless apps) is things we really, really need. There is no point in trying to build a mobile web app if you can not access the hardware. For example I can read the orientation of an Android device in all three axes as radians in Firefox, it doesnt work with the current Android browser. That is not right. Another thing Firefox does is animating and transition content generated in CSS with ::after and ::before. Other browsers dont do that and it allows you to do so many great visual things without soiling your markup. WebRTC and getUserMedia is something we need, too. I am sick of buggy video chat clients using plugins.

What is your feeling about JavaScript? Do you think that the language should evolve into a more advanced one, closer to Java for instance?
I like JavaScript as it is simple to learn but hard to master. I am getting excited by the things I can build with JavaScript. Hypothetical discussions on where the language should go are not high on my list of must haves. There are things that are very, very broken in JS - especially the security model - but I dont see it as a good use of my time to try to change a language that is probably the most used one on the web. I leave that to the experts that get very excited about that kind of research. Ive seen a lot of people trying to shoe-horn best practices of other languages into JS come and go whilst I happily used what is supported. I think, with the move of JS to the server side, we have to come up with new rules and extensions. Bring them on. Then we try them out and see just how much more we get.

93/100

Whats the mission of a web browser? Whats the positioning of Firefox within that mission?
The mission of a web browser is to allow users to take part in the web. This means that they should get the best experience of the web without being locked in to a certain environment or having to sign up. It also means that their privacy and security should be the most important asset to protect. The ability to surf the web in a quick, secure and safe way should not come at the cost of giving up your identity or all your movements being monitored and sold to advertisers. Firefox very much is a browser that follows these principles. The Do Not Track feature invented by Mozilla allows you to say that you dont want to be tracked when you surf the web. Moreover, Firefox is available across your devices - there is no need to have an Android profile and a Desktop one. Your history, your passwords and your tabs get synced across the tablet, mobile and desktop. All of this backed up by a not-for-profit organisation that only answers to you and not stakeholders of the parent company. I think people can use whatever they want, but I found Firefox to be the most portable and consistent of browsers over the years. I wished that Chrome for Android be the standard in Android and not the browser it has now. There is nothing more annoying than having a worse experience in surfing just because you switch devices.

Should modern browsers only be available on advanced smartphones?


That is a tough one. The most important thing is the experience. If a modern browser and great features are too slow to use on an old phone we dont deliver anything of use to the people using the phone. I see this right now in the native market. Ever since my one year old smartphone upgraded to Android Ice Cream Sandwich it keeps crashing and I cant even open the browser a lot of times. That is frustrating. We should strive to give the best possible experience, not bring the newest technologies to environments where they cause annoyance. This also applies to our programming habits - there is no point in using polyfills and simulations of CSS animation on Internet Explorer 6 when we could just show and hide on this browser instead of smoothly transitioning from one state to another. Back to the phone question though: we shouldnt force people to upgrade in outdated environments that are prone to bad experiences but we should give them the option to upgrade. A browser that only upgrades when the OS gets a new upgrade is hindering innovation.

94/100

What are the latest innovations in mozilla?


Well, we are working on a few things at the moment, all of which very necessary to make the mobile web a reality: Firefox for Android got a complete overhaul to allow a seamless experience between Desktop and mobile. Boot to Gecko is the platform (Linux core and Firefox using the WebAPIs to access the hardware) powering the open web device which means a web enabled smartphone for the price of a feature phone. This will be sold in the Latin American market by our partner Telefonica. Persona is an identity system for the web based on the browserID protocol. It means you can log in to web sites and apps on desktop and mobile without the need of usernames and passwords and without sharing your online identity and social graph. This is independent of browser, it works on all modern browsers. Collusion is an add-on that shows you whilst you are surfing who gets your data. Your whole data transmission history is shown as a graph and we hope this shows a few people just how much of our online travels are monitored and sold to advertisers. We keep working on improving the built-in developer tools of Firefox to ensure that people do not need to rely on add-ons to use the browser as a development platform. In the education space we set ourselves a goal to make 10,000 people web makers this year who have no experience in building things for the web. We reach out to journalists, have programs for kids and run the Mozilla Festival to do so. And last but very much not least the Mozilla Marketplace for Web apps allows you to build and distribute cross-platform HTML5 apps. The market place especially is an essential step to promote HTML5 apps as a way to make money and to delight users.

95/100

Firefox is very popular on mobile devices. What are the benefits compared to default web browsers?
Firefox Mobile is a speedy, powerful and customised upgrade to mobile browsing for Android phones and tablets. It puts people in control of their online lives and enables them to synchronise their personal Web experience across devices - taking browsing history and passwords everywhere they go. It offers the highest level of privacy and security features in mobile browsing and offers lots of add-ons to enhance the experience. And it has more predictable and much better documented HTML5 support. It is the free upgrade to the browser that doesnt mean you have to wait till Android upgrades.

Developers talk a lot about the War of browsers. Do you feel there is merit to this?
Ive blogged about this lately - I really think the passion we have for seeing browser makers going at each others throats and the fanboyism in developers is very much holding the web back. I am really happy that I work for an organisation that builds a browser that is not part of an operation system strategy or a means to get more users to use our online services. There are a lot of different goals and targets to meet by the different browser vendors. I think it is time that, as developers, we demand more predictability in support across browser and stop getting excited about innovation for the sake of innovation. No web developer I know builds a big customer-facing product without resorting to libraries, polyfills and frameworks. We should be allowed to concentrate on the interface experience of our users, not how to make things work across dozens of device/browser permutations. A browser war is good for browser makers, but actually makes it much harder for developers. Unless you think building for one browser only is the right way to go. Ive seen that fail a few times, and it would be sad to see people do the same mistake again.

What will differentiate one browser from another?

It should be the interface and the way the browser ties in with your day to day work. You should be able to easily switch from a work to a home setting, it should always be obvious which data the browser gets from you and where it goes. My biggest pet peeve are browsers that are not available across platforms and only upgrade when the OS upgrades. This is not the 90s, we should have learned by now that browsers need to change quicker, be very easy to patch when security holes happen and I should have the option to customise and personalise my browser in the way I want and take these changes with me wherever I go. A great browser should fix and upgrade itself without interrupting me and let me enjoy the web rather than lock me in to its services.

The web of tomorrow is the web of now on better devices.

What is your vision for the Web of Tomorrow?


The web of tomorrow is the web of now on better devices, with more human interfaces (touch, gestures, facial and movement detection) and more ubiquity. My biggest concern right now is that the innovation on the web has overtaken our connectivity speeds and connectivity availability. The web of tomorrow to me wouldnt mean much of a difference to my experience and productivity as it works offline and online. The thing that lets me down the most about the web of now is spinning loading animations and messages that this cant be done as you are offline. We can do better than that. On demand entertainment, education and communication is not a future dream if we stop bickering about patents, stop building expensive glass shields to protect against piracy instead of making piracy the worse experience and embrace the fact that the web - the read/write web where consumers are makers - is here instead of seeing it as a danger to the media world as we know it.
96/100

The mobile web is limited when you want to access some Hardware APIs. Hybrid apps (with frameworks such as PhoneGap) are an efficient workaround. But do you feel that web apps will soon be able to communicate with the camera for instance?
They already do. Firefox Mobile and Boot to Gecko have phone access. The getUserMedia API (and Addy Osmanis polyfill using Flash) gives access to the camera, too and you can use an HTML5 canvas to display and modify the video stream coming from the camera. I think it crucial for web apps to access the hardware of the device - as only by using the hardware access that comes natural with a device allows you to build compelling apps. Playing a game by tilting your phone is much nicer than pressing arrow buttons on a small screen.

Web developers are living in exciting times and we see new innovations every week. Do you see a gap between those innovations and what customers need?
Tough to say. A lot of times customer need is driven by advertising. A few years ago, if you had asked people if they wanted to fling birds at pigs on their phone theyd have told you - no, Id rather call people without spending a fortune. I do see a lack of down to earth innovation though. We try to bring people interactive glasses but we fail to link for example our smartphones and public transport. We have amazingly connected devices in our pockets and we use them to 99% for entertainment. Id love to see more innovation in the field of accessibility, language learning and so on but the assistive device angle is very often overlooked. A great example Ive seen lately was cooklet. This is a recipe app that allows people to cook better food. It is tablet based but the developers realised that most of the time when you cook you have sticky fingers, so the navigation is moving your hand left or right over the camera rather than on touch. We need more of this thinking.

97/100

Do you feel that the browser is the new Operating System? In the long term, could we foresee the end of native and proprietary technologies to develop and deploy apps?
Yes I very much hope so. I am sick of having to hunt apps. OSX is a good example. You install the native apps from a market - they might as well be HTML5. The Web Runtime project of Mozilla very much targets this use case.

A few years ago, platforms such as Flash used to promote youll get the same user experience everywhere. Its not the current trend. How do you explain this?
I guess people finally realised that the promise of getting the same experience everywhere is either a lie or results in a boil-in-the-bag experience without any flavour. A good app to me gets better and more immersive by how much the device the user experiences it on supports. If you run a new computer with the latest Firefox you should get a better experience than the Windows2000 machine with IE6. You shouldnt block out IE6 but you should not give it code it chokes on.

As a web developer, what tools do you use today?


I am very much a purist. I use TextMate as my main editor (thinking of giving SublimeText2 a go or go fully towards Vim), I love to collaboratively test things with people in JSFiddle, JSBin or Cloud9IDE. For graphics, I use Photoshop CS2 as I was too lazy to upgrade. For video editing I use Screenflow and MPEGStreamClip and for audio work Audacity. I love Dropbox for collaboration and Google Docs for writing and reviewing. In Mozilla a lot works with IRC and Etherpad for collaboration and for code versioning and hosting GitHub is the weapon of choice. All in all our work has become much more hosted and shifting from tool to tool is much easier. I really love the concept of collaborative developing and this will just become better and better. Ive never felt happy with massive IDEs and build processes. I guess that means I am a web developer and not an engineer. What I love to bits is that you dont need debugging tools any longer as browsers come with them built in. It is incredibly useful to right-click an element and do a debug seeing its HTML, the CSS that was applied to it, see what was loaded and how long it took and to be able to change values in the browser debug tools and see the effect. A lot of the knowledge we have right now we gained by viewing the source of other solutions. Nowadays we can not only peek under the hood of the systems we use but we also can fiddle with the cables and see what happens when we tweak things.

What is missing? What tools would you expect to have available?


I am not the main group of developers, or lets say makers we need to get to using HTML5. What is missing right now are the simple tools to allow anyone to build HTML5 and CSS3 solutions. Basically what we need is Dreamweaver and Flash with standards output. And we need enterprise tools to keep up. There is no point in us pushing for a web app world based on standards when the really expensive CMS, frameworks and IDEs still spit out old school table layouts or plugin based solutions. The other big request I have is good mobile development tools. It is not fun at all to reload things on mobiles and wait for 90% of the time, we need more immediate results. There was a great presentation by Bret Victor on Inventing on principle and he showed some tools he build based on this personal principle of an immediate connection between building and seeing the result. For example he showed how you could define an animation whilst playing it or defined the success path of a jump and run game by playing it. This is a very powerful idea. I love being a coder, but we have the means and the technology to make me redundant for a lot of things and allow people to build whilst using tools. I am looking forward to this world as it would also turn tablets from consumption devices to builder tools.

98/100

You invite developers to become evangelists. How do you encourage them and why?
It is great to develop and to be paid for it. But when you dont get people to understand what you are doing then you are a delivery service and you will get money but never the respect you deserve. Developing is not screwing things together or repairing machines. It is a very creative and almost poetic way of dealing with logic, commands and machines that understand them. By sharing the passion that you have for a subject and making other people understand it the way you do, you have a much better chance to get more freedom and a voice when decisions are being made and goals set. We are probably the best paid market in the job world right now and there are not enough people to fill the positions that are open. That someone that wanted works on things they dont believe in or are not proud of saddens me as I think only people with a passion for what they do should be paid a lot of money. I encourage developers to reach out and speak about the things they do by example and by sharing all that I do for them to use. I know quite a few people who used my code examples, books and articles in trainings or my slide decks in company internal presentations. It is pretty incredible how much more your company listens to you when people from the outside praise you or talk about you. Much like we pay consultants to tell us the obvious we are either too busy to see or too scared to bring up.

What defines a good evangelist?


Hunger, interest, the ability to take a step back and get a high level overview, the ability to find the story in data or a use case others havent thought of for a technology and above all a clear way of communicating. Another very important part of being a good evangelist is being impartial and admit when other products but the ones you are working on are better. A good evangelist is not a sales person, you dont push products and ideas down peoples throats but instead you show the benefits and let people decide on their own. Last but not least a good evangelist needs to be flexible in translating. What you say should be catered to the audience you want to reach - not just to sound knowledgable and clever. The what is in it for me is the question you should provide the answer to, not the heres what I want you to like.

How should people learn a new technology today? How can we stay up to date with HTML development?
Online. Of course books are a great thing to have if you want to deep-dive but print is too slow to keep up with the changes we have. Following the right people on Twitter, subscribing to good online magazines and news feeds and reading mailing lists, bug requests and statements from the big web companies, the W3C and WHATWG is what keeps you up-to-date. I know people who are totally in the know
99/100

and dont go to conferences at all. That said, good conferences and workshops give you a chance to have some real dedicated time to learning new things and people should use that time. When I was leading a team people were only allowed to go to events when they gave a presentation afterwards on what they learned and what the company could benefit from. Learn and share and it is incredible how fast you are seen as an expert.

Are there any personal projects youd like to accomplish in the coming years thanks to the web?
I want to take a crack at educating people who long to learn but cant afford it. Khan academy is a great project for learning all kind of things online but you need a good connection and a computer to do it. One idea I am playing with is talking to Google about donating Chromebooks to internet cafes worldwide or in deprived areas to allow people to learn from TED and Khan Academy. This is powerful stuff but it still smacks a bit of being elitist. It hurts me to see people live in very well-off environments and waste their time watching TV or being sports fans with a massive hatred for each other. Education is a way out of misery for a lot of people and it is despicable how we treat it in the Western world as something that is given and not cool and not needed. The web can give those who live in areas where the government censors them a voice. The web can also allow people to learn on their own terms and time. It is a wonderful thing and could change this world much like the appearance of movable type brought literacy to poor people in Europe back in the days.

to ap t d M is he c oz o im v illa er ag e B th ar e

100/100

appliness

CHEAT SHEET

css selectors
first-of-type first-child descendant child nth-child adjacent sibling
general sibling

learn css selectors with this great interactive sample by Ben Howdle
#target p:first-of-type {color: #36de4e;} <div id=target> <h2>Where the Buggalo Roam</h2> <p>Alright, lets mafia things up a bit. Joey, burn down the ship. Clamps, burn down the crew. No! Dont jump! Dr. Zoidberg, that doesnt make sense.</p> <div> <p>Does anybody else feel jealous and aroused and worried? </p> </div> <h2>The Mutants Are Revolting</h2> <p>But, okay! I just want to talk. It has nothing to do with mating. Fry, that doesnt make sense.</ p> <h2>Space Pilot 3000</h2>

first-line nth-of-type last-of-type


This pseudo-class matches the first child element of the specified element type.

<p>Now, now. Perfectly symmetrical violence never solved anything.</p> </div>

ABOUT THIS ARTICLE


Ben Howdle is a web developer from Droitwich, UK. He works by day at Wapple.net and by night and weekends as Two Step Media. An insatiable passion for the dynamic web and exciting web applications. http://twostepmedia.co.uk/notes/ @benhowdle

ONLINE RESOURCES CSS selector on W3C http://www.w3.org/TR/CSS2/selector.html 30 CSS selectors to memorize http://net.tutsplus.com/tutorials/html-css-techniques/the-30-css-selectors-you-must-memorize/ CSS selectors http://css.maxdesign.com.au/selectutorial/

appliness

FEEDBACK

room 112 - phonegap exploration

Whenever I start to play around with a new technology, platform or framework I usually plan out a small and easy to complete project that tries to address some of features I am most interested in testing out.

room 112 background


To vet out PhoneGap I decided to build a simple app called Room112 to keep track of my hotel room number when I travel. This exploration document outlines how I approached architecting my app but also some of the issues I ran into while exploring how PhoneGap works. Room112 is a simple way to keep track of your hotel room number. Enter your hotel room number into the app and the next time you open it the number is displayed for you along with the time you checked in, the floor your room is on and a map of the hotels location. TripIt doesnt really track the last two bits of information. This app is just like the card a hotel would give you with your room number on it.

d n u o laygr

- PhoneGap - Xcode - CSS

Difficulty
- rookie - intermediate - expert

Todo list

- design for iOS - deploy

- optimize

by Jesse Freeman

Goals
I collaborated with Wesley Crozier (who did all the artwork) on Room112 with the goal of creating a simple PhoneGap app that looks and feels as close to native as possible. I travel a lot and always forget my hotel address, room number and floor. I set the following goals when creating this application: Create a simple one-screen app Test our local storage Make the app feel like a native iOS app Have most design done via CSS3 Test out animation on mobile Web browsers Take advantage of some simple jQuery Understand how to set up and publish a PhoneGap app in Xcode Display a Google Maps image via built-in GPS support The full source code for this project is availbile on github.

architecture
Room112 is very simple. When you launch the app it checks for saved room data. If no data exists you are taken to the check-in screen. If data does exist then the check-in card is displayed with the saved data. I also planned on being able to review past check-in data, but this feature didnt make it into the initial release.

Over the next few pages, we will discuss each of the applications screens based on the designs with functional notes on the logic.

103/117

Loading Screen/Background This represents the loading screen of the application, which is the same as the background image.

When the application is fully loaded, a small pocket is faded in to allow for easier masking of the check-in card animation.

104/117

Once the application is fully loaded, the two layers (background and pocket) work very well to mask off the card animations and offer up a little more depth to the design.

Before Check-In This is the screen you see after launching the app when no hotel information is saved. Simply enter a room number to activate the Check In button and save your data.

During this process, the user is not able to actually check in until the room is entered. All other data is optional to make adding room data as fast as possible. Once a room number is added, the Check In button is highlighted and the user can save their data. Check In When you have entered your hotel information you are ready to check in. The Check In button becomes active, allowing the data to be saved.

105/117

One thing to note is that the date is automatically filled in before checking in. Again, the goal is to simplify the check-in process by not forcing the user to have to add information we can assume is going to be contextual to the check-in process. Also, the user can add their room number as well as a map to the hotels location by pressing on the top part of the card at any time. Once the user checks in, the card slides down into the pocket and the Check In button is changed to a Check Out button indicating that the data is set. At this point, if the user exits the app and comes back, their data will be saved and re-displayed until they check out. Check Out After you have checked in, you can edit your data at any time or check out. Checking out clears the card data and a new empty card is shown allowing the user to start the process over.

Once the user hits the Check Out button, they are asked if they are sure they want to proceed.

If the user gives the OK to check out, the card slides out of the pocket and off the top of the screen and is reset before a new card slides back down into view.

106/117

Error Screen There is only one error state for the app, which is displayed when the app is unable to locate the GPS position of the check-in.

Error handling and messaging is done by swapping out images. The initial state of the application is to display the Add Your Location image. If there is a failure, the Could Not Locate Your Position image is displayed. If the location can be used, an image of the map from Google is loaded in on top of the display area.

Code Review
Due to the nature of this application, the codebase was architected to be as small and portable as possible. I did not break out the JS logic into classes and relied heavily on frameworks to help speed up my development. Lets take a look at what is going on under the hood.

107/117

Application Structure For the most part the application is very flat. There is a standard www directory, which houses all the Web content loaded by PhoneGap. In that directory are my css, images, js and index.html files.

In addition to the www folder, PhoneGap automatically adds all the needed libraries to run on iOS when you create a new PhoneGap template from Xcode.

Its important to note that once you create a PhoneGap project you will need to manually link the www directory into the project. Here is how the project looks in the finder:

Notice the www sites outside of the Xcode Room112 project and how I tend to include my own design directory in the root to keep my source designs organized, especially when I check in a project.
108/117

Lets take a quick look at each of the directories in the www folder. css - There are two css files, one for the base of the project and the other that has overrides for retina resolution graphics. Ill talk more about this in the next section. images - This contains all the images the Web side of the PhoneGap application requires to display. js - This contains all my JavaScript libraries. I am using the following libraries for this project: jquery1.7.1.min.js - to handle animation, changing data on the page, etc. jquery.animate-enhanced.min.js - allows jQuery animations to use CSS3 transitions where supported to help improve performance on mobile lawnchair-0.6.1.min.js - handles local storage phonegap-1.3.0.js - PhoneGaps APIs and native to JS bridge room112.js - application logic Room112 Core Code I designed the application to be a simple state machine. It handles three states: not checked in, checked in and checking out. From there I was able to manage the state changes and update the display accordingly. Here is a high-level overview of the apps functions and what they do: onDeviceReady - This is the main init function of the application. It handles setting up the initial visuals of the application along with requested saved room information from local storage via Lawnchair. Once everything is set up, the room card is animated in and the app is ready to be used. loadGPS - This handles making the request to the browsers built-in GPS API: navigator.geolocation.getCurrentPosition(showMap, showMapError); I decided to use the built-in browsers GPS instead of the API provided by PhoneGap to help minimize any dependencies on their library. The call to navigator.geolocation accepts two callbacks, one for success and the other for failure. When the request is made, a pop-up is shown automatically to allow the user to accept permission to use the built-in GPS.

showMap- This is called when the GPS is able to find the users location. It simply makes a request to Google Maps for an image and displays it at the top of the check-in card. The URL for the map is saved locally so the service doesnt have to be called when the app re-loads and the user is checked in. cacheMapURL = http://maps.google.com/maps/api/staticmap?center= + coords. latitude + , + coords. longitude + &zoom=13&size=+width+x+height+&maptype= roadmap&key=MyGoogleMap sAPIKey&sensor=true; The method accepts a position argument that can be used to determine the coordinates the Google Maps API needs to generate the image. I also provide the image size manually so I can support standard resolution and retna.

109/117

showMapError - This is called if the GPS is unable to return a valid position to the application. I simply show the error image allowing users to try again later.

addInputListeners - This handles adding listeners for the buttons and other UI elements such as each input field. This allows me to listen for when an input field loses focus so I can call invalidate() in order to see what data has changed. invalidate - This method compares the data in the form to what has been saved. This allows the application to automatically save any changes made while checked in and also test if the user has entered enough information in order to check in. updateDisplay - This manages updating the action button based on the state of the application.

getHotelData - This is a simple utility method for accessing saved hotel data from Lawnchair.
110/117

formAction - This is called after invalidate() and simply switches between the applications mode methods: checkIn(), checkOut() and saveRoomData(). checkIn - This is the default state of the application when no saved data is found upon launch. checkOut - This animates the card off the screen, calls resetCard() to clear the data and resets the applications mode method back to checkIn(). saveRoomData - This is called when the user is checked in and they change any values in the form. resetCard - This clears the data on the check-in card while it is off-screen. This is called after the card is animated off the screen. Design/Retina Display Support The application was designed with iPhone 4S Retina display support in mind. In order to do this you must provide two resolution images and a secondary CSS sheet to override the base image paths. This is relatively easy to set up. <link rel=stylesheet type=text/css href=css/normal.css> <link rel=stylesheet type=text/css href=css/retina.css media=only screen and (-webkit-min-device-pixel-ratio: 2)> As you can see, the initial CSS sheet is loaded and then we use a media query, which is supported on WebKit on iOS to detect if the pixel ratio is 2x larger. Here is an example of a low res image: #pocket { background: url(../images/pocket.png) no-repeat; background-size: 320px 80px; width: 320px; height: 80px; position: absolute; bottom: 0px; } and the retina override: #pocket { background-image: url(../images/pocket@2x.png); } Its important to note that in the base style we need to define the background size so that when the retina image loads its not rendered at its native resolution. Here are the two images:

111/117

All the images in the application have retina size graphics to support the higher resolution, and the difference visually on the device is noticeable. On a website, this approach would be problematic since we are loading both sets of images and would probably want to use a better solution so the application is only loading the right image to cut down on bandwidth. I didnt take this into account since it was a locally running app, but if the app is image intensive this could end up being a performance issue.

Finally, there is some mobile WebKit-specific CSS code you should add to your style sheets as well to help make your app look and feel more native. <!-* { -webkit-touch-callout: none; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); -webkit-text-size-adjust: none; -webkit-user-select: none; } --> This allows you to hide the fact that your app is running in WebKit and remove highlight colors on taps and user selection on form elements. Also, adding the following metadata block will disable scaling and zooming, which is built into the WebView by default: <meta name=viewport content=width=device-width; initial-scale=1.0; userscalable=0;> This extra line of CSS and meta tag will make your app run at native resolution and is important to have in your projects HTML code. Animation I chose to go with jQuery for the animation and ran into performance issues, which I will discuss later on. My reasoning for this was to make sure the app wasnt dependant on CSS3-specific animations that may not be supported on other platforms. To me this was a big concern even though I focused on an iOS app only, so if you have a clear understanding of where you application will be deployed to you may just want to go with CSS3 animations from the beginning. jQuery did allow me some additional control with call backs and delays, which I still dont find to be well supported with CSS3 animation right now, especially when you need to execute JS during a key point in the animation sequence. Local Storage I chose to go with a local storage wrapper framework called Lawnchair. Using local storage directly is relatively easy, but I had read good things about it and liked its implementation. It is very straightforward to set up a pointer to local storage by doing the following: hotelData = new Lawnchair({name:hoteldata}, function (e) {console. log(Storage Open, this); }); Then, at any point when I need to save data, I simply reference the Lawnchair instance and save my data out. var formData = { room:$(#room).val(), floor:$(#floor).val(), date:$(#date).val(), map: cacheMapURL } hotelData.save({key:room, value:formData}); I save out my applications state to a simple JSON object, which makes loading and parsing the data very easy.
112/117

Development Workflow
Browser Prototyping I experimented with several workflows, the first of which was doing all my development locally and testing it out in Safari on the Mac. This allowed me to quickly prototype the application using the tools I was most comfortable with along with WebKits built-in debugger. One of the biggest issues I ran into while testing was being able to simply debug my CSS and JS, which is incredibly difficult to do when running the PhoneGap application on the iPhone simulator.

Development in Xcode Once I was happy with the application and the way it ran in Safari, I moved the project over to Xcode. Development tended to slow down considerably for me since debugging issues and JS integration were difficult without better debug tools. The big downside to testing in Xcode is the compile time. While it isnt too bad, it does take a few seconds to go back and forth between the two environments. I did find Xcode to have good JS support and was even able to continue to use Xcode to write and fix my JS logic without much issue.

113/117

Deployment Once you have everything set up in a PhoneGap project, your application runs just like any other iOS application. Technically, this is a native app, so you get to take advantage of Xcodes built-in support for setting up provisioning.

Issues
I ran into several issues that in the end made it hard for me to make Room112 feel like a native app. I have outlined a few of the issues below to help you address them in your own app as well as things to keep in mind when planning out your own development. Animation Performance I ran into lots of issues trying to get native-looking animation using PhoneGap. At first my issue was the performance penalty of using jQuery for animation. Doing direct DOM-based animation is incredibly slow. There are lots of hacks you can do in order to force hardware-accelerated CSS3 animation on iOS, and it wasnt until I started using jquery.animate-enhanced that I began seeing better performance. Also, at some point everything slowed down on later builds and I was unable to debug. My suggestion for iOS is to simply use CSS3 transitions from the beginning and make sure you take advantage of the -webkit-transform: translate3d(0,0,0); hack, which is said to force all other CSS3 translations to be hardware-accelerated. This could also be problematic if you are trying to directly port over an existing mobile site to PhoneGap, which may not have support on other platforms for CSS3 transitions. I

114/117

will probably continue to experiment with this to find the best solution with good fallback support to allow the code to be as portable as possible. PhoneGap Issues I was running into a lot of issues trying to disable the native scrolling of the Web page via JS. The only way I was able to fully disable it was to add the following Objective-C code to disable scrolling and bouncing directly in the PhoneGap WebView instance: UIScrollView* scroll; for(UIView* theWebSubView in self.webView.subviews){ if([theWebSubView isKindOfClass:[UIScrollView class] ]){ scroll = (UIScrollView*) theWebSubView; scroll.scrollEnabled = false; scroll.bounces = false; } } I ended up having to add this to the AppDelegate.m class, which is auto-generated by PhoneGap because the JS code to ignore scroll events didnt block the user from scrolling from inside a text field. This is a good example of how you may need to augment your PhoneGap app with native code when JS hacks simply dont work. I was also running into issues trying to access the Google Maps APIs and had to whitelist the URL in PhoneGaps .plist file, which is located in the native project.

Once you have PhoneGap.plist open, simply go to the ExternalHosts property and add any URLs your application will need access to.

After that you shouldnt have any issues.

115/117

Alerts and Messages I ran into several strange issues with displaying alerts in my app. At first I was trying to avoid using the native PhoneGap hooks so I could continue to test my app in Safari on my computer, but when you call JSs default alert youll see the parent page the alert is being called into.

I wasnt really expecting this, and it certainly takes away from the native feel of the app. I tried to switch over to PhoneGaps built-in native alert message bridge but had problems getting it to run. I was using an older version of PhoneGap, so hopefully updating it will fix the issue. Other people on the forums had similar issues with it as well. Graphics Issues I didnt run into many issues, but the few that I did see are slightly annoying. The biggest issue I noticed is after the application loads there is a split second flash of white, which happens when the WebView loads right after the loading image is removed and the index.html pages background hasnt fully loaded. I believe there are ways to keep the loader image up longer to smoothe out the transition, but that would have to be done in Obj-C and there isnt much you can do about it. This just means you need to pay special attention to the loading of your main page, especially if it is graphically intensive or requires a lot of JS to initialize. The only other issue I want to highlight was the difficulty I ran into with getting fonts to match up exactly with my Photoshop designs. At first I tried to do the entire design via CSS3 and use fonts where possible. I was unable to get the layout to match my PSD to my satisfaction and ended up using rasterized images instead for most of the UI. While this app would be relatively easy to localize, since I could swap out different images via CSS based on the default language of the phone, in a production application this would not be ideal. While CSS3 and browser fonts have come a long way, there is still a gap between what can be done in the browser versus Photoshop, so that limitation should be in the back of your mind when trying to figure out how to set up the visuals of your PhoneGap app. Development Bottlenecks While I only focused on doing an iOS application, I have heard of issues building for Android. In addition, it became next to impossible to maintain a Web-only version of the app. So, while it would be ideal to be able to deploy the same code base to a mobile website and have the PhoneGap wrapper app for people who want to use native, you will end up having to modify each build for each platform. You could write a wrapper to emulate or disable the PhoneGap-specific JS logic so that your application would degrade better on the Web, but the level of work required to architect a single app that could run on the Web and in PhoneGap on all its supported platforms would be a huge undertaking. Its not impossible but I just dont think that it ends up being worth the level of effort. In that case you are better off defining blocks of code that are portable and spending the last 10-20% of your development customizing the code base to each platform.

116/117

Moving Forward
While this was a fun little exercise to help me get up and running in PhoneGap and vet out Web-based app building, I still have a lot to do and learn. Deploying to Multiple OSs The next steps are going to be getting this app to run on different OSs such as Android and Windows Phone 7. The biggest reservation I have with porting the app to other platforms is that each one has its own UI and navigation paradigm. While Room112 was designed according to what most iOS apps are starting to look like, using real-world textures to look photo realistic, this may look out of place on Android and Windows Phone 7. Luckily, I could easily swap out the CSS and images and quickly reskin the app; its just extra work and platform-specific customization I dont want to do. This is just another problem with the dream of having a single app that runs and uses the same code base across multiple platforms. iPad/Tablet Support I would also like to eventually support the iPad, tablets and other higher-resolution devices but would have to rethink my design approach. Right now the app doesnt warrant a larger-resolution design, but I would like to test out how to handle scaling up in a PhoneGap app. I may just try this on another project. Again, I hope it would be a few quick CSS changes, but most phone apps need to be rethought out for tablets so it would be interesting to see how much of the application logic I could keep and what the performance would be on larger screen devices.

Conclusion
While this wasnt the most awe inspiring application I have ever built, it did give me a great opportunity to learn more about PhoneGap as well as how to style for iOS mobile browsers. All in all, while PhoneGap is easy to use and being able to leverage a Web Stack for development is a great advantage, its also incredibly difficult to get a native feel and responsiveness most users would be expecting on iOS. I think if you approach your PhoneGap app understanding the limitations and pain points, you can actually produce something really polished and portable across multiple platforms. I wouldnt rule this out because over time, as devices get faster and support more HTML5 features, this may turn out to be a viable development solution.

MORE INFORMATION

>

ABOUT THIS ARTICLE


Jesse Freeman is an artist, interactive developer and writer. For over 13 years, hes been on the cutting edge of interactive development focusing on web and mobile platforms. Jesse has been a speaker at 15 conferences and is a writer for several sites and autha book on HTML5 game development. http://jessefreeman.com/ @jessefreeman

ONLINE RESOURCES PhoneGap official website http://phonegap.com Room 112 Source Code http://github.com JQuery http://jquery.com/

>

appliness

IS A WARM GUN

e want to showcase in this section the best applications built with web standards. If you want to showcase your application, contact us by email - contact@appliness.net. This month, find professional contacts, see who the noisy tweeters are and check in to what your friends are drinking.

linkedin on the ipad


by linkedin

LinkedIn has very talented in-house JavaScript developers. The new iPad application is the best access to your professional network. The interesting fact is that it has been unveiled by VentureBeat. com. Guess how much of LinkedIns new iPad app is actually mobile web and not native? 95% is using web standards! Only one screen in the entire LinkedIn iPad app is actually native. The rest is good ol HTML5-based mobile web technology, running in the browser and leaning heavily on Node.js. Its a brand new experience created for iPad users. LinkedIn didnt try to adapt the desktop web application or to extend the mobile app, they built a tablet experience. They estimate that in the base of complex apps, responsive design cannot answer users needs. Here is a quote of Prasad, leader of the mobile LinkedIn team: You cant take a mobile app and just scale it up to tablet or desktop, he said. A lot of responsive design is building one site that works everywhere, and that works for websites. But its bad for apps You have to come up with a completely different design because of the use case. (source - VentureBeat)

lottatweets.com
by greg wilson

Greg Wilson uses Twitter often to keep up with the latest trends, announcements, and more. He has been looking for a good project to beef up his jQuery skills, and decided to see if he could build something to meet his own requirements for a tweet rapid-reader. LottaTweets is a web-based tool that fills your screen with tweets in a multi-column, newspaper-style layout allowing super fast reading. In addition to being able to quickly scan tweets, there are a few neat features: - Color coded retweet rate: Tweets are color-coded based on the number of re-tweets per minute. - Noise factor: The noise factor is computed by number_of_tweets / number_of_followers. - Infinite horizontal scrolling: you can keep scrolling right and it continues to load more tweets for you to read.

untappd

by untappd llc Untappd is a mobile app that allows you to socially share the brew youre currently enjoying, as well as where youre enjoying it, with your friends! Known as the Foursquare for beer, user can check-in to what theyre drinking and where and share with their friends on Untappd, Twitter, Facebook, & Foursquare.

Its using PhoneGap and demonstrates that you can design beautiful experiences using web standards on iOS and Android. One of the best demonstration of the power of mobile apps.

appliness

VIDEO TUTORIAL

HTML5 for App Developers: PhoneGap Build


by Piotr Walczyszyn
ABOUT THIS ARTICLE
The video above is a short tutorial on how to quickly get up and running with PhoneGap Build. PhoneGap Build allows you to compile and package your PhoneGap/Cordova apps for different platforms using online service. This helps you do iOS development without a Mac or Xcode, or Windows development without a PC.

ONLINE RESOURCES Official website of PhoneGap Build https://build.phonegap.com/ Official website of PhoneGap http://phonegap.com/ HTML5 development http://www.adobe.com/devnet/html5.html

http://outof.me/ @pwalczyszyn

<div> or <section> or <dl> ?

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

ABOUT WHICHELEMENT.COM

121/121

Terry Ryan is a Worldwide Developer Evangelist for Adobe. The job basically entails helping developers using Adobe technologies to be successful. His focus is on web and mobile technologies including expertise in both Flash and HTML. http://terrenceryan.com/ @tpryan

? . . . . . . .

Address

A postal address, where someone would deliver mail. Its seems straight-forward, there is an element named <address>. Case closed right? Its not so simple, the spec has something to say.

Candidates

- <address> - A collection of <div> and <span> elements. At first glance it would seem <address> would be the right choice, its called address for goodness sake. But alas, as per the specification, address in the context of an HTML5 element <address> means To whom should I address my issue with this piece of content. So in this case it is referring to the authors of the article or the maintainer of the page. If in that context, a postal address makes sense then you can use it, otherwise postal addresses should be otherwise marked up.

Verdict

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

Further reading
- HTML5 doctor - the address element - W3C - the address element

Raymond Camden is a 38 year old married father of three living in beautiful Lafayette, Louisiana. He is a developer evangelist for Adobe. His primary technical focus is on web standards. http://www.raymondcamden.com/ @cfjedimaster

appliness

LIBRARY OF THE MONTH

MANAGE YOUR DATA IN THE CLOUD WITH SIGNALBOX

Signal Box is A GREAT way to build the server for your WEB APPLICATIONS. IT eliminates the need for a custom backend, so you can focus on building a polished app for the Web. I HAVE DEVELOPED A CRUD SAMPLE TO EXPLAIN HOW TO IMPLEMENT THIS CLOUD SERVICE.

A simple architecture
When you plan to build web apps, especially mobile apps, you usually need to define a simple database architecture and expose the tables with web services. I see more and more services in the cloud to create and manage the data of custom applications, getsignalbox.com is one of them. For this tutorial, Ive just created a free account, Ive declared an ApplinessTest application and created one resource called subscriber in five minutes. The web dashboard lets you add properties in your resources. So Ive defined that a subscriber has an EMAIL property, which is a STRING with an email validator (built-in validator provided by the service), plus a FIRSTNAME and a LASTNAME properties. Then you can manually add records in your new resource, or use the web API to read/write/delete or update your records. As we are web application developers, Ive built a mobile app with jQuery Mobile that will display the list of subscribers listed in the cloud, and Ive added a simple form to create new subscribers. The SignalBox team has shared on GitHub a JavaScript library to directly make calls to your database using JavaScript.

d n u o laygr
- SQL - REST - JQM

Difficulty
- rookie - intermediate - expert

Todo list

- REST HTTP

- add records - sql queries

by Michal Chaize

Test the final application


Here is my final application where you can list the subscribers and create new ones. Everything will be stored in the cloud.

123/126

the html view


Actually, there is no code on the server-side, everything is managed by SignalBox that exposes http services to manage your data resources. So here is the code Ive used to build this app: Lets start with the HTML code and this unique screen: <body> <div data-role=page> <div data-role=header> <h1>My Subscribers</h1> </div> <div data-role=content> <div data-role=collapsible> <h3>Register a new subscriber:</h3> <label for=basic>First name:</label> <input type=text name=name id=ti_firstName data-mini=true onkeypress=activateCreation()/> <label for=basic>Last name:</label> <input type=text name=name id=ti_lastName data-mini=true onkeypress=activateCreation() /> <a href=# id=createButton onclick=create() class=ui-disabled data-role=button data-icon=plus> Create subscriber</a> </div> <hr/> <h3>Get all subscribers:</h3> <a href=# onclick=getAllData() data-role=button data-icon=refresh>Get all data from SignalBox</a> <p>List of subscribers:</p> <ul id=listSubs data-role=listview> </ul> </div><!-- /content -->

</div><!-- /page --> </body> Im using a very classic jQuery Mobile structure. The <ul> list of subscribers is empty and well feed it with the data coming from SignalBox. As you can see, you need to tap the buttons to call getAllData() and display the list of subscribers, or to call create() and add a user in the database.

124/126

get all subscribers


Now lets send a request to SignalBox to get the content of the subscribers resource. <script type=text/javascript> SignalBox.setup({ app : ApplinessTest, username : mchaize }); function getAllData(){ //Clean list $(#listSubs).children().remove(li); $.mobile.showPageLoadingMsg(b, Loading data from SignalBox, false); SignalBox.list(subscribers, { query : SELECT * ORDER BY {{thevar}} ASC, queryReplacements: { thevar : firstName }, error: function(xhr, ajaxOptions, thrownError){ console.log(xhr); console.log(ajaxOptions); }, success : function(response, xhr){ console.log(response.records.length + subscriber records found.); $.mobile.showPageLoadingMsg(b, Loading data from SignalBox, false); totalSub = response.records.length; for(var i=0; i < response.records.length; i++){ console.log(response.records[i].firstName); $(#listSubs).append(<li>+ response.records[i].firstName+ + response.records[i].lastName+</li>); } $(#listSubs).listview(refresh); $.mobile.hidePageLoadingMsg(); }}); } You start by declaring the name of your application (ApplinessTest) and your username. This sample is not secured, but of course, you can create a secured connection and manage the cross-origins requests. Once the setup() method of the SignalBox object called, Im using the list() method and the query property to define a custom SQL query and order my results by firstnames. Then its a classic asynchronous HTTP request: in case of success, I can parse the array of results and use the jQuery append() method to

125/126

feed the list. As you can see, 10 lines of code and you get everything.

CREATE A NEW RECORD


The activateCreation() function is just here to make sure that the firstName and lastName HTML fields are not empty. Then it activates the Add a subscriber button. function create(){ var theFirstName = escape($(#ti_firstName).val()); var theLastName = escape($(#ti_lastName).val()); var theEmail = contact@appliness.com; SignalBox.create(subscribers, { params : { firstName : theFirstName, lastName : theLastName, email: theEmail }, success : function(subscriber, xhr){ console.log(Created: + subscriber._id, subscriber); getAllData(); } , error : function(subscriber, xhr){ console.log(Error: + subscriber._id, subscriber); } }); }; function activateCreation(){ if(($(#ti_lastName).val() != ) && ($(#ti_firstName).val() != )){ $(#createButton).removeClass(ui-disabled); }else{ $(#createButton).addClass(ui-disabled); } } </script> The create method just needs to know the name of the targeted resource and the parameters to apss. It will automatically build the SQL INSERT query for you. The 5 default actions of the JavaScript SDK are: list, read (to get a single record), create, update and destroy. As you can see, you can create and manage your own database in 5 minutes!!! Visit the website of SignalBox and sign-up for free:

https://getsignalbox.com/
126/126

appliness

BLEEDING EDGE

Example of getUserMedia and CSS Filters

One of the more interesting features on the bleeding edge of HTML5 is getUserMedia. This API covers basic access to the users audio and video devices.

playing with css filters


One of the more interesting features on the bleeding edge of HTML5 is getUserMedia. This API covers basic access to the users audio and video devices. I first blogged about this a few weeks ago with my face detection example. Since that time Ive been curious what other uses would be possible with this support. As I said in the previous blog entry, chat and quick picture taking is kind of obvious. Im more interested in the not-so-obvious (and possibly not very practical ;) examples. In the excellent HTML5 Rocks tutorial on getUserMedia, they discuss how live video passed to a canvas object can be modified using CSS filters in real time. This allows for interesting effects. For example, Hulk Ray!!!

an interactive form
When I saw this demo, I was curious if something fun could be done with it. Along with basic color changes you can also blur the video. I thought it might be cool to create a user registration form that creates a crystal-clear image of you as you fill it out. I know many of you cant use this feature yet in your browser, so here are a few screen shots to demonstrate what I mean. Upon hitting the form, here is how things look.

How does it work? Im going to assume you read my earlier post (or the excellent HTML5 Rocks article I already linked to). The basic gist is - once youve gotten access to the web cam and have directed the output to the canvas, you simply apply different CSS filters based on how correct the form is.

allfields = $(input[required]); $(input[required]).on(input, function(e) { if(!hasGetUserMedia()) return; //count number of invalid fields var totalGood = 0; for(var i=0, len=allfields.length; i<len; i++) { if($(allfields[i]).attr(required) && allfields[i].checkValidity()) { totalGood++; } } console.log(totalGood); var video = $(#myuglyface)[0]; video.className = ; switch(totalGood) { case 0: video.classList.add(deepblur); break; case 1: video.classList.add(notdeepblur); break; case 2: video.classList.add(lesserblur); break; case 3: video.classList.add(lightblur); break; default: } }); And the CSS styles declaration: <style> #myuglyface { float: right; width: 500px;

128/129

height: 500px;

.deepblur { -webkit-filter: blur(30px) grayscale(1); } .notdeepblur { -webkit-filter: blur(20px) grayscale(0.8); } .lesserblur { -webkit-filter: blur(10px) grayscale(0.6); } .lightblur { } </style> -webkit-filter: blur(6px) grayscale(0.4);

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 getUserMedia W3C specification http://dev.w3.org/


HTML5 Rocks Tutorial http://www.html5rocks.com/en/tutorials/getusermedia/intro/ WebRTC http://webrtc.org/

appliness

BLEEDING EDGE

Face detection with getUserMedia

This is a JavaScript API that gives you access to (with permission) the users web cam and microphone.

A bleeding edge api


There are quite a few interesting APIs evolving in the modern web, but not all of them are going to be things you would use in most projects. Ive been very public about my feelings concerning canvas, for example. Great for games and charting - but not much else. That doesnt make it a bad feature. It just makes it one I wont use terribly often. Whenever I read about some new cool feature being developed, my mind starts trying to figure out what they could be used for in a practical sense. Obviously whats practical to you may not be practical to me, but figuring out how I would actually use a feature is part of how I learn it. One such feature is getUserMedia (W3C Spec). This is a JavaScript API that gives you access to (with permission) the users web cam and microphone. getUserMedia is currently supported in Opera and Chrome (I believe it is in version 18 now, but you may need to grab Canary. You also need to enable it. Instructions on that here.) Once you get past actually enabling it, the API is rather simple. Heres a quick request for access: //a video tag var video = document.getElementById(monitor); //request it navigator.webkitGetUserMedia({video:true}, gotStream, noStream); function gotStream(stream) { video.src = webkitURL.createObjectURL(stream); video.onerror = function () { stream.stop(); streamError();

}; } function noStream() { document.getElementById(errorMessage).textContent = No camera available.; } function streamError() { document.getElementById(errorMessage).textContent = Camera error.; }

The first argument to getUserMedia is the type. According to the spec, this is supposed to be an object where you enable audio, video, or both, like so: {audio:true, video:true}. However in my testing, passing a string, video, worked fine. The demo you will be seeing is based on another demo so that line possibly came from an earlier build that still works with Chrome. The second and third arguments are your success and failure callbacks respectively. You can see in the gist where the success handler assigns the video stream to an HTML5 video tag. Whats cool then is that, once you have that running, you can use the Canvas API to take pictures. For a demo of this, check out Greg Miernickis demo: http://miernicki.com/cam.html Based on Gregs demo, it occurred to me that there is something cool we can do with pictures of our web cams. (Cue the dirty jokes.) I remembered that Face.com had a very cool API for parsing pictures for faces. (I blogged a ColdFusion example back in November.) I wondered then if we could combine Gregs demo with the Face.com API to do some basic facial recognition. Turns out there are a few significant issues with this. First - while Face.com has a nice REST API, how would we use it from a JavaScript application? Secondly - Face.com requires you to either upload a picture or give it a URL. I know I could send a canvas picture to a server and have my backend upload it to Face. com, but is there a way to bypass the server and send the picture right to the API? The first issue actually turned out to be a non-issue. Face.com implements CORS (Cross-Origin Resource Sharing). CORS basically allows a server to expose itself to Ajax calls from documents on other domains. Its a great feature and I hope more services enable it. The more complex issue then was taking the canvas data and sending it to Face.com. How can I fake a file upload? Turns out theres another cool new trick - FormData. Fellow ColdFusion blogger Sagar Ganatra has an excellent blog entry on the topic. Heres how I used it: function snapshot() { $(#result).html(<p><i>Working hard for the money...</i></p>); canvas.width = video.videoWidth; canvas.height = video.videoHeight; canvas.getContext(2d).drawImage(video, 0, 0); var data = canvas.toDataURL(image/jpeg, 1.0); newblob = dataURItoBlob(data);

var formdata = new FormData(); formdata.append(api_key, faceKey); formdata.append(api_secret, faceSecret); formdata.append(filename,temp.jpg);


131/132

formdata.append(file,newblob); $.ajax({ url: http://api.face.com/faces/detect.json?attributes=age_est,gender, mood,smiling,glasses, data: formdata, cache: false, contentType: false, processData: false, dataType:json, type: POST, success: function (data) { handleResult(data.photos[0]); } } });

Lets look at this line by line. First off - I need to get the binary data from the canvas object. Theres a few ways of doing this, but I wanted a Binary Blob specifically. Notice the dataURIToBlob method. This comes from a StackOverflow post I found a few weeks back. I create a new FormData object and then simply begin setting my values. You can see I pass in a few API requirements but the crucial parts are the filename and file object itself. Below that, you can see the simple jQuery Ajax call. Face.com has a variety of options, but I basically just asked it to return an estimated age, gender, mood, and whether or not the person was smiling and wearing glasses. Thats it. I get a nice JSON packet back and format it. Now obviously no API is perfect. Ive had different levels of results from using the API. Sometimes its pretty damn accurate and sometimes it isnt. Overall though its pretty cool. Here are some scary pictures of Yours Truly testing it out.

For another look at getUserMedia, check out these examples: Its Curtains for Marital Strife Thanks to getUserMedia Testing WebRTC on Chrome Bleeding Edge HTML5, WebRTC & Device Access Capturing Audio & Video in HTML5

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 getUserMedia W3C specification http://dev.w3.org/


Cross-Origin Resource Sharing http://dvcs.w3.org/hg/cors/raw-file/tip/Overview.html WebRTC http://webrtc.org/

appliness
Data Binding Using data-* Attributes via Eric Bidelman

HELTER SKELTER NEWS

Fresh news about HTML and Javascript collected by Brian Rinaldi - remotesynthesis.com

Self-updating scripts via Steve Souders

requestAnimationFrame API: now with sub-millisecond precision via Paul Irish

Working with files in JavaScript, Part 3: Progress events and errors via Nicholas Zakas Using requestAnimationFrame to Optimize Dragging Events via Ryan Stewart Adding Filter as you type support to IndexedDB via Ray Camden

Diving into CanJS viaCurtis Commings

Annotation Overlay Effect with CSS3 via Mary Lou

JavaScript CustomEvent by David Walsh

appliness

HELTER SKELTER NEWS

Has your sites third-party content gone rogue? via Joshua Bixby Intro to CSS 3D transforms via Dave DeSandro

JavaScript design patterns Part 2: Adapter, decorator, and factory via Joe Zim

Diving Into CSS Regions via Umar Hansa Animated 3D Bar Chart with CSS3 via Sergey Lukin

Dynamically creating jQuery Mobile radio buttons with Mustache via Andy Matthews

Meet Crockfords JSCheck via Andrew Burgess

Front-end Unit Testing with JavaScript via Danny Croft

SASS vs. LESS by Chris Coyier

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

RAYMOND

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

ANDY 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

Andy is currently a Senior Web Developer for Dealerskins, Inc. and runs commadelimited.com. Hes the author of open source ColdFusion libraries: PicasaCFC, & ShrinkURL. Hes written an HTML/JS Adobe AIR Application called Shrinkadoo (in AIR Marketplace), & speaks at RIA User Groups or conferences.

MATTHEWS

MARK

DONG
Mark Dong works in Adobe for 6 years in China.

Flex, JavaScript and Java developer with much experience on enterprise RIA architect and project manager in FSI and Energy industry.

BRIAN
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.

Mark is also the author of The road of Flex master.

RINALDI

TERRENCE
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.

RYAN

PIOTR
Walczyszyn
Piotr Walczyszyn is a technology geek leaving in Warsaw, Poland, where he was born. outof.me is his new blog in which he wants to express his current interests and share some of his work. Technologies change; new trends come and go. These days nobody talks about RIAs (Rich Internet Applications) anymore, and he thinkd this phrase has become almost pass although its main concepts have not.

ANDREW
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.

TRICE

MAILE

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

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.

WILSON

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

FOLLOW

o t t n a w ? u e Yo ribut t n co

US

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

CONTRIBUTE

Você também pode gostar