Posts tagged CodeSample

player-full

Introducing Video Player Sample

0

Have you ever wanted a fun and beautiful way to publish videos on your own site like the new 60 Minutes or RedBull.tv apps from the Chrome Web Store? I’m excited to announce the release of The Video Player Sample! The Video Player Sample is an open source video player web app built using the same architecture as the 60 Minutes and RedBull.tv apps. It can be customized, extended, or just used out of the box and populated with your own content.

How it works

When a user opens the Video Player Sample web app, they can choose to watch a single video or create a playlist of videos/episodes from a list that they have uploaded and populated to the app. The Video Player Sample is configured and information about the videos is stored in JSON files (config.json and data.json respectively), both of which are located in the data directory.

Key features

  • A beautiful video watching experience, including a full screen view
  • Ability to subscribe to shows, watch episodes, create play lists
  • Support for multiple video formats depending on what the user’s browser supports (including WebM, Ogg, MP4, and even a Flash fallback)
  • A Categories page with an overview of the different shows/categories available in the app
  • Notifications of new episodes (when the app is installed via the Chrome Web Store)
  • Built in support for sharing to Google+, Twitter and Facebook
  • To ensure easy customization, all source files, including the Photoshop PSD’s, are included

How it’s built

The Google Video Application is written for the open web platform using HTML and JavaScript, broadly following the MVC (Model View Controller) pattern and structure.

Browser Support

In addition to working as an app that can be installed through the Chrome Web Store, the Video Player Web App has been tested and works in all of the modern browsers.

Try it out

You can see a demo of the video player in action in the demo app, or by Adding it to Chrome through the Chrome Web Store. To learn more about how the app works, check out the documentation.

You can grab the code from Google Code.

Enjoy!

Cross Posted at: http://google-opensource.blogspot.com/2012/01/introducing-video-player-sample.html

HTML5_Logo_512_thumb.png

HTML5 Slide Decks & Presentation Timer

2

Countdown Timer For PresentationsA couple of folks at GDD and other events have asked what I use to create my slide decks, and I figured I’d share and add a link to a little plug in that I wrote for the slide decks.

My slide decks are based on HTML5Slides, the Google HTML5 Slide Template – it’s the same one that was used at Google IO, generally by the Chrome DevRel team and lots of other folks.  It’s freely available for anyone to use, modify, fork, whatever you want, and creating the content for it is pretty easy.  One of my favorite things about using the HTML5Slides as my presentation software is that I can embed my demos straight into the slides and when you want to understand what’s going on, you can simply view source!

There are a couple of things that I think this framework is missing though.  There isn’t a way to do a presenter view and an audience view (not always necessary, but sometimes helpful to make sure you don’t forget any of the important points you want to hit).  There wasn’t an easy way to add fades when doing builds, but most importantly for me, it doesn’t have any kind of timer.   I love to talk, and can easily lose track of time when on stage.

Creating a presentation timer

This weekend, while on the flight from Brazil to Argentina, I build a little timer plug in that would help better keep track of time.  I wanted it to do three things:

  1. Tell me how many minutes until the official start time of my presentation
  2. Tell me how many minutes left until I was supposed to be done
  3. Tell me when I was done, and how many minutes over I was

Inserting a canvas element

Let’s jump right into the code! When the timer starts, it inserts a <canvas> element at the beginning of the <body> element with insertAdjacentHTML. The canvas element is going to draw our clock face and display the number of minutes left.

var insertElement = function() {
  var body = document.getElementsByTagName("body")[0];
  body.insertAdjacentHTML("afterbegin",
    '<canvas id="cClock" width="30" height="30"></canvas>');
}

Make it look pretty, and subtle

Since I wanted things to be very subtle and configurable, I used CSS to set the position to the upper left corner, and set the opacity to 0.25 to it mostly invisible so that I’ll likely be the only one who notices it. I also created a hover pseudo element so that I can hover over the element if I need to. Finally, I added a hidden class so that the element is completely invisible if the presentation ended a long time ago.

#cClock {
  position: fixed;
  top: 0px;
  left: 0px;
  opacity: 0.25;
  z-index: 1000;
}

#cClock:hover { opacity: 1.0; }

#cClock.hidden { display: none; }

Refreshing the clock

When I start the clock, it uses a setTimeout to fire at a specific interval. I decided to use setTimeout instead of setInterval because I wanted to be able to dynamically change the amount of time between refreshes, depending on where in the presentation I was. If I was close to either the start time or end time, I want the clock to update more often, where as in the middle, it can fire every minute.

Drawing the clock
Getting the clock to draw in the way I wanted took a little bit of tinkering.

  var drawClock = function(min, color) {
    var canvas = document.getElementById("cClock");
    var ctx = canvas.getContext('2d');
    ctx.clearRect(0,0,30,30);
    ctx.lineWidth = 3;
    ctx.strokeStyle = color;
    ctx.beginPath();
    ctx.arc(15, 15, 10, toRadians(-90), toRadians((((min-60)/60)*360)-90), true);
    ctx.stroke();
    ctx.fillStyle = color;
    ctx.font="10px sans-serif"
    ctx.textAlign = "center";
    ctx.textBaseline = "middle";
    ctx.fillText(min, 15, 15);
  }

Math is hard, let’s go shopping!*

drawClock(min, color) grabs the <canvas> element, and uses clearRect() to erase everything in the box. I then set the line width and color and start the drawing the circle with beginPath() and arc(). Let’s quickly start at the end, the “true” tells arc to draw the circle counterclockwise. Then, the first three parameters tell the arc to put the center at 15, 15 with a radius of 10px. The next two parameters are the angles to start drawing the circle at in radians. If you remember high school algebra (which I don’t), 0 in radians on a circle would be equivalent of 3pm on a clock, so to figure out where the top is, we need to rotate -90 degrees and then convert to radians with toRadians(-90).

To calculate the second arc position, we need to convert everything to radians again, but we also need to figure out the angle in degrees. Since I wanted the circle to become more complete the closer the time gets to zero, I started by taking the minutes and subtracting 60. Next, I needed to figure out where (in degrees) the minutes would be, to do that, I divided by 60 to get a percentage and multiplied by 360 to get the degrees along the circle.

For example to figure out where the circle should end if the minutes were 15:
toRadians((((15 – 60) / 60) * 360) – 90)
-45 / 60 = -0.75 — The arc line should continue three quarters of the way around
-0.75 * 360 = -270 — The angle in degrees that the arc should draw to
-270 – 90 = -360 — The angle in radians, and remember my comment earlier that 0 (or 360) would be at the 3 o’clock position.

Phew! When coding this up, that was the hardest part for me. I’m not exactly the biggest math fan! :) Next I called .stroke() to draw the circle, and sure enough – the circle appears! Finally, I wanted to show the number of minutes left in the center of the circle. I did that by using fillText(). To get things to fit in the circle perfectly centered, I aligned everything middle and center, and with fillText, set the base point to 15, 15 – the center of the box.

Getting the countdown timer on screen

Finally – to create an instance of the clock in a presentation, I created a JSON config object that contained the start time, and a length and a warning time, and then created an instance of the timer.

<script type="text/javascript" src="js/timer.js"></script>
<script type="text/javascript">
  window.timerConfig = window.timerConfig || {
    settings : {
      date: new Date('Sept 19 2011 16:30'),
      minutes: 45,
      warnAt: 10
    }
  };
  var t = PresentationTimer();
  t.start()
</script>

In action

I’ve iframed the timer into the window below, or you can try it here. It creates a new instance of the timer, and sets the start time to be two minutes from now, with a length of 2 minutes and a warning at 1 minute. I also made a small change to the CSS so that it’s less transparent and you can see it better.

Summary

You can see the entire timer.js file in GitHub, or even grab the whole project.. I really want to integrate this into the HTML5Slides template at some point, because I think it’s pretty useful. Feel free to grab it, use it, fork it, what ever works for you!

*Math is hard, let’s go shopping is one of my favorite Simpsons quotes.

HTML5_Logo_512.png

Showing & Hiding Panels with HTML and CSS

2

I’ve always loved web apps that use little panels that animate in from the sides as a way to show and hide content, settings, or other components of a web page. We used them a couple of times in Tweeter Fall, so I figured I’d share my way of doing them. I wanted to try doing this without any libraries to start, using only HTML5, CSS3 and as little JavaScript as possible, which will work for most browsers, but not all. Once we get it working with the latest stuff, I’ll go back and make the necessary modifications to get it to work across all browsers.

I’m using a slightly modified version of Eric Meyer’s CSS reset to ensure that everything is ready to go, you can use that or other ones as you see fit.

Let’s get started!

First, let’s create the panel where everything will live

<div class="left-panel">
</div>

and we need to apply a bit of CSS. Typically when I start working on something like this, I’ll use super ugly colors to make sure that the stuff that I’m working on sticks out, so in this case, I’m going for a nice bright red.

#left-panel {
  width: 300px;
  height: 400px;
  border: 3px solid red;
  background-color: #fcc;
}

Positioning The Panel

Great, we’ve not got our panel, though it’s not in the right place, but at least it’s on screen. Next, let’s move it to it’s default position, so that it’s minimized. To do that, I’m going to set the position to fixed – I want it so that it’s always on screen. Then, we need to move the left side of the panel into the negative space, and move the panel down the screen.

#left-panel {
  width: 300px;
  height: 400px;
  border: 5px solid red;
  background-color: #fcc;
  position: fixed;
  top: 150px;
  left: -275px;
}

Making the panel appear

To get the panel to be fully visible, we’re going to add both a hover pseudo-class as well as a show class. The pseudo-class will move it out just a bit, to add some realism and a clear indication that the panel has more to show.

#left-panel:hover {
  left: -250px;
}

#left-panel.show {
  left: 0px;
}

Adding controls to show & hide the panel

You could simply show the panel on any hover, but that always gets a little annoying to me, especially when I’m moving my mouse around quite a bit, so I’d rather not do that. Now we need to add the logic that will show and hide the panel. I’m going to use a hyperlink as the main item, and a little JavaScript to toggle the show class. The &gt; will come in handy a bit later. :)

<div id="left-panel">
  <a href="#" onclick="showLeftPanel();" class="controller">&gt;</a>
</div>

The CSS for the hyperlink is pretty simple, it absolutely positions the hyperlink in the upper right hand corner, and removes the underline from the text.

#left-panel .controller {
  position: absolute;
  right: 0px;
  top: 0px;
  text-decoration: none;
}

Hooking everything up

Finally, we need the JavaScript to toggle the CSS class. I’m using a new property off element called callList that gives me similar functionality to a lot of libraries for modifying classes on elements. classList provides the ability to add, remove or toggle classes on elements.

<script type="text/javascript">
  function showLeftPanel() {
    var elem = document.getElementById("left-panel");
    elem.classList.toggle("show");
  }
</script>

Now, when we click on the >, the panel becomes visible, and clicking on it again, makes it disappear, perfect! The panel isn’t exactly beautiful yet, and it doesn’t take advantage of any of the cool CSS3 stuff yet, so let’s add a bit of that.

Adding a bit of style

First, we’ll add some rounded corners to the top right, and bottom right, and a little bit of spacing inside the panel with a 5px padding along all the edges. Next, I’ll add the transtion properties. The first, -wekit-transition specifies that all properties that change (beyond what’s indicated in #left-panel), they’ll appear over 0.5 seconds, and will use the ease-in-out transition. In a bit, we’ll need to add the transitions for other browsers that support it – but we’re going to get it working in Chrome first.

#left-panel {
  width: 300px;
  height: 400px;
  border: 5px solid red;
  background-color: #fcc;
  position: fixed;
  top: 150px;
  left: -275px;
  border-radius: 0 1em 1em 0;
  padding: 5px;
  -webkit-transition: all 0.5s ease-in-out;
}

I also need to make a few other modifications to a couple of the other classes. I’ve changed the left on #left-panel.show to -5px. That hides the border on the left, and ensures the 5px padding on the left doesn’t look too odd. I could have modified the border to only display on three sides, but it kind of felt like more work to me. ;)

#left-panel.show {
  left: -5px;
}

Add hinting to help the user

The other thing that I want to do is make a few changes to the open/close hyperlink. Because of the rounded corners, we need to move it in a bit, but I’m also going to add transitions to it as well.

#left-panel a.controller {
  position: absolute;
  right: 5px;
  top: 5px;
  text-decoration: none;
  -webkit-transition: all 0.5s ease-in-out;
}

So why add the transitions? When the panel is closed, we’re using a > which renders like an arrow pointing to the right, to indicate the panel can be closed, we want the arrow to point to the left, so I used a transform and rotated the character by 180 degrees, and suddenly my > is a <!

#left-panel.show a.controller {
  -webkit-transform: rotate(180deg);
}

Our first working version

Alright, so here’s the final code that works in Chrome, with some nicer colors:

The HTML

<div id="left-panel">
  <a href="#" onclick="showLeftPanel();" class="controller">&gt;</a>
</div>

The CSS

#left-panel {
  width: 300px;
  height: 400px;
  border: 5px solid #555;
  background-color: #ccc;
  position: fixed;
  top: 150px;
  left: -275px;
  border-radius: 0 1em 1em 0;
  padding: 5px;
  -webkit-transition: all 0.5s ease-in-out;
}

#left-panel:hover {
  left: -250px;
}

#left-panel.show {
  left: -5px;
}

#left-panel a.controller {
  position: absolute;
  right: 5px;
  top: 5px;
  text-decoration: none;
  -webkit-transition: all 0.5s ease-in-out;
  color: black;
  font-weight: bold;
}

#left-panel.show a.controller {
  -webkit-transform: rotate(180deg);
}

And finally, the JavaScript

<script type="text/javascript">
  function showLeftPanel() {
    var elem = document.getElementById("left-panel");
    elem.classList.toggle("show");
  }
</script>

But what about other browsers?

To get this working in other browsers, we need to change our CSS a bit to add other vendor prefixed items, and we’ll need to make some changes to our JavaScript as well.

Safari

Safari doesn’t support classList’s yet, so we need to modify our JavaScript here. The absolute easiest way to make this change would be to use jQuery’s toggle function, but I want to do this without any libraries. That means we’ll have to do some feature detection to see if elem.classList is supported, if it is, we’ll use that, otherwise we’ll manually add or remove the show class.

<script type="text/javascript">
  function showLeftPanel() {
    var elem = document.getElementById("left-panel");
    if (elem.classList) {
      elem.classList.toggle("show");
    } else {
      var classes = elem.className;
      if (classes.indexOf("show") >= 0) {
        elem.className = classes.replace("show", "");
      } else {
        elem.className = classes + " show";
      }
      console.log(elem.className);
    }
  }
</script>

That’s all we need for Safari to work!

Firefox and Opera

Firefox 3.6+ and Opera 11.5+ both support classList, and previous versions will fall back to the manual method, so our JavaScript is good to go. But, the -webkit- vendor prefixed stuff needs a little love and thankfully it’s pretty easy!

In #left-panel and #left-panel a.controller add:

-moz-transition: all 0.5s ease-in-out;
-o-transition: all 0.5s ease-in-out;

In #left-panel.show a.controller add:

-moz-transform: rotate(180deg);
-o-transform: rotate(180deg);

Internet Explorer

Unfortunately, Internet Explorer (9 or the Platform Previews for 10), don’t have support for transtions yet, which mean that our panels just appear and disappear, but that’s not an awful experience, it’s just not ideal. In fact, the experience for Internet Explorer 7, 8 and 9 is identical except IE9 does have rounded corners. Just in case they add support for transitions in the future, I added the -ms- vendor prefix already.

Summary

There you go – you’ve not got a simple panel that can be displayed by the simple click of a link, and gets out of the way when not needed. It works in IE7/8/9, Chrome, Firefox, Opera and Safari and I suspect it will work in IE6, though I didn’t test that.

Give it a try at http://petelepage.com/scratch/slider-panel/

HTML5_Performance_512

TweeterFall – Web Workers

1

How often have you seen this dialog, or something similar – telling you that some scripts on a page are taking too long while your browser has become completely unresponsive. Because JavaScript runs in the same thread as the rest of the browser UI, we’re often faced with the challenge of being unable to run any complex or long running JavaScript without the fear of blocking the browser. That’s where web workers come in.

Web Workers are part of the HTML5 specification and allow you to run scripts in the background, independently of the main browser thread. This means that you can do complex calculations or run scripts that may take a while to run without yielding to keep the page responsive.  The W3C spec has some great examples of use cases and other helpful descriptions that are worth reading for deeper details.  It also notes that workers are relatively heavy weight and are not intended to be used in large numbers.

In order to to maintain thread safety, workers run in an effective sandbox, which means they don’t have access to the DOM or many other components.  To get information back and forth between the worker and the main application, we need to use the postMessage method and listen for message events.

In TweeterFall, we used a worker thread poll Twitter for new tweets and then we ‘pushed’ those new tweets to the main thread.  Let’s have a look how we used workers.

Starting & Stopping the Worker

We only ever have one working running in our application, and to maintain an easy handle to it, we defined it’s variable in the global scope.  We then had two methods that would handle how the worker would behave – startWorker() and stopWorker(). The startWorker() method takes a parameter that provides information about the username or list that we want to pull tweets from, how often we should poll Twitter and the ID of the last tweet we saw.

var myWorker;

function startWorker(settings) {
  settings.cmd = "start";
  settings.lastTweetID = lastTweetID();
  console.log("WebWorker: Starting", settings);
  myWorker = new Worker("scripts/worker.js");
  myWorker.addEventListener("message", newTweetHandler, false);
  myWorker.postMessage(settings);
}

function stopWorker() {
  if (myWorker != undefined) {
    console.log("WebWorker: Terminating");
    myWorker.terminate();
    myWorker = null;
  }
}

In our startWorker() thread, we create the new worker with myWorker = new Worker("scripts/worker.js");, and then add an event listener and listen for any messages that the worker wants to pass back to us – this is the only way we’re going to be able to communicate to the worker because it’s working off in it’s own little isolated world. At this point, the worker exists, and if it wants to tell us anything, we’re ready to listen, but now we need to tell it to do something, which is the myWorker.postMessage(settings);.

Stopping our worker is pretty similar, we check to make sure that we have a valid object, and as long as we do, .terminate() will immediately close the worker without giving it an opportunity to shut down properly or clean up after itself. This works in our case because we don’t have anything in memory and we’re not doing any calculations of any kind. If you may need to save state or want to clean up after yourself, the better way to shut down would be to send a stop message via .postMessage() and within your worker thread, shut down gracefully by calling self.close(); after completing any clean up.

The Worker Thread

Inside our worker thread, we need to set up an event listener to listen for messages from our parent thread and any other code that we want to execute.

self.addEventListener('message', function(e) {
	var data = e.data;
	switch (data.cmd) {
		case 'start':
		  self.postMessage("Worker: Starting");
			setConfig(data);
			readTweets();
			break;
		case 'stop':
		  self.postMessage("Worker: Stopping");
			self.close();
			break;
		default:
		  self.postMessage("Worker: Error - Unknown Command");
	};
}, false);

Our event listener listens for messages from the parent and will start or stop the worker as necessary. When we get the start command, we parse the settings data (setConfig), and then start reading tweets (readTweets()). For sake of readability, I’ll skip the code we used for setConfig(), but it’s easy enough to find if you want it.

function getURL() {
  var sinceID = "";
  if (parseInt(lastKnownTweetID, 10) > 0) {
    sinceID = "&since_id=" + lastKnownTweetID;
  }
  if (typeof userList === 'undefined') {
    return 'http://twitter.com/statuses/user_timeline/' + twitterUser
      + '.json?count=' + tweetCount+ '&callback=processTweets' + sinceID;
  } else {
    //For a list
    return 'http://api.twitter.com/1/' + twitterUser + '/lists/' +
      userList + '/statuses.json?callback=processTweets' + sinceID;
  }
}

function readTweets() {
  try {
    var url = getURL();
    self.postMessage("Worker: Attempting To Read Tweets From - " + url);
    importScripts(url);
  }
  catch (e) {
    self.postMessage("Worker: Error - " + e.message);
    setTimeout(readTweets, 120000);
  }
}

readTweets() is the function that does the dirty work, making a JSONP call to Twitter that requests the latest tweets. We encapsulated the URL generation into it’s own method so that we could use it even if we weren’t using workers. Because we don’t have access to the DOM, we can’t just insert a <script> block, so after getting the URL, we call importScripts(url);, which makes an synchronous call and injects the result into the worker. If we run into any problems, like over capacity, not being able to reach Twitter or anything else, it’s caught in the catch block, and we wait two minutes before trying again. Here’s the JSONP call we make http://api.twitter.com/1/petele/lists/chromedevrel-11/statuses.json?callBack=processTweets.

The request we sent to Twitter includes ?callback=processTweets in the query string which will cause processTweets() to be executed once we’ve pulled the new tweets from Twitter.

function processTweets(data) {
  var len = data.length;
  for (var i = 0; i < len; i++) {
    if (data[i].id_str >= lastKnownTweetID) {
      lastKnownTweetID = data[i].id_str;
    }
  }
  returnTweets(data);
}

function returnTweets(data) {
  if (data.length > 0) {
    self.postMessage("Worker: New Tweets - " + data.length);
    self.postMessage(data);
  } else {
    self.postMessage("Worker: New Tweets - 0");
  }
  setTimeout(readTweets, updateDelay);
}

processTweets() enumerates all of the tweets we got back to find the most recent tweet ID. That way, when we ask Twitter again later for tweets, we’re only asking for the ones that we haven’t seen. Once we’ve done that, we call returnTweets() to push the new tweets back to the application. We could have merged processTweets() and returnTweets(), and I don’t remember why I decided to do it as two separate methods. Once we’re returned the tweets via returnTweets() we use setTimeout() to call readTweets() again.

A couple of quick tips

A couple things to remember about web workers, no DOM access means that you can’t manipulate the DOM, so that means that if you want to create new UI components in threads, you can, but you need to do it in the thread, and then pass that back to the main application via postMessage(). Unfortunately, it also means that jQuery doesn’t work in threads, so generating those UI components becomes a little more complex. I’ve heard rumors of a worker safe jQuery library, but haven’t seen it yet. Hopefully! :)

The other good thing to know is that you can debug works in the Chrome Developer Tools by clicking on the Scripts tab, and scrolling down in the column on the right to Workers and clicking on the debug checkbox.

Summary

I found using workers to be really easy, and a good way of handling this. There are plenty of other good ways to use workers – and it gives us some pretty good power to be able to push complex work down to the client. Especially as browsers JavaScript engines are getting faster and faster.

Additional Resources

HTML5_Performance_512

TweeterFall – Notifications

0

In TweeterFall, when a new tweet is received, we notify the user about that tweet via desktop notifications.  If you use Chrome and Gmail, you’ve probably seen notifications pop up when you receive a new mail, or about an upcoming appointment.  The Desktop Notifications API allows script to request a small toast to appear on the desktop of the user. The contents of the toast can either be specified as iconUrl/title/text strings, or as a URL to a remote resource which contains the contents of the toast. They’re part of the WebAPI spec, though still in early draft, and so far only implemented in Chrome.

Since notifications are still something that may change, in Chrome, they’re under the webkit vendor prefix. The Chromium implementation details can be found on the Chromium site.

There are two types of notifications that you can surface, what I’ll call simple notifications like the one on the left that contains an image, a headline and some text; and HTML notifications.  HTML notifications are much more powerful because instead of sending the image, headline and text, you send it a URL, and it will display the contents of that URL. That means you can style your notification to match your applications UI and even provide interactivity through links, javascript, etc.

Let’s have a look at how we implemented new tweet notifications in TweeterFall.

Requesting Permission

When the user turns on notifications in TweeterFall, we need to check to see if we have permission to show notifications and if we don’t we need to ask for it. Desktop Notifications pop open a new window and could quickly become an easy spam target if we didn’t provide some kind of permission system. When a user grants or denies permission, they do so for the domain.

function requestPermissionIfRequired() {
  if (!hasNotificationPermission() && (window.webkitNotifications)) {
    window.webkitNotifications.requestPermission();
  }
}

In requestPermissionIfRequired(), we check to see if the browser supports notifications, and if we already have permission. If we don’t have permission, but notifications are supported, Chrome prompts the user asking for permission to provide notifications.

Checking For Permission

I also use feature detection here to check to see if notifications are supported in the browser.  We will only return true if notifications are supported and the user has already given permission to show notifications.

function hasNotificationPermission() {
  return !!(window.webkitNotifications)
    && (window.webkitNotifications.checkPermission() == 0);
}

Show the Notification

We’re finally ready to show our notification to the user.

function showNotification(pic, title, text) {
  if (hasNotificationPermission()) {
    var notificationWindow =
      window.webkitNotifications.createNotification(pic, title, text);
    notificationWindow.show();
    setTimeout(function(notWin) {
      notWin.cancel();
    }, 10000, notificationWindow);
  } else {
    console.log("showNotification: No Permission");
  }
}

The method takes three parameters, the image to use, the title and the text do display. When the function is called, it checks to see if it has permission using our previously established permission check that also encompasses feature detection, so we know we’ll be safe calling this even if the browser doesn’t support notifications. We then create the notification with window.webkitNotifications.createNotification(pic, title, text) and show it with .show().

Immediately below that, we have a setTimeout call with an anonymous function that takes one parameter (the window handle to the notification) and will hide the notification after the timeout period has expired. If we didn’t do this, the notification would remain on screen until the user clicked the close button, or closed the browser. I’ve hard coded the timeout to be 10000ms, and you can change this to suit your needs.

Summary

As you can see, showing notifications is pretty easy, check & ask for permission, and then show the notification. You can use these to let the user know when a task is complete, when there’s new information that they might be interested in and so forth. Obviously these only work when a user is on your site, but you can overcome that limitation by publishing your app in the Chrome Web Store and using background pages.

Other Resources

Be sure to check out the notification tutorial on HTML5Rocks, it covers some additional things like the events that notifications fire and using HTML notifications.

screen shot of pong

1970′s Retro Pong

3

screen shot of pongI started writing my first article for HTML5Rocks.com the other day, and as I started working on it, I wanted to do something fun with it, something that folks could play with and enjoy, but still learn something. I found a really simple Pong implementation and decided that I’d re-write it in SVG, use the HTML5 audio tag and a few other little things for some extra fun.  The article isn’t done yet, but I at least wanted to put the game up!

Play Pong

The little “boink” noise is me. But it actually presented an interesting challenge, you’ll probably notice that the boink doesn’t happen every time the ball hits the wall. When the ball hits a wall twice, in quick succession, the browser is still playing the first boink, and doesn’t start a second boink [sad trombone noise]. While it’s still in early draft, this is a really great example of something the Web Audio API will be really useful for – playing sounds in quick succession.

Thanks to Chris Wilson for suggesting a painfully obvious optimization – I had two loops running in the game world, one for the paddle and one for the ball moving.  Chris suggested one loop and tracking which key is pressed and moving both the paddle and the ball at the same time.

I’ve tested the game in Chrome 10, Firefox 4, Opera 11, Safari 5 and Internet Explorer 9 and it worked well in all of them.

The one thing I didn’t include was a scoring system, and I didn’t really see any interesting ones on the ‘net anywhere.  I think the next update I’ll include one that is timer based, but if anyone has any better suggestions, I’m open!

Wheel.png

How To: HSL and HSLA Color Models

3

HSLA is defined in the CSS3 Color Module, and is another way that designers and developers can specify the color of something via CSS.  I grew up understanding color defined by light, varying the amounts of red, green and blue result in different colors – yellow and blue make green, or if you’re in the USA, yellow and blue mean your ziploc bag is sealed. Smile

It took me a little while to wrap my head around the HSL color model because it’s quite different from the RGB model.  Instead of adding different amounts of each of those, the color is defined by three properties:

  1. Hue [0 to 360] – defines the color according to a position or degree on the color wheel.  The color wheel is split into effectively three areas, with 0° being pure red, 120° being pure green and 240° being pure blue.  Therefore, if you wanted purple, it’d be halfway between red (0 or 360) and blue (240), or 300°
    Wheel
  2. Saturation [0-100%] – defines the intensity of the color, zero, there is no instensity to the color and it shows as gray, and as the number gets bigger, the more intense the color.
  3. Lightness [0-100%] – defines how bright, or dark the color is.  50% is the true color, the larger the number, the closer you get to white, and the smaller the number, the closer you get to black.
  4. Alpha [0-1] – is the alpha transparency, and tells the browser how transparent or opaque the color should be.  The closer to 1, the more opaque, and the closer to 0, the more transparent.

Let’s See It In Action!

In the samples below, if your browser supports HSLA, you’ll see two color swatches, the first which sets the table cell background color via the HSLA property, and the second, an image of the same. If your browser doesn’t support HSLA, you’ll only see the image. Each color box is represented by the code sample below, in order from left to right.

Hue
background-color: hsla(0, 100%, 50%, 1.0);
background-color: hsla(120, 100%, 50%, 1.0);
background-color: hsla(240, 100%, 50%, 1.0);

The value for hue is specified as a number between 0 and 359, but you can go above 359, which just cycles around the circle again. For example 480 represents green, because 480 – 360 = 120.

Saturation
background-color: hsla(300, 0%, 50%, 1.0);
background-color: hsla(300, 25%, 50%, 1.0);
background-color: hsla(300, 50%, 50%, 1.0);
background-color: hsla(300, 75%, 50%, 1.0);
background-color: hsla(300, 100%, 50%, 1.0);

The saturation needs to be a percentage between 0% and 100% and defines the intensity of the color. At 0%, with no intensity, we end up with gray.

Lightness
background-color: hsla(300, 100%, 0%, 1.0);
background-color: hsla(300, 100%, 25%, 1.0);
background-color: hsla(300, 100%, 50%, 1.0);
background-color: hsla(300, 100%, 75%, 1.0);
background-color: hsla(300, 100%, 100%, 1.0);

Like the saturation attribute, the lightness attribute is a percentage between 0% and 100%. Changing the value, allows you to easily create black or white, but you can also get very subtle shades of a color, for example by setting the lightness to 98%, will result in an almost white, with a hint of color in it.

Alpha
background-color: hsla(300, 100%, 50%, 0.0);
background-color: hsla(300, 100%, 50%, 0.25);
background-color: hsla(300, 100%, 50%, 0.50);
background-color: hsla(300, 100%, 50%, 0.75);
background-color: hsla(300, 100%, 50%, 1.0);

Alpha transparency makes the object more or less transparent. This is very useful if you want to overlay something on top of another object, but still want to be able to see the object underneath. Like other places where you can specify the alpha transparency, the value is between 0 and 1, where 0 is completely transparent (effectively invisible), and 1 is completely opaque and you cannot see through it at all.

Black, Grays and White
background-color: hsla(0, 0%, 0%, 1.0);
background-color: hsla(0, 0%, 25%, 1.0);
background-color: hsla(0, 0%, 50%, 1.0);
background-color: hsla(0, 0%, 75%, 1.0);
background-color: hsla(0, 0%, 100%, 1.0);

When defining black, grays and white, the hue doesn’t matter at all. The needs to be set at 0, to indicate that there should be no indication of the color showing through. Then, by changing the lightness you can adjust the shade of black, with 0% being black, and 100% being pure white.

Using It Today

If you want to use the HSLA color model today, but still have to support browsers that don’t support the HSLA color model, the fact that CSS styles cascade (crazy I know), allow you to do support both models.

div {
 background-color: #ff00ff;
 background-color: hsla(300, 100%, 50%, 1);
}

A Quick Intro: Canvas in IE9

1

Yesterday, with the release of Internet Explorer 9 Platform Preview 3, the engineering team announced support for hardware accelerated <canvas>!  The <canvas> element is a part of the HTML5 Standards specification and allows for dynamic scriptable rendering of 2D graphics.  To use it, you put a simple <canvas> element in your HTML, which defines the drawing area, then through JavaScript, you can get the 2d context and begin dynamically drawing within that region.

Much like SVG, you can draw on the page using basic shapes, but you can also easily include rasterized images, videos and other objects.  But unlike SVG, when you draw on the page, the browser doesn’t remember any of the “drawings”.  With SVG, the “drawings” just become elements in the DOM and you can script them, change them, basically treat them like any other element.  Canvas on the other hand, doesn’t remember the state of the “drawings” so you can’t change them as easily.

Quick Code Sample

<canvas id="myCanvas" width="200" height="200"
    style="border: 1px solid black;">
      Your browser doesn’t support Canvas, sorry.
</canvas>
    var canvasElement = document.getElementById("myCanvas");
    if (canvasElement.getContext) {
        // The Context exists, so we know we have a canvas element
        // we can work with.
        var context = canvasElement.getContext("2d");
        context.fillStyle = "rgb(255,0,0)";
        context.fillRect(30, 30, 50, 50);
    }
    else {
        // There is no Context, so we can't do anything.
        // Put fall back code here.
    }

Results in…


Your browser doesn’t support Canvas, sorry.

The More Exciting Stuff…

Okay, so I can draw a little red box on a page, woop-de-doo right!  This is when I recommend you check out the IETestDrive.com website where the truly cool demos are.  Be sure when you’re looking at these demos that you take a minute to look at the source code as well – it’s pretty interesting to see how few lines of HTML are required, and in many cases how few lines of JavaScript as well!

  • Amazon Shelf – A visualization of Amazon’s top books and a way to read a bit more into them
  • FishIE Tank – Remember the Windows 7 beta fish, he’s back!
  • Mr. Potato Gun – Mr. Potato plus what looks like an air canon is never good for Mr. Potato!
  • Asteroid Belt – be sure to look at the HTML for this one, there really isn’t any!
  • DeemZoom – this is truly making web apps native!
  • Canvas Pad – An interactive canvas drawing app

Enjoy!
PEte

wlEmoticonsadsmile.png

How To: Put HTML5 <video> On A Page

7

This week has been kind of fun, we’ve been getting ready for the release of IE9 Platform Preview 3, and around 2pm PST today – it was released!  The reception has been awesome so far!  This is the build that supports <video>, <audio> and uber cool – <canvas>!

I’m going to save <canvas> for another post but wanted to get a post out tonight about some quick ways to try out the <video> tag and ways to encode H.264 video.

REMEMBER: This is still an early preview release and there may be some fun issues… For example, in my demos below, IE9 is showing both the video and the non-video content, it should only be showing the video. That’s why these are platform previews! :)

Putting <video> on your page is EASY!

    <video poster="http://www2.petelepage.com/videos/poster.jpg" src="http://www2.petelepage.com/videos/skydive.mp4" preload="none" controls style="border-radius: 10px; border: 5px solid black;">
        <div style="margin:5px;padding:5px;border:1px solid black;">
            <h2>Sad Panda: HTML5 Video Not Supported</h2>
            <p>This browser doesn't support HTML5 video with the H.264 video codec, so instead, you get the generic fall back.</p>
            <p>You could install the <a href="http://ietestdrive.com">IE9 Platform Preview</a></p>
            <p>In reality, you should probably put a Flash or Silverlight fall back here, 'cause not everyone will install a new browser just to see my/your video!</p>
        </div>
    </video>

Results In…

Sad Panda: HTML5 Video Not Supported

This browser doesn’t support HTML5 video with the H.264 video codec, so instead, you get the generic fall back.

You could install the IE9 Platform Preview

In reality, you should probably put a Flash or Silverlight fall back here, ’cause not everyone will install a new browser just to see my/your video! :)

