HTML5 Hacks

Hacking Next Generation Web Technologies

HTML5 and Ember.js at Øredev 2013:The Arts in Malmö, Sweden

| Comments

At the beginning of November, I was given an opportunity to give two talks in Malmö, Sweden at the Øredev conference. First of all, I have to say I was extremely impressed with the conference. Although the theme was the Arts, I found it to be a developer’s conference with an artsy edge. The speakers I had a chance to see were developer’s developers, one of my favorites being a talk on Meteor by Chris Mather (@eventedmind) of eventedmind.com. I’ve maintained a peripheral view of Meteor, so it was good to get a beginner to intermediate overview of its capabilities. Given that I have been doing MongoDB / Ember-data client work as of lately, I am particularly interested in exploring minimongo.

Øredev 2013 HTML5 Hacks

The city of Malmö was also a pleasure to experience, and as you might imagine, the people of Sweden were very welcoming. One of the highlights for me was the speaker dinner at the Malmö City Hall, originally constructed in the Middle Ages. On a side note, I finally had a chance to meet and have dinner with Douglass Crockford, a long time inspiration and virtual mentor, who was in town to give the keynote on Managing Async with RQ.

Building Web Applications with Ember.js and Ruby On Rails from Øredev Conference on Vimeo .

My first talk was a preview of my new book O’Reilly’s Building Web Apps with Ember.js. I shared the stage with co-author and fellow frog, Thomas Q. Brady. We took the audience through the creation of RocknRollCall, an intermediate level Ember.js application that fills in many of the blanks that most of the ‘Getting Started’ applications don’t.

O'Reilly's Building Web Apps with Ember.js

Some of the highlights of the book, and the talk, cover topics such as: a survey of Ember tooling, debugging with the Ember Inspector, Ember boilerplates, app initializers, promises in Ember, the needs API, Ember components, 3rd Party JavaScript Integration (jQuery, D3), Ember testing, SPA authentication, Ember-data and other client-side persistence solutions, and remote data persistence with Ruby On Rails and Node.js.

