Showing posts with label tutorial. Show all posts
Showing posts with label tutorial. Show all posts

The HTML 5 History API

The HTML 5 History API will allow us to update the browser history and keep the all so important functionality of the back and forward browser buttons when the site is loading content dynamically using XMLHttpRequest.

You want to use XMLHttpRequests (AJAX) to avoid unnecessary page loads, hence reducing network traffic and therefore speeding up you web-app, you probably already do this in your web-apps. However, before the advent of the HTML 5 History API there was a problem with this otherwise smart approach to building web-apps. When a page updated it's content this would not be reflected in the browser history and you had to do a lot of work to make the back and forward buttons work as expected. Thanks to the HTML 5 History API this is now much simpler. In this article I'll explain an approach to "mimicking" a common server-side approach to "dynamic" page loading using parameters in the url, while retaining the functionality of the browser history. Take a look at the demo.

What this typical AJAX demo does is pretty basic:

  • At startup it loads a page depending upon the presence of a parameter.
  • When you click a link (at the top), it fetches and swaps the content of the "content" holder of the main page.
Pushed history items
However, after having clicked the links you'll also notice that the back and forward buttons are working, without actually navigating you away from the main page, like the're integrated with the app. Also, items are "pushed" onto the browser history, making it possible to navigate directly to a previously loaded page. It's just updating the content of the content box when you click a link, not the entire page. This is what happens:
  • When a link is clicked the new content is fetched using a XMLHttpRequest.
  • The current content is replaced and the browser history is updated.