The video above was shot while I was in Australia earlier this year, a bunch of my friends and I went sky diving just outside of Sydney to celebrate Christian’s birthday.  Eric (the second one) compiled all of our videos together into one single video, put a sound track to it, and made this great video!  It’s about 35 megs for the 5:30 minutes worth of video. It won’t start until you hit play, so it shouldn’t cause stuff to start playing without your input!

So What Does Everything Mean?

  • preload=”none” tells the browser not to preload the video file unless the user hit’s the play button – saves on bandwidth.
  • poster=”" indicated where the browser should load the poster file from, that’s the image the browser shows until you hit play, or it finishes loading the video file
  • src=”" – well, that one’s pretty obvious, it’s the video you’re trying to load
  • controls – tells the browser to show the video controls. In IE9 PP3, if the video width is less than about 400px, it won’t show the controls because the image is too small, I fought with that one for more than a few minutes! Grrr! Also, I’m using the more relaxed HTML5 syntax here, and not giving the attribute a value, you could do controls=”controls” if you want to make sure your code validates as expected.

You could also add…

  • autoplay – plays the video without the user having to click the play button.
  • loop – loops the video infinitely, or until the user hits the stop button, or navigates away from the page.
  • width or height – sets the width and height of the video element.

Encoding Videos

Getting the <video> element on your page is the easiest part! How big is the video, both from a screen size perspective, and from a file download size is the more challenging part! Is it encoded with the right encoder? Some point and shoot cameras record in H.264 mode, some (like my Canon SD780 IS) don’t Sad smile.  Encoding the video is likely the most difficult!

So how what’s the best way to resize and encode your video? There are a bunch of tools available today, some free, some paid. Sadly, the free Windows Live Movie Maker won’t encode videos with the H.264 encoder . I’m going to walk through how to do this with Expression Encoder 4 Pro. It’s part of the Expression Studio set of tools. If you’re an MSDN subscriber, you can download it as part of your MSDN subscription. Otherwise, you can download the 60 day free trial from the Expression Site, after that you’ll need to purchase a license for it.

For the rest of the walk through, I’m going to assume you’ve already got Expression Encoder 4 Pro installed, and you’ve got the video file that you want to encode ready to go.

  1. Start Expression Media Encoder, when it starts, it’ll prompt you with a “Load A New Project” dialog box.  Since we’re going to put our video online with the HTML5 video tag, not Silverlight, you want to create a new Transcoding Project.
    xmedia1
  2. Now that we’re in Expression Media Encoder, we need to import the video file that we want to encode.  Under the File menu, choose Import and find the file that you want to encode.  It’ll take a second to analyze and for Expression Encoder to read the file completely (especially if it’s a big file you want to encode).
    XE1
  3. Now we need to chose our output encoding settings, thankfully Encoder 4 Pro makes that pretty easy for us.  xmedia-encoding-settingsIn the Presets box in the left, there are a bunch of pre-configured settings you can choose from.  Video can get really big, depending on the quality and length of video, so unless I need super high quality, I typically choose one of the Encoding For Online Services profiles, and from there I usually use an standard def profile, but again, you’ll want to experiment with this depending on your needs and the bandwidth of your users and your server.  For this example, I chose the “H.264 YouTube SD” profile, which results in a file that’s about 4megs per minute of video.  Be sure to click Apply once you’ve chosen your profile to apply the settings.  You’ll notice that the area in red now defines the output format, and other information.  You can go in and expand out any of those tabs to change how the video is encoded. The video that I’m encoding is 16:9, but you’ll notice the output format is 4:3.  Because of that, Expression Encoder will automatically add the black bars above and below the video, and give me a letter box look.
  4. xmedia-outputThe other important tab you’ll want to make sure you’ve got set up how you want it is the Output tab – this is where Expression Web will save file that it just encoded. I change the output directory from my user folder to the web folder that I’m working on, and also turn off the Sub-folder by Job ID check box.  I don’t use Job ID’s, so there’s no need for that.
  5. We’re now ready to encode!  Push the Encode button on the bottom left part of the screen and Expression Encoder 4 Pro will start it’s magic…  After a couple of minutes, you’re file will be done and ready to go!

Other Resources

There’s a fantastic post on DiveIntoHTML5.org with some really great info about the video tag and how to use it that I’d highly recommend checking out at http://diveintohtml5.org/video.html.  On there, he also talks about other encoders that you can use (including some of the free ones), and also the different issues surrounding codecs.

Some Other Fun Videos

I shot these videos last January while I was in St. Maarten.  If you’re an airplane buff like I am, it’s a place you HAVE to go at some point, watching a 747-400 land or take off less than 100 feet from you is AMAZING!  I never knew a Dash-8-Q400 could give such a good exfoliation when standing behind it Smile

Sad Panda: HTML5 Video Not Supported

This browser doesn’t support HTML5 video with the H.264 video codec, so instead, you get the generic fall back.

Sad Panda: HTML5 Video Not Supported

This browser doesn’t support HTML5 video with the H.264 video codec, so instead, you get the generic fall back.

Enjoy!
PEte

PS: I tested these links and videos in Internet Explorer 9 Platform Preview 3, and Chrome 5.
[UPDATE 6/24/2010 @ 3:42PM PST] I added the preload=”none” attribute to all the videos so browsers that do support video don’t download the videos unless you ask for them.

Go to Top