My second talk was HTML5 Hacks Evolved, where I continue to share more hacks from by first book HTML5 Hacks, and html5hacks.com. This talk is culmination of HTML5 specifications that will have you rethinking browser-based applications. Some of the highlights of this talk included: Web Workers, WebSocket w/ GeoLocation, Device Orientation, and LeapJS, Web Components / Polymer / Ember Components (Custom Elements, Shadow DOM, HTML Imports, Model Driven Views, and Local Storage.

HTML5 Hacks from Øredev Conference on Vimeo .

In 2014, I’m retiring the HTML5 Hacks talks, to begin focusing solely on Single Page Application development in 2014. My hope is to kick out an early release of Building Web Apps with Ember.js very soon, and finish the book in early 2014. After that I’ll be in Louisville, KY at Code PaLOUsa to continue the Ember.js roadtrip.

JavaScript Makers: How JS Is Helping Drive the Maker Movement

| Comments

This post is mirrored from: jessecravens.com

ok200 Conference

I spend my days writing a lot of JavaScript, and helping companies deliver ambitious UX focused applications to the web. I author books on the subject, blog, and speak at conferences as often as I can.

I work for frog, a product design firm, that for the last forty years has been helping increase the profiles of brands like Sony and Apple through iconic design.

I work within a culture that has deep roots into the Maker Movement; A culture that was making before the Maker Movement was cool, the “original makers” if you will. Written upon our walls and slide decks is the tag, ‘Love What You Make’, and as you might expect many of the frogs that sit around me are craftsfolk, DIYourselfers, and tinkerers. It is not uncommon to see a flying quadcopter, a mesh sensor network of Arduinos, 3D printed prototypes, explorations in next generation gesture with the Leap Motion and Kinect, video production, motion studies, 3D modeling, along with the standard artistic mood boards and web and native mobile application wireframes. Let’s just say there is no shortage of creativity across every medium imaginable.

Sharing My Craft with my Children

ok200 Conference - setting up

All of that being said, I’m a parent of two young children. My little ones constantly challenge me to find ways to share quality time with them. The parents reading this know the juggling act.

What I try to do is architect bridges between my children’s curiosity and the passions of others that have explored their crafts in a deep way. Myself, and my wife, being the most important of those craftsfolk.

If I’m doing it right, when I spend time with my children, they should share in my excitement and passion. If I’m doing it wrong, I’m overwhelmed and exhausted from work. In my vision, my children should be witnessing a model of how to wake up everyday with the goal of embracing opportunity to create a combination of function and beauty within the world around them.

Maker Faire

So it is in this context, that I met up with Mozilla’s Luke Crouch, and Tulsa Mini Maker Faire’s Scott Phillips to put together the closing keynote at the 200ok conference .

JavaScript Makers: How JS is Helping Drive the Maker Movement

The 200ok conference is on track to become Oklaoma’s premier web conference attracting a sold out crowd of web professionals from all over Oklahoma and the neighboring states. Going in, I felt as though I knew my audience well. In other words, if I spoke to them about languages they would understand, JavaScript and HTML5, my message would easily resonate. I also knew that given their location, Tulsa, OK, a presentation that touched upon work life balance and family values would immediate strike a chord as well.

So in the spirit of authenticity, I pretended as if getting prepared for a closing keynote dependent on hacked together hardware and software demos wasn’t challenging enough; I made the decision to include my 6 year old son, Carter with a flying drone and a custom configured Minecraft server accessible over conference wifi. I knew this would ensure that the presentation dangled on the brink of disaster, mirroring the chaotic reality of both open hacking and parenting.

My thinking was that a presentation on this topic should be authentic, and reflect the reality of my proposition, not be an ivory tower, academic/authoritative talk about how to share your craft with your children. I also made sure to not prep Carter. With a loose structure in place, we took the stage and worked our way through a story that consisted of 12 open software and hardware demos that showcased JavaScript as a primary scripting language, and a table full of hardware that ranged from a drone, a dissected wifli helicopter and erector set, a leap motion, and numerous prototyping boards.

Here are some of the highlights:

JavaScript and Prototyping Boards

Earlier this year I did a presentation at HTML5.tx that focused on building an Internet of Things with JavaScript and various open hardware prototyping boards such as Arduino, BeagleBone, and the Raspberry Pi. It was in that talk that I made a connection that eventually led to an introduction to Luke. So, given that the HTML5.tx content was of interest I started the presentation with a demo of the Arduino, Johnny Five, the original Beaglebone and BoneScript.

bonescript.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
  ...

  require('bonescript');

  ledPin = bone.P8_3;
  ledPin2 = bone.P8_4;

  ...

  app.post('/motion', function(req, res, next) {

    console.log(req.body['eventType']);

    res.send('Motion data collected for '  + req.body['eventType'] + ' event');

    if (req.body['eventType'] == "motionstart"){
      digitalWrite(ledPin2, HIGH);
    }
    else if (req.body['eventType'] == "motionend") {
      digitalWrite(ledPin, HIGH);
    }

  });

Nodecopter and the Leap Motion

I started with the basics of the node-ar-drone module:

ar-drone.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
  var arDrone = require('ar-drone');
  var client  = arDrone.createClient();

  client.takeoff();

  client
    .after(7000, function() {
      this.animate('flipRight', 1000);
      this.animateLeds('blinkRed', 5, 2);
    })
    .after(3000, function() {
      this.stop();
      this.land();
    });

Later, a crowd favorite was mapping the gestures from the Leap Motion to the Parrot AR drone, so that a one finger clockwise gesture triggered a nodecopter takeoff. A counter clockwise gesture then landed it. I was able to put this together using the leapJS and node-ardrone node modules, based on some initial hacking by Markus Kobler, where he pulled this off at a Nodecopter London event.

Jesse Cravens blowing minds with a JS-driven copter. from Michael Gorsuch on Vimeo.

ScriptCraft: Running JavaScript from within Minecraft

ok200 Conference

Later, I showed how to script inside of the Minecraft virtual world, using Walter Higgins’ great ScriptCraft library. I wasn’t expecting the conference wifi, and single access point, to suffice in allowing Carter and I to interact within virtual world. I was also concerned about the dynamic IP, and having to change it on the fly, start/restart the server, etc. So I made the decision 10 minutes before to not have Carter log in, and I would just speak to the possibility instead. In true 6 year old fashion, he rebelled and logged onto my server, popping up in front of me wearing a Creeper mask, as I was mid stream explaining how to script wooden signs with his 1st grade sight words as a homework exercise.

sightwords.js
1
2
3
4
5
6
7
8
9
10
Drone.extend('sightwords',function (){

    var wordsArr = ["have", "black", "three", "want", "get", "how", "two", "ten", "come", "went", "into", "know", "my", "do", "down", "who", "must", "let", "with", "red", "find", "will", "new", "live", "five", "you", "funny", "yes", "no", "may"];

    for (i = 0;i < wordsArr.length; i++){
        this.right(0+i).sign(wordsArr[i],68);
    }

    return this.move('sightwords');
});

Needless to say, his innapropriate behavior was a crowd favorite. I have to admit, it was mine as well.

ok200 Conference

Going into the talk, I knew I’d either be trying this again in the future or abandoning it as ‘one of those ideas’ that sounded good in theory, but was just not going to work. Where did I land? Well, let’s just say that Carter and I are looking for our next opportunity to share our experiences with other parents/web professionals.

Debugging Modern Web Applications Part 1

| Comments

As JavaScript-centric web applications continue to become the standard, and the browser continues to evolve into a full-featured web application platform, developers need powerful debugging tools to help quickly troubleshoot issues and fix them efficiently. Issues can range from HTML/CSS browser inconsistencies, JavaScript exceptions, and a myriad of performance issues that range from DOM access to network latency.

There a number of tools that web developers can use to help make debugging front end applications less painful.

Debugging Modern Web Applications

In this tutorial, we will walk through the top tools available and how to use these tools by addressing some of the most common issues faced in modern web application. This is a beginner to intermediate level tutorial for web developers getting started with debugging the web, or programmers coming from other languages who want to better understand how to troubleshoot client side JavaScript, the DOM, performance, and network calls.

To demonstrate we will be debugging a simple web application. The source code is available here: https://github.com/jessecravens/techpro-debugging.

Read more at: http://tech.pro/tutorial/1404/debugging-modern-web-applications-part-1

Web Worker Patterns

| Comments

JavaScript is executed in a single thread. If you’re not familiar with threads, what this means is that JavaScript can only execute one block of code at a time. If code is already executing, any interaction by the user will instantiate an asynchronous event that is queued up for later execution. Other events like those from XMLHttpRequests and timers, are also added to the queue.

So, as you might expect, a single-threaded architecture can be problematic to the user experience if a particular script takes a long time to complete.

Read more at: http://tech.pro/tutorial/1487/web-worker-patterns

Building Next Generation Widgets With Web Components

| Comments

Nerdclustr

For SXSWi and FluentConf this year, @boyofgreen and I created a demo application to showcase some of the hacks that we included in our book OReilly’s HTML5 Hacks.

The demo application, Nerdclustr, is an HTML5 mobile application that brings ‘nerds’ of all types together conferences and provides a visual map that updates in real time. The application was written with Node.js and the Express web framework. It demonstrates the following specifications: HTML5 Web Forms, Geo Location API, WebSocket, Canvas, CSS3 transforms.

Given, the attention that Web Components and Polymer.js have been getting lately, I felt this was a good opportunity to demonstrate some of the exciting new specifications that are making their way to modern browsers. For the sake of this tutorial, I’ll be using and providing screenshots of Google Chrome, but it should be worth your time to explore the status of each of the specifications in other modern browsers as well.

In this tutorial, we will take a look at the HTML5 specs mentioned above in detail. Then, we will explore Polymer.js and build out an example application.

Read more at: http://tech.pro/tutorial/1421/building-next-generation-widgets-with-web-components

Add Narration to Your Slide Deck With HTML5 Audio

| Comments

Most presenter will share their slide deck on the web after their presentation. But many times the slides are only a shell of the real talk. Fortunately, with HTML5 audio, we can add our voice back to our slides and recreate the real presentation.

Sample Example

To show what we’re trying to accomplish, I’ve created a very basic slide deck with audio narration which briefly describes the issue at hand.

Audio on the Web

Back when the web was just taking off, it was common (bad) practice to include audio on your page. I’m not talking about a Flash-based music player, but rather the more primitive audio solution: <bgsound>. Those who were programming back when HTML 3.2 came out will be familiar with this oft-forgotten tag.

Luckily for us, <bgsound> isn’t the end of the story. According to the latest W3C spec, <bgsound> has a much friendlier HTML5 alternative that you’ve likely heard of: the <audio> tag.

So what benefits does <audio> bring us? Well, <bgsound> was an IE only property. <audio> on the other hand has wide support, with only IE 7 & 8 lacking functionality. <audio> also allows API access so that we can control playback, seek through the audio, and even manipulate the data with the MediaStream API. Plus, the <audio> tag allows you to use native controls and/or provide your own customized controls.

File formats

Before getting in to the details on how we’re going to use the <audio> tag, we need to talk a little about file formats. The MP3 format has gained tremendous popularity over the last decade and a half, but unfortunately due to licensing requirements, relying on MP3’s for our audio is a messy situation.

Luckily for us, the <audio> tag supports multiple formats gracefully. This means we can create a patchwork of audio file formats to gain full browser support. And we’ll need a patch work because no one format is currently supported across all browsers.

For our needs, we’ve created two files: an MP4/AAC file and an OggVorbis file.

If you’d like to read more on the subject, I highly recommend Ashley Gullen’s post ‘On HTML5 audio formats – AAC and Ogg’.

How to Use It?

We can load our audio files by adding in two <source> tags with information about our two audio files inside of the <audio> tag:

index.html
1
2
3
4
5
<audio controls id="myPlayer">
  <source src="myAudio.m4a" type="audio/mp4" />
  <source src="myAudio.ogg" type="audio/ogg"  />
  Your browser does not support HTML5 audio.
</audio>

There are two attributes for each <source> tag. The ‘src’ attribute, whose value is the path to the audio file, and the ‘type’ attribute, whose value is the MIME type of the file.

Again, the browser will choose whichever file it supports without you having to do any detective work. Very nice.

Starting/Stopping

Okay, so now if we load this into a webpage we’ll get a simple audio player that we can manually control. What’s nice is that since we used the ‘controls’ attribute, the audio player controls are built for us by the browser. This makes allowing manual control of our audio very simple.

For our needs, we want to control the playback of the audio programmatically. To do this, let’s take a look at the API for starting and stopping playback. The element has two built-in methods for this, ‘play’ and ‘pause’. Calling those methods is straightforward:

audio.js
1
2
3
var audioPlayer = document.getElementById('myPlayer');
audioPlayer.play();
audioPlayer.pause();

These methods will come in handy in a moment when we want to start playing our audio after we change slides.

Seeking

The other part of the equation is the ability to seek to different locations in our audio. Again, this is very simple. Our element has a ‘currentTime’ property that can be both get and set (in seconds).

audio.js
1
2
3
4
5
6
7
8
9
console.log(audioPlayer.currentTime); // returns 0 since we haven't started playing the audio yet
audioPlayer.currentTime = 10; // move to 10 seconds into the audio
console.log(audioPlayer.currentTime); // returns 10

audioPlayer.play();

setTimeout(function () {
  console.log(audioPlayer.currentTime); // returns 11
}, 1000);

As you can see, getting and setting the current time is a trivial process. In the Part 2, we’ll put this functionality to use by adding narration to slides.

Implementing Slide Narration

So now we’ve got the building blocks for implementing a slide narrator. To make things easier, we’re going to use the fantastic ‘Deck.js’ project as our HTML slide framework. Deck.js supports extensions, which allows you to add functionality to your slides beyond what’s already provided.

We’ll be creating a new extension called Narrator. For brevity’s sake, I won’t get into the details of Deck.js or creating extensions, but you can check out the code in the deck.narrator.js GitHub repo.

Our extension boils down to one requirement: It should automatically play a defined section of audio on each slide.

That might sound simple, but we need to figure out a couple of things first:

  • How will we define what audio to play for each slide?
  • How will we stop the audio after it gets to the end of the section

Defining Audio Stops

There are a couple of ways to define what segment of the audio each slide plays. You could define a start time and a stop time for each slide, but that seems like too much work. Instead we’ll just define how long each slide should play for, and then calculate the implied start and stop timestamps for each slide.

To store our audio duration, we’ll take advantage of HTML5 data-* attributes by creating a custom ‘data-narrator-duration’ attribute. The value of this will be the number of seconds to play the audio for. Here’s a sample slide element for a Deck.js HTML file.

index.html
1
2
3
<section class="slide" data-narrator-duration="2">
  ...
</section>

Then, upon page initialization, we’ll loop through each slide element and calculate the proper start/stop timestamps for each slide. This is important in case our viewer wants to move through the slides in a non-linear fashion. Here’s the basic code:

deck.narrator.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// create an array for our segment timestamps 
var segments = [];

// create a placeholder for our audio element reference 
var audio;

// we'll get to this variable later
var segmentEnd = 0;

function init () {
  // get the audio element we added to our page
  audio = document.getElementById('audioNarration');

  // use deck.js built-in functionality to get all slides and current slide
  var $slides = $.deck('getSlides');
  var $currentSlide = $.deck('getSlide');

  // set initial values for time position and index
  var position = 0;
  var currentIndex = 0;

  // now loop through each slide
  $.each($slides, function(i, $el) {
    // get the duration specified from the HTML element
    var duration = $el.data('narrator-duration');

    // this determines which slide the viewer loaded the page on
    if ($currentSlide == $el) {
      currentIndex = i;
    }

    // push the start time (previous position) and end time (position + duration) to an array of slides
    segments.push([position, position + duration]);

    // increment the position to the start of the next slide
    position += duration;
  });
}

Adding Playback Automatically on Slide Change

Now that we’ve got our segment timestamps defined, let’s look at playing that audio on each slide transition. Deck.js fires a ‘deck.change’ event when the slide is changed, so we can hook into that and have it call our changeSlides function, which looks like this:

deck.narrator.js
1
2
3
4
5
6
7
8
9
10
function changeSlides (e, from, to) {
  // check to make sure audio element has been found
  if(audio) {
    // move the playback to our slides start
    audio.currentTime = segments[to][0];

    // define the end of our section
    segmentEnd = segments[to][1];
  }
}

Most of the code makes sense, but I do want to talk about the ‘segmentEnd’ line and what it’s doing.

Playing Segments of Audio

Unfortunately, you can’t give the play() function an amount of time to play for. Once you start playing, it will keep going until it runs out of audio or you tell it to pause. Thankfully, the audio element emits a ‘timeupdate’ event which we can listen to in order to pause playback once our segment timestamp has been reached. We can add that listener just like any other event listener:

deck.narrator.js
1
audio.addEventListener('timeupdate', checkTime, false);

Our ‘checkTime’ function is very small. All it does is check to see if currentTime in the audio is greater than the segmentEnd time. If so, it pauses our audio:

deck.narrator.js
1
2
3
4
5
function checkTime () {
  if (audio.currentTime >= segmentEnd) {
    audio.pause();
  }
}

Automatically Moving Through Slides

Now that we’ve got our audio hooked up to our slides, we can take advantage of the other extensions already written for Deck.js. https://github.com/rchampourlier/deck.automatic.js/‎ is an extension that makes your slides run automatically. By including this extension with our presentation, we can recreate that ‘presentation’ feel to our slides.

Aside from the going through the steps of adding the automatic extension, we also need to make sure that if a user starts/stops the audio, we start/stop the slideshow playback. To do this, we’ll sync up the ‘play’ and ‘pause’ events of our audio element with the automatic extension. For simplicity, we’re going to control all slide playback using our audio controls and leave off the deck.automatic.js playback control.

Deck.automatic.js adds some events to the mix, including ‘play’ and ‘pause’ events. By triggering these events when our similarly named audio events fire, we can make sure our slides are in sync with our content.

We add two simple functions to our extension:

deck.narrator.js
1
2
3
4
5
6
7
function startSlides (ev) {
  $.deck('play');
}

function stopSlides (ev) {
  $.deck('pause');
}

And then add our event listeners in the deck.init callback:

deck.narrator.js
1
2
3
4
5
6
7
8
9
$d.bind('deck.init', function() {

  // ... other code here ...

  // Sync audio with slides
  audio.addEventListener('play', startSlides, false);
  audio.addEventListener('pause', stopSlides, false);

});

Also, since our slides automatically advance, we need to comment out the ‘timeupdate’ event listener which would pause our audio at the end of a slide.

With those things taken care of, our slides and audio automatically transition to create a seamless experience.

Next Steps

One thing the code doesn’t take into consideration is if the user navigation the audio themselves. We could add this by listening to the ‘seeked’ event from the audio element and calculating where in the slide deck we should move to.

There is also some duplication around defining the duration of the as a result of adding in the automatic slide advancement extension. The other extension is looking for a data-duration attribute on each slide. This can be easily fixed by updating our code to look for that attribute instead.

Finally, we need to add in some captioning for folks who either cannot hear the audio or are in a public place and simply forgot their headphones. There is a new track tag that can handle this for us, so that’s a likely route we can go down.

Summing Up

That’s the majority of the code. I left out a few details in relation to some deck.js configurations, so again check out the GitHub repo for the full example.

Ember.js Views and Live Templates With Handlebars.js Part 1

| Comments

Tech-pro Ember.js Views

This is an exploration of Handlebars.js template library when used with Ember.js views. Many of the Handlebars.js tutorials on the web discuss the Handlebars API, but not in the specific context of using Handlebars with Ember.js. In addition to filling that void, I’ll also give a brief background of JavaScript templating in general to provide perspective as to the problems it is solving.

This tutorial will be divided into two parts. In Part 1, you should gain a clear understanding of JavaScript templates, the capabilities of Handlebars expressions and helpers, and how to write your own Handlebars helpers.

Read more at: http://tech.pro/tutorial/1308/emberjs-views-and-live-templates-with-handlebarsjs-part-1

Utilize Rich Input Data From W3C Pointer Events

| Comments

The W3C Pointer Events specification allows you to develop for a single event model that supports various input types. Instead of writing code for multiple event types, or having to use feature detection on page load that forces one event model over the other, Pointers allows you to write one event model that works everywhere. To make the transition easy, Pointer Events builds upon the Event Model of Mouse Events. This means that code that’s written for mouse events is going to be very easy to upgrade to Pointers.

There’s a lot of great content out there on how to implement pointers. Microsoft’s original post on pointer event implementation in IE10 and Windows 8 Apps is a great place to start learning about Pointers. To see an example of how to convert a current mouse based app into a pointers based app, I suggest you check out my channel 9 video on pointers. In this post I want to focus on a different aspect of pointers. Along with the multiple input support, and ease of implementation, Pointer Events also provide a wealth of new data values that can be quite useful in your applications. This post will look in depth at that data.

The code samples will all use the W3C spec pointer names such as “pointermove” and “pointerup”, however in practice this spec is not finalized, so the working code samples will be using the prefixed version such as “MSPointerMove” and “MSPointerUp”.

The Pointer Event Object

The Pointer Event object is modeled directly off the Mouse Event object, meaning all the values, and all the methods available in a mouse event model, will be present inside a Pointer Event Model. Let’s look at an example you might implement for the Mouse Event Model:

More poiner.js
1
2
3
4
5
6
7
8
9
        var myY, myX;
        document.getElementById('myElement').addEventListener('mouseup', function(e){

            e.preventDefault();

            myY = e.offsetY;
            myX = e.offsetX;

        });

This same code will also run with Pointer Events:

More poiner.js
1
2
3
4
5
6
7
8
        document.getElementById('myElement').addEventListener('pointerup', function(e){

            e.preventDefault();

            myY = e.offsetY;
            myX = e.offsetX;

        });

Every value and method will run the same. The main difference is that Pointers aren’t single threaded as Mouse Events are (you can only have one mouse pointer on the screen at a time). So if you have two Pointers on the screen, say two fingers on your touch screen, or one finger and one mouse, this event will be fired twice.

The “upgrade” comes in all the additional data that is available when you use Pointer Events.

The Event Type

Since a Pointer Event will be fired no matter what type of input you are using, it’s sometimes important to know what type of input is firing the Event. While accessing the event object, you can retrieve the pointer type like so:

More poiner.js
1
2
3
4
5
6
        document.getElementById('myElement').addEventListener('pointerup', function(e){

            var pointerType = e.pointerType;

        });

The type will return one of three value types:

-mouse: movement with a mouse -pen: movement with a pressure sensitive pen (not a capacitive stylus) -touch: any input from the touch screen

Note that the original spec, and what is implemented In IE10, provides number values that correspond with the input types. The value will return either a 2(touch), 3(pen) or 4(mouse).

For implementing pointers today, I actually check for both the string value or the number to be sure I support both the current implementation and the final spec:

More poiner.js
1
2
3
4
5
6
7
8
9
        document.getElementById('myElement').addEventListener('pointerup', function(e){

            var pointerType = e.pointerType;

            if (pointerType == 'touch'||4) {
                //this is a touch type pointer
            }

        });

New Values for All Pointer Types

There is a range of new values packed into the Pointer Event Object that is common across all pointer types. Each of these expose new values that provide valuable data for interaction development

PointerID: each pointer interaction is given a unique ID within your page and session. This number will be consistent across events for each interaction. For Example, a “pointerdown” event may be given a PointerID of 127, the subsequent “pointermove” and “pointerend” events will all have the same PointerID. This could be helpful for tracking which finger is doing what when there are multiple touch screen pointers on the screen at once. You can access the value as below:

More poiner.js
1
2
3
4
5
        document.getElementById('myElement').addEventListener('pointerdown', function(e){

            var pointerId = e.pointerId
            ;
        });

isPrimary: When multiple Pointer Events are on the screen at once, one of them will be assigned as the primary pointer. If one of them is of the Pointer type of mouse, it will be the primary, otherwise the first pointer to fire an event will be designated as the primary. This could be helpful for a developer who is building an application that is intended for a single pointer input. There is one catch, when you are using multiple pointer types on the screen at the same time, the first pointer of each type will be a primary pointer, and thus will allow you to have multiple primary pointers on the screen at the same time. The value can be accessed as such:

More poiner.js
1
2
3
4
5
        document.getElementById('myElement').addEventListener('pointerup', function(e){

            var isPrimary = e.isPrimary; // will return true or false

        });

button/buttons: This isn’t a new value for pointers, but in pointers you get new information. With both a mouse and a pen, the user has buttons that can be pressed. Weather those buttons are being pressed, and which button is pressed can be determined in these two values.

Figure 12-1

The entire list of values can be found in the most recent version of the spec, and keep in mind, not all values are implemented in IE10 (or any other browser) at this point.

Pen Specific Values

There are some values that are only applicable to the pointer type of Pen. Keep in mind the pen type refers to a mechanical stylus that works with supported screen types. Capacitive styus like the types used with iPads or Surface RT register as pointer types of touch, which will be discussed next.

The following values provide data in the Pointer Event Object for pens:

tiltX/tiltY: When you hold a pen there is generally an angle associated with it. If you were to hold the pen by the end and lower it perfectly straight on the screen, the tilt would be 0, but if you were to hold it in writing position, it would have a tilt value like 90. The tilt values are returned in degrees and be accessed as such:

More poiner.js
1
2
3
4
5
6
7
document.getElementById('myElement').addEventListener('pointerup', function(e){


            var tiltX = e.tiltX;
            var tiltY = e. tiltY;

        });

Pressure: Much of the data provided from a pen type pointer event is actually data provided from the pen to the screen. Another one of those is pressure. This is a value that reports how hard a pen is being pressed against the screen. The value is reported as a number between x and x. The value is accessed as below:

More poiner.js
1
2
3
4
5
6
7
document.getElementById('myElement').addEventListener('pointerup', function(e){


            var pressure = e.pressure;

        });

New Data for Touch

The Pointer Spec provides for detail touch data that just doesn’t exist in any other touch model on the web. Most significantly the actual width and height of a the touch area. Being so new, my testing showed that this value is often returned as 0 depending on the touch screen and driver installed on the device. Accessing this data follows the same patteren as the other new data:

More poiner.js
1
2
3
4
5
6
7
document.getElementById('myElement').addEventListener('pointerup', function(e){


            var width = e.width;
            var height = e.height;

        });

Keep in mind this is related to touch pointers only, so a mouse or pen will always return 0 for these values.

Mobile Implementations

The only mobile browser that has implemented Pointers is IE10 for Windows Phone 8. Since the phone OS doesn’t support a mouse or mechanical stylus, the only pointer type that returns is touch. The user agent does accurately report the pointer type, but many of the other new pointer values (such as width and height) are currently reported as 0s.

The Sample App

I’ve been working on a sample app that helps illustrate the rich data reported through pointers. It’s a simple canvas resized to your page that shows a report from each touch point of the key data values, additionally, the new data is used to effect the drawing on the screen to make a more accurate drawing surface.

Test the app here in IE 10 or any future browser that supports pointer events, or view this video of the app in action.

Next Steps

The Pointer Event Specification is not yet finalized so changes could occur at any time (and it has changed since the version implemented in ie10). If you interested in the work that is going on around Pointers, join the working group mailing list, and encourage others in the browser maker community to implement the Pointer Even Specification in every browser.

Push Notifications to the Browser With Server Sent Events

| Comments

Created by Opera, Server Sent Events standardizes Comet technologies. The standard intends to enable native real time updates through a simple JavaScript API called EventSource, which connects to servers that asynchronously push data updates to clients via HTTP Streaming. Server Sent Events use a single, unidirectional, persistent connection between the browser and the server.

Unlike the Web Socket API, Server Sent Events and EventSource object use HTTP to enable real-time server push capabilities within your application. HTTP Streaming predates the WebSocket API, and it is often referred to as Comet or server push. The exciting part here is that the Server Sent Events API intends to standardize the Comet technique, making it trivial to implement in the browser.

What is HTTP Streaming?

In a standard HTTP request and response between a web browser and a web server, the server will close the connection once it has completed the processing of the request. HTTP streaming, or Comet, differs in that the server maintains a persistent, open connection with the browser.

It is important to note that not all web servers are capable of streaming. Only evented servers such as Node.js, Tornado, or Thin are equipped incorporate an event loop that is optimal for supporting HTTP streaming. These, non-blocking servers handle persistent connections from a large number of concurrent requests very well.

A complete discussion on evented vs. threaded servers is out of scope for this post, but that being said, in the upcoming hack we will provide a very simple evented server implementation example to get you started. We provide a simple browser based JavaScript to connect to the server, and a server side implementation using Ruby, Thin, and Sinatra. For the record, this is also very easy to do with Node.js.

Here is a link to the companion github repository: https://github.com/html5hacks/chapter9

Ruby’s Sinatra

The Sinatra documentation describes itself as a “DSL for quickly creating web applications in Ruby with minimal effort.” This text has focused primarily on Node.js (HTTP Server) and Express.js (web application framework) to quickly generate server side implementations for hacking out functionality.

It would a disservice to not mention Ruby, Rails and Sinatra in the same or similar light as we have Node.js in this text. Although learning Ruby is another learning curve, in the larger scheme of programming languages it is a less daunting curve than most. And as most die-hard Rubyists will preach, it is arguably the most elegant and fun to write of all modern programming languages. Ruby on Rails, and its little brother Sinatra are also great web application frameworks to start with if you are new to web application development.

Much like Node.js and Express, Sinatra makes building small server implementations nearly trivial. So for the context of HTML5 Hacks, that allows us to focus our efforts on programming in the browser.

For now let’s build a simple HTTP Streaming server using Sinatra.

To get started with Ruby On Rails or Sinatra, check out the great documentation available at http://guides.rubyonrails.org/getting_started.html and http://sinatrarb.com/intro, respectively.

Building Push Notifications

Our goal in the next hack is to build a simple streaming server and use the EventSource object to open a persistent connection from the browser. We will then push notifcations from one ‘admin’ browser to all the connected receivers. Sounds simple, right? Let’s get started.

A Simple HTTP Streaming Server

Open up a file and name it stream.rb. Then add the following: Simple requiring of Sinatra and the JSON library:

stream.rb
1
2
  require 'json'
  require 'sinatra'

Then, we set up a public folder, and set the server to use the evented ruby server, Thin.

stream.rb
1
2
  set :public_folder, Proc.new { File.join(root, "public") }
  set server: 'thin'

Set up two routs for serving our 2 pages: index and admin. We will use Erb as our templating language. The details are out of scope, but our use is very minimal. More on Erb here: http://ruby-doc.org/stdlib-1.9.3/libdoc/erb/rdoc/ERB.html

stream.rb
1
2
3
4
5
6
7
  get '/' do
    erb :index
  end

  get '/admin' do
    erb :admin
  end

We’d like to timestamp each notification, so here is a very simple function definition.

stream.rb
1
2
3
  def timestamp
    Time.now.strftime("%H:%M:%S")
  end

We also set up two empty arrays: one to hold the connections and the other to hold out notifications.

stream.rb
1
2
  connections = []
  notifications = []

Now, for the routes. When our browser loads it s page, we have JavaScript running which will use the EventSource object to connect to a url here: http://localhost:4567/connect.

More on EventSource later.

But for now you can see the magic of the evented HTTP stream, the connection is held open until a callback is fired to close the stream.

stream.rb
1
2
3
4
5
6
7
8
9
10
11
  get '/connect', provides: 'text/event-stream' do
    stream :keep_open do |out|
      connections << out

      #out.callback on stream close evt. 
      out.callback {
        #delete the connection 
        connections.delete(out)
      }
    end
  end

Finally, any data this posted to the /push route is pushed out to each connected device.

stream.rb
1
2
3
4
5
6
7
8
9
10
  post '/push' do
    puts params
    #Add the timestamp to the notification
    notification = params.merge( {'timestamp' => timestamp}).to_json

    notifications << notification

    notifications.shift if notifications.length > 10
    connections.each { |out| out << "data: #{notification}\n\n"}
  end

As we said before, you can just follow the instructions at our git repository to pull down and build this code. Or if you have been following along, launch a terminal, navigate to the directory where you code is, and run:

cli
1
$ ruby stream.rb

Figure 9.15 Starting the Sinatra Server

Figure 7-2

Alright, so now that we have out Sinatra app up and running with custom routes to handle incoming requests from our browser.

If this doesn’t make complete sense yet, just hang loose. In the upcoming subsections, the rest of the items will start to fall into place.

Set Up the HTML pages

We will be building 2 pages: one for the admin to push out notifications, and the other will be for the connected receivers to receive the notification. Both of these ‘views’ will share the same layout, as such:

index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<html>
  <head>
    <title>HTML5 Hacks - Server Sent Events</title>
    <meta charset="utf-8" />

    <script src=”http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js”>
</script>
    <script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1/jquery-ui.js"> </script>
    <script src="jquery.notify.js" type="text/javascript"></script>
    <link rel="stylesheet" type="text/css" href="style.css">
    <link rel="stylesheet" type="text/css" href="ui.notify.css">

  </head>
  <body>
    <!—- implementation specific here -->
  </body>
</html>

The admin page will contain an input tag and a simple button.

admin.html
1
2
3
4
<div id="wrapper">
    <input type="text" id="message" placeholder="Enter Notification Here" /><br>
    <input type=”button” id="send" data-role="button">push</input>
</div>

And our receiver pages will display a simple piece of text:

receiver.html
1
2
3
<div id="wrapper">
  <p>Don't Mind me ... Just Waiting for a Push Notification from HTML5 Hacks.</p>
</div>

By launching one browser window to http://localhost:4567/admin you should now see our admin form.

Figure 9.16 The initial admin page

Figure 9-16

And, navigate to http://localhost:4567 in your browser and you should see.

Figure 9.17 The initial index page

Figure 9-17

Adding a bit of jQuery

We need to add a bit of JavaScript to attach an event listener to the “send” button. This snippet will prevent the default submission of the form and post the notifcation object to the server as JSON. Notice the url /push maps to the route we defined in our Sinatra app.

push.js
1
2
3
4
5
6
7
 $('#send').click(function(event) {
    event.preventDefault();

   var notifcation = { notifcation: $('#notification').val()};

    $.post( '/push', notifcation,'json');
 })

Now, lets open up five browser windows: one admin at http://localhost:4567/admin and four more receivers at http://localhost:4567

Figure 9.18 Opening 5 browser windows

Figure 9-18

Looking good.

But before we get started, lets set up our EventSource.

EventSource

Event Source is a super simple JavaScript API for opening a connection with an HTTP stream. Because our receiver pages are just ‘dumb’ terminals that receive data, we have an ideal scenario for Server Side Events. Earlier, when we discussed the Sinatra app, we showed exposing a route for the browser to connect to an HTTP stream. Well, this is where we connect!

es.js
1
2
3
4
5
6
7
  var es = new EventSource('/connect');

  es.onmessage = function(e) {
    var msg = $.parseJSON(event.data);

        // … do something
  }

Now we can add a simple notification with the available data,

es.js
1
2
3
4
5
6
7
  var es = new EventSource('/connect');

  es.onmessage = function(e) {
    var msg = $.parseJSON(event.data);

// … Notify
  }

And here is the final script for the admin:

es.js
1
2
3
4
5
6
7
8
9
  $(function() {
    $('#send').click(function(event) {
      event.preventDefault();

      var notification = {message: $('#notification').val()};

      $.post( '/push', notification,'json');
    })
  });

Installing jQuery.notify

For our Push Notifcations we will make use of Eric Hynds great jQuery plugin jquery-notify, located here at github: [github.com/ehynds/jquery-notify] (https://github.com/ehynds/jquery-notify)

In order to display the notification, we will need to include some markup to the receiver page.

receiver.html
1
2
3
4
5
6
7
<div id="container" style="display:none">
    <div id="basic-template">
        <a class="ui-notify-cross ui-notify-close" href="#">x</a>
        <h1>#{title}</h1>
        <p>#{text}</p>
    </div>
</div>

This creates a hidden div tag in the bottom of the document. We are not showing the CSS that uses “display: none” to hide it, but you can see more by examining the source code in the companion git repo.

Figure 9.19 Inspecting the DOM in Chrome Dev Tools

Figure 9-19

In order for jQuery.notify to initialize, you must first call the following:

es.js
1
2
3
4
$("#container").notify({
  speed: 500,
  expires: false
});

And here is the final script for the receiver:

es.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$(function() {

  $("#container").notify({
      speed: 500,
      expires: false
  });

  var es = new EventSource('/connect');
  es.onmessage = function(e) {
    var msg = $.parseJSON(event.data);
    $("#container").notify("create", {
        title: msg.timestamp,
        text: msg.notification
    });
  }
})

It’s that simple. The EventSource API is minimal and plugging it into a web framework like Sinatra or Node.js is straightforward.

Now, as we submit notifications from the admin page, our receiver pages are updated with time stamped notifications:

Figure 9.20 Pushing Notifications to the Connected Browsers

Figure 9-20

Turn Your Web App Into a Windows 8 App

| Comments

I talk a lot about just how similar the Windows 8 App environment is to developing for the Web. Since windows 8 uses the same rendering engine as IE10, and the same JavaScript engine as IE10, building a Windows 8 App with JavaScript is in fact, building a web app. We’ll talk about some of the keys to success but first, let’s take a step by step walk through converting one of my favorite web apps into a Windows 8 App. First thing first, you need to make sure your using Visual Studio 2012 (I’m using the Express version which is free). Since Visual Studio 2012 has a requirement of Windows 8, you’ll need to be running Windows 8 as well. We’re going to be taking the new fantastic game “YetiBowl” for our conversion. You can play a web version of the game here.

Figure 7-1

Once your done playing go to codeplex and download the project:

http://yetibowl.codeplex.com

If you open up the content in the directory marked “web” you’ll see all the code for the YetiBowl game. Now let’s go to Visual Studio and open up a new “Blank” JavaScript App:

Figure 7-1

Next, go back to your recently downloaded code, and copy all the content from the “web” folder

Figure 7-1

Now go back to your new Visual Studio project, and find the solutions explorer on the right side of the screen, past your code into your project:

Figure 7-1

Before our code is going to work, we need to open up our package.appxmanifest and make one small change. Find the field for “start page” and change it to the name of your html file(game.html):

Figure 7-1

Now, hit F5 and see what happens! That’s all it takes, our YetiBowl game is now a Windows 8 Store App, and a pretty fine one at that. Our web app code just works in Windows 8.

Figure 7-1

Add a Little Delight for your users

Now that you have your app up and running, let’s use one of the favorite Windows 8 API to add some additional features to our app. With a few lines of code we’ll be able to add the ability to “share” with the Windows 8 Share Charm. To keep it easy, let’s go to the bottom of our game.html file and add a script tag. We’ll then past a few lines of code into it:

win8.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24




        var dataTransferManager = Windows.ApplicationModel.DataTransfer.DataTransferManager.getForCurrentView();



        dataTransferManager.addEventListener("datarequested", function (e) {
            // Code to handle event goes here.


            var request = e.request;
            request.data.properties.title = "I'm Rocking out with the Yeti";
            request.data.properties.description = "HTML share from YetiBowl Game";
            var localImage = 'ms-appx:///media/logos/yeti_logo.png';
            var htmlExample = "<p>Here's to some fun with the Yeti. If your not playing YetiBowl, then your not really having fun!</p><div><img src=\"" + localImage + "\">.</div>";

            var htmlFormat = Windows.ApplicationModel.DataTransfer.HtmlFormatHelper.createHtmlFormat(htmlExample);
            request.data.setHtmlFormat(htmlFormat);
            var streamRef = Windows.Storage.Streams.RandomAccessStreamReference.createFromUri(new Windows.Foundation.Uri(localImage));
            request.data.resourceMap[localImage] = streamRef;

        });

Figure 7-1

You can find out more about the share charm here, but we are basically taking advantage of one of the many Windows RT APIs that you have access to via JavaScript inside your Windows 8 App. Once you’ve added this above code, you’ll now be able to share info from your Yeti Bowl Game to other apps you have installed.

Figure 7-1

Figure 7-1

A Few Closing Notes

It is very easy to move your web apps to Windows 8 where you have access to a whole series of new APIs and functionality that isn’t safe to expose on the web. That being the case, it’s important that you look into the security model that is implemented in Windows 8 Apps. Using a JavaScript library? Many libraries like YUI and jQuery already work within the Windows 8 App environment. It’s that easy, reuse your code, and your skills to build Windows 8 Store Apps.

Author: Jeff Burtoft – @boyofgreen code sample: http://touch.azurewebsites.net/yeti/game.html