All of these operations are accomplished using only three (3) API calls:
  • The «onpopstate» event allows us to listen to events fired when the history is being navigated, like when using the back button. (see line 57'ish in the demo code for how this is handled).
  • The «replaceState» method allows us to replace the current state in the browser history. This is used to create a state when for example on initial page load.
  • The «pushState» method allows us to add things to the history stack (it's a stack, hence push and pop).
Now, this does not work in all browsers (IE..duh!) and as of writing this post still has «Working Draft» status. However, support is pretty good and when Microsoft finally adds support in IE 10, all major browsers will support the History API.

Take a look at the demo and the source code (which is heavily commented) and feel free to use the source freely.

Bye!

Accessing the gyroscope and accelerometer using JavaScript

With the advent of "mobile" devices such as the iPad, iPhone and all the gazillion Android devices, an increasing demand for browser-applications to sport the features and functionality native applications arises. In this article I'll have a quick look at one of these features, namely «device orientation». First of all, take a look at the demo. In this demo I'm using the "deviceorientation" event listener of the «window» object to listen for orientation events. Orientation events are in short events triggered when your device is twisting and turning, sort of. In my iPhone, these events originate in the accelerometer and the gyroscope. For your phone this might be different, but it doesn't matter as the API's for accessing the data are pretty much the same and part of the «DeviceOrientation Event Specification». Note that this demo is only tested on the iPhone 4, so if you have something else it might not work. Let's get to it then.
window.addEventListener('deviceorientation', orientationHandler, false);

First of all we need to add an event listener for the «device orientation» event. This event is fired by the «window» object as mentioned above. We then simply set up our event handler.

function orientationHandler(e)
{
 image.style.webkitTransform = "perspective(500) 
rotateZ("+e.alpha+"deg) 
rotateX("+e.beta+"deg) 
rotateY("+e.gamma+"deg)";
}

There are three properties of the «orientation event» we want to get at.

  • «alpha» - This is rotation about the Z axis. In other words left and right rotation.
  • «beta» - This is rotation about the X axis. This means how much you are tilting the device towards you.
  • «gamma» - This is the rotation about the Y axis, or the angle of the device screen if you may.
There are also two other properties present in iOS 5 which gives you access to the compass and it's accuracy, but those are not used in this example.

The «perspective(500)» transform simply defines how "far away" from the object you are when it's rotated, or the depth if you like. Since the properties of the «device orientation» event correlates to the values handled by the CSS transform properties, no calculation is needed. Try it out! (Should work on iPhone 4 and iPad 2)

References:

HTML 5 Offline data storage

One of the most anticipated features of HTML 5 and all it's consequential technologies and APIs are the «offline storage» APIs. In this post I'll take a "real world" approach to using the HTML 5 Web-Database and the «HTML 5 Offline application cache». I will take you through an example where a complete elephant gets stored on your computer. That's right! A pink one as well! The point of this demo is to investigate how to store both static data as well as dynamic data which might not be known at design time. For this occasion I have created a demo which you are free to download and inspect. It is fully commented and somewhat verbose for easier reading. What this application does in essence is to store a HTML and a JavaScript file on your computer, then it will go on to store a picture (which could be dynamic data) in a local database, hence making the application usable when not online. Let's have a look!

So, our goal is to store both static data and some dynamic data. To achieve this we'll need to use two approaches as mentioned above. The first one, called «HTML 5 Offline Application Storage» is almost automatic once you have it configured. We will utilize this method to store our main JavaScript file so that it will work when you're not online. Cool!
This approach uses a simple text file, called a «manifest file» which tells the browser which data to store locally. In order for this file to be interpreted by the browser correctly you'll need to (1) configure your web-server to serve this file with the «text/cache-manifest» mime-type. It doesn't matter what kind of extension you use, but I prefer either «.manifest» or «.cache». Now that thats out of the way we need to create the «manifest file». Mine looks something like this.

CACHE MANIFEST
# Cache manifest version 1.0.5
# If you change the version number in this comment,
# the cache manifest is no longer byte-for-byte
# identical.

main.js

NETWORK:
# All URLs that start with the following lines
# are whitelisted.

http://web.kinderas.com/

The first line MUST be the text «CACHE MANIFEST». After that you'll go on to specify the files you'll like to be cached. Here you'll put stuff like JavaScript files, HTML pages, CSS files and so on. Mine only has the one «main.js». Note that you do NOT need to specify the HTML file which declares the manifest file. This will typically be your «index.html» file or something like that. More on that later. The next section is the «NETWORK:» section. In this section you specify a "white list" containing URL's from where your application is allowed to get it's data. If you don't specify this your app will not download any data, not from the server it's hosted on or from anywhere else. I have specified my own domain since this is where the elephant is hosted.
You declare the manifest file in your HTML file like so:
<html manifest="cache.manifest">
That is it for the manifest file actually. If you are simply going to host a static site, a game or something like that, this will work just file as is. Note that to update your files, you do need to make a change in the manifest file itself, like incrementing the version number.

Next we need to add some sexy JavaScript in order to make the pink elephant available for your viewing pleasure in locations the WiFi gods have forsaken. There are three main steps to this: (1) Opening and creating the database and the table if it's not already present. (2) Reading the image from the database or saving it to the database if it's not already in there. (3) Displaying the image. I will not be explaining every line of the code in this post, you'd rather take a look at the JavaScript file and read the comments. However I will discuss some of the more important points briefly.
Not all browsers will support the HTML 5 database APIs, so we need to check for this before we can do anything. To do this we check for the existence of the «openDatabase» method on the «window» object, like so:

if(!window.openDatabase){
// No support for HTML 5 db
return;
}

This will detect if the browser has support for the methods we need. If not, give the user a message or some alternative content.
Then, to open / create the database we would we simply write:
db = openDatabase('testdb','1.0','Offline Elephant DB',1024*1024);
We have just created a 1MB database or opened one if it already existed. Now it's ready to execute SQL queries using transactions.

var sql = 'CREATE TABLE IF NOT EXISTS offline_image (id INTEGER ....);';
db.transaction(
 function(transaction){
  transaction.executeSql(sql,[],
  function(transaction, result){
   //The table was created
  },
  errorHandler);
 }
);

The database table has now been created if it wasn't already there. We now need to check if there is an image already saved in the database, this happens on line 56 in the «readImage()» function. If there is an image with the matching filename saved, we use that, if not we go on to loading and serializing the image, as follows.

var canvas = document.createElement('canvas');
var ctx    = canvas.getContext('2d');
var img    = document.createElement('img'); 
img.onload = function(){
 canvas.width  = img.width;
 canvas.height = img.height;
 ctx.drawImage(img,0,0,img.width,img.height);
 var base64Image = canvas.toDataURL();
 showImage(base64Image);  
}
img.src = sImgURL;

To be able to save the image we need to create a text version of it's data. We can accomplish this by loading the image and then rendering it in a canvas element. The Canvas element has a method called «toDataURL» which will create a base64 representation of the Canvas content. Base64 images, also referred to as data urls can easily be saved to the database. Base64 data can also be read directly by the «img» element, so there is no need to decode the base64 string again once it's encoded. But, do note that the canvas element will give you the png base64 version of the image, and it's quite a bit larger than the original binary file.

That's the gist of it, but you do need to take a look at the demo and the JavaScript in order to really understand what it going on here. Once you get the hang of it, this is a really powerful approach to making web-applications much more accessible and more interesting.

Further reading: