Friday, November 25, 2011

Indexed DB: Reading data

Finally we get to the part where we can see the results of our Indexed DB tutorial. For the last few moths we have been structuring our database, adding data and now I’ll show how you can read data from an Indexed DB. For this we have 2 approaches. First one is retrieving a single record and the other way is retrieving a collection of records by a cursor.

In this post I’ll handle the retrieving of a single record. A post about retrieving data with a cursor will appear in the near future.

Retrieving data from an object store

In the IObjectStore interface we have an get method to retrieve data. This method must be provided with a key we want to search on. The key parameter can be a valid key or a key range. In case you don’t provide a valid key, a DATA_ERR exception will be thrown.

In the first situation a record of the object store will be retrieved where the given key is the same as the key of the key/value pair. In the other situation, the first record will be retrieved that matches one of the keys defined in the key range. If no record gets found, the result will be undefined. If you are using the Indexed DB prototype on IE 9, you’ll get an “Object with specified key not found.” error in stead of an result.

Time for some code:

When we want to read data, we need to create a transaction. This we do on the same way as for adding data. The only difference is we can use the IDBTransaction.READ_ONLY mode. This is the type that will be used as default when we create a transaction.

   1: var txn = dbconnection.transaction([“ObjectStoreName”]);
   2: var objectStore = txn.objectStore(“ObjectStoreName”);

The result of the get method is a IDBrequest object. When this is successful, the record is added to the result.



   1: var getReq = store.get(key);
   2: getReq.onsuccess = function(event) { 
   3:     var result;
   4:     // IE 9 implementation
   5:     if(event.result){
   6:         result = event.result;
   7:     }
   8:     // IE 10, Chrome and Firefox implementation
   9:     else if (getReq.result){
  10:         result = getReq.result;
  11:     }
  12:     // Code to present the result on your screen
  13: };

Retrieving data from an Index


In a previous post I have been talking about Indexes. Indexes make it possible to look up data from the object store by fields of the value object. By example: we have an object store person. In this object store we store persons. A person object has a first name and a last name field. By creating an index with a key path “last name”, we make it possible to retrieve data from the object store by providing the last name of the person.


In the IDBIndex interface we have the get method to retrieve a record from the object store, and the GetKey method to retrieve the key of the record from the object store. In both cases a key must be provided. This key parameter can be a valid key or a key range. For the rest every thing works the same as for retrieving data from an object store.


One think you need to keep in mind. In the Indexed DB prototype on IE9 the get and getKey method work different. In this case the getKey method retrieves the data and the get method the key of the record.



   1: var txn = dbconnection.transaction([“ObjectStoreName”]);
   2: var objectStore = txn.objectStore(“ObjectStoreName”);
   3: var index = store.index(“IndexName”);
   4: var getReq = index.getKey(key);
   5:  
   6: getReq.onsuccess = function(event) { 
   7:     var result;
   8:     if(event.result){
   9:         result = event.result;
  10:     }
  11:     else{
  12:         result = getReq.result
  13:     }
  14:     // Code to present the result on your screen
  15: };

Wednesday, November 9, 2011

Indexed DB: Manipulating data

The first thing we need to do when we want to read data, is to make sure we have data available in our database. So this post will handle inserting and updating data into the database.

For inserting data we have 2 possibilities: we have an add and a put method available. Both methods take the same parameters, but there is a slight difference between them. When we use the add method, we need to be sure that no other object with the same key is already added in the database. If it does, an constraint error (CONSTRAINT_ERR) will occur. So the add method will only be used when we want to add data that won’t be overwritten when it is already present with the same key in the database.

The put method we will usually use when we want to update data. If the data isn’t present yet with the same key, the data will be inserted. If you want some more information about the steps for storing a record into an object store, you can find this here on the W3C specs site.

Make sure when you are starting a new transaction to manipulate data, you will use a read_write transaction. Otherwise you will receive an READ_ONLY_ERR when calling the methods.

The put and the add method are both available in the IObjectStore interface. This means once we have created the transaction where we will work in, we need to retrieve the object store we want to work on. We do this by calling the ObjectStore method on the transaction. The only thing we need to pass is the name of the object store.
var txn = dbconnection.transaction([“ObjectStoreName”]
                                                 , IDBTransaction.READ_WRITE);
var objectStore = txn.objectStore(“ObjectStoreName”);
Once we have the object store object, we can start adding data to it. The result of the add operation is an IDBRequest object. This means the onsuccess will be called when the operation was successful and an onerror will be called when something went wrong.
When the onsuccess function gets called, the result of this action will be the key of the object in the object store
var addresult = objectStore.add(data);
addresult.onsuccess = function (event) {
      // Adding data is successful
      // Commit the transaction when using IE9
      var key;

      // IE 9 implementation
      if(event.result){
            key = event.result
      }
      // IE 10, Chrome and Firefox implementation
      else if (addresult.result){
            key = addresult.result;
      }
};
addresult.onerror = function (event) {
      // Handle the error
}
If we use a put for adding or changing data, we get the same structure only we will use the put method instead.
var putresult = objectStore.put(data);
putresult.onsuccess = function (event) {
      // Putting data is successful
      // Commit the transaction when using IE9
};
putresult.onerror = function (event) {
      // Handle the error
}
Now that we have added some data to our database, we can start retrieving it and present it to our users…

Thursday, November 3, 2011

Indexed DB: Deleting your database

In a previous post I have been talking about creating and deleting a database. The creation/opening of a database is supported in all the major browsers, but deleting isn’t. Only Internet Explorer currently supports deleting your database trough the IDBFactory interface.

Because we have been playing for a while now, it’s interesting we can delete our database so we can rebuild it from scratch without having to use a new name for our database. I’m only used to work on windows machines, so the solution I will propose will probably only work under windows. If you are using an other operating system, it will work on the same way, but you’ll have to look where you can find the databases.

Firefox

The Indexed DB databases of Firefox can be found on the following location:

<location of the windows user profiles>\<account name>\AppData\Roaming\
Mozilla\Firefox\Profiles\<some random characters>.default\IndexedDB

In my case this is:

C:\Users\kristof\AppData\Roaming\Mozilla\Firefox\Profiles\ tvv6t475.default\indexedDB

You will find a folder with your current domain. Delete these folder, and you can start all over again. In my case, I get the following:

http+++localhost+50350

I have to notice that the AppData folder is a hidden folder, so it is possible you won’t see it when going to your user profile directory.

Chrome

The Indexed DB databases of Chrome can be found on the following location:

<location of the windows user profiles>\<account name>\AppData\Local\Google\
Chrome\User Data\Default\IndexedDB

In my case this is:

C:\Users\kristof\AppData\Local\Google\Chrome\User Data\Default\IndexedDB

You will find a folder and a file with your current domain. Delete these files, and you can start all over again.

In my case I get the following:

folder: http_localhost_50350.indexeddb.leveldb
file:     http_localhost_50350.indexeddb

Wednesday, November 2, 2011

Indexed DB: Transactions

Today, I’ll handle the transaction subject. As said in previous posts, every request made to the database needs to be done in a transaction. So for every read or write request we need to create a new transaction. There for we need a database connection and 2 argument that we will pass to the transaction method.

The first argument will define the scope of the transaction. Here we pass all the object stores we want to use during the transaction. We do this by passing the object store names in an array. Providing an empty array will allow to use all available object stores in the database.

The second argument is the mode we want to use to access the data. This is an optional parameter and if not provided the transaction will be created read only by default. If you want to manipulate data, you’ll need to pass IDBTransaction.READ_WRITE. There is also a third mode, CHANGE_VERSION, but this type of transaction can only be created in the setVersion method. More about this method can be found in my post about Indexed DB: Defining the database structure

var txn = dbconnection.transaction([], IDBTransaction.READ_WRITE);

txn.oncomplete = function () {
     // Transaction successful
};
txn.onabort = function () {
    // Code to handle the abort of the transaction
};
txn.onerror = function () {
// Code to handle the error
};

For a transaction we have 3 possible outcomes. The first one is that the transaction is committed and so got completed. This function will be called if the transaction was successful and in the case we were reading data, we can here write the code to show the retrieved data it in the browser. Keep in mind that a transaction in the Indexed DB API is committed by default, but in IE9 you still need to do this manually.

The onabort function will be called when we manually call the abort function on the transaction object. This means the transaction must do a rollback.

The last one will handle all the errors that can occur within the transaction, this will also mean that the transaction must rollback.

Now that we know how to create a transaction, we can start retrieving and manipulating data from our database. This will be the next subject of my future posts.

Wednesday, October 26, 2011

HTML5: A complete overview

The last two days I have been giving a presentation about the capabilities of HTML5. For all the people who weren’t able to follow these sessions, I have put my slides on Slideshare.

I noticed that it is hard to find out what all the functionalities are of HTML5, that is why I made a little overview. It’s possible it will be out dated soon, but this is because HTML5 is a dynamic standard that still keeps growing and the major browser are still bringing up proposals for new features. Enjoy the slides…

Tuesday, October 25, 2011

Indexed DB: Defining the database structure

In previous post I have been talking about the basic concepts in the Indexed DB and how you can open/create a database and a database connection. Today I will tell you how you can construct your own database structure. This includes defining the object store where we can store our objects and defining indexes. These indexes will be used when searching into the objects we store in our database.

version_change transaction

There exists only one way to define your object stores and indexes, and this is in a VERSION_CHANGE transaction. We can start this transaction by calling the setVersion method on the database connection. When a database is initially created, the version of the database is an empty string. By passing a string as version to the setVersion method, we add object stores and indexes. This we do by defining the onsuccess event. We can also provide error handeling trough the onerror event.

var dbreq = dbConnection.setVersion(version);
dbreq.onsuccess = function (event) {
      // Here we put code to create object stores or indexes
}

dbreq.onerror = function (event) {
      // Here we put code to handle an error while changing the version
}

dbreq.onabort = function (event) {
      // Here we put code to handle an abort when changing the database version
}

If we are using the IE 9 Indexed DB prototype, we need to commit the transaction. In all other browsers this is not necessary because the implementation of Indexed DB determines that every transaction is committed by default when closed. If a transaction should be aborted you have to do this explicitly.

dbreq.onsuccess = function (event) {
       var txn;
       if (event.result) {
             txn = event.result;
       }
       // Here we put code to create object stores or indexes
      
       if(typeof(txn.commit) != "undefined")
       {
            txn.commit();
       }
}

Because a database can’t have multiple versions at one time, the only way you can change the version is by closing all other connections to the database. This also means no new connections can’t be opened until the VERSION_CHANGE transaction is completed. A blocked event will be raised when a connection to the database is still open when changing the version.

dbreq.onblocked = function (event) {
// Here we put code to handle an abort when changing the database version
}

Creating an objectStore

Once we started the VERSION_CHANGE transaction, we can start adding or deleting object stores. We can do this by calling the createObjectStore method. As first parameter we need to pass the name of the object store. Optionally you can can add two extra parameters. The first one is JSON object with two fields. The first field is a keyPath, when this is provided, the key of the object store will be determined by the field that has the name given in the string of the key path. The second field determines if the object store should have a key generator.

The last parameter we pass is the same as the autoIncrement field in the second parameter. We do this to enable the object store to have a key generator in the IE9 prototype. When using Firefox, Chrome and IE 10, you don’t need to pass this parameter.

The following combinations of a KeyPath and autoIncrement are possible:

Key path Auto increment Description
Empty False This object store can hold any kind of value, even primitive values like numbers and strings. You must supply a separate key argument whenever you want to add a new value to the object store.
Provided False This object store can only hold JavaScript objects. The objects must have a property with the same name as the key path.
Empty True This object store can hold any kind of value. The key is generated for you automatically, or you can supply a separate key argument if you want to use a specific key.
Provided True This object store can only hold JavaScript objects. Usually a key is generated and the value of the generated key is stored in the object in a property with the same name as the key path. However, if such a property already exists, the value of that property is used as key rather than generating a new key.

dbConnection.createObjectStore("ObjectStoreName"
                                              , { "keyPath": "keyPath"
                                                , "autoIncrement": true }
                                              , true);

removing an object store

When we want to remove an object store, the only thing we need to pass is the name of the object store we want to remove.

dbConnection.deleteObjectStore("ObjectStoreName");

Creating an INDEX

Once we created our object store, we can add indexes to it. These indexes are object stores as well, but the key of these key/value pairs is the key path of the index. This means that in this object store that multiple keys with the same value are allowed. When we want to create an index we need to provide a name and a key path for them. Optionally we can provide a JSON object with a unique and multiplerow field.

Field Description Support
unique A boolean value indicating whether the index allows duplicate values. If this attribute is "true", duplicate values are not allowed. Duplicate values are allowed when this attribute is "false" (the default value). This means when you add an object to an object store where an index with a unique value on "true". You will get an exception when you add an object with a duplicate value in the field of the key path of the index. IE 10
FF
Chrome
multiplerow A boolean value that describes determines the results when multiple rows in the object store match individual key values. When this happens, the resulting object is an array. If this parameter is "true", the resulting array contains a single item; the key of the item contains an array of the matching values. When this parameter is "false" (the default), the result array contains one item for each item that matches the key value. IE 10

store.createIndex("IndexName"
                         , "keyPath"
                         , { unique: false });

If we want to create an index in IE 9 Indexed DB prototype, we need to pass the boolean value for the uniqueness as parameter and not as a JSON object.

store.createIndex("IndexName"
, "keyPath"
, false);

Deleting an index

The last action we can do in the VERSION_CHANGE event is deleting an existing index. We can do this by passing the name of the index we want to delete.

store.deleteIndex("IndexName");

Sunday, October 2, 2011

Indexed DB: Creating, opening and deleting a database

In my last post I provided some more information about the structure of the Indexed DB database. Today, I will dive into code and tell you how to create, open and delete a database. There are some small differences between the browsers, but I will handle that at the specific parts of code.

The code I will show will be the Asynchronous implementation of the API. In my previous post I have said no browser does implement the synchronous API, but I was wrong. The IE 10 Preview 3 also implements the Synchronous implementation, but you should only use it in combination with web workers, because it freezes the UI if you don’t.

Initializing the Indexed DB API

First things first: the Indexed DB API is still in draft, so this means the unified Indexed DB property on the window element isn’t implemented yet. Every browser uses his on prefix to use the API, but we can assign this to the Indexed DB property. This gives us a way to us the Indexed DB on the same way.

Initializing the Firefox implementation

if (window.mozIndexedDB) {
            window.indexedDB = window.mozIndexedDB;
            window.IDBKeyRange = window.IDBKeyRange;
            window.IDBTransaction = window.IDBTransaction;
}

Initializing the Chrome implementation

if (window.webkitIndexedDB) {
            window.indexedDB = window.webkitIndexedDB;
            window.IDBKeyRange = window.webkitIDBKeyRange;
            window.IDBTransaction = window.webkitIDBTransaction;
}

Initializing the IE 10 Preview 3 implementation (You’ll need to be running the Windows 8 Developer Preview to run this)

if (window.msIndexedDB) {
            window.indexedDB = window.msIndexedDB;
}

Initializing the IE prototype implementation

if (navigator.appName == 'Microsoft Internet Explorer') {
            window.indexedDB = new ActiveXObject("SQLCE.Factory.4.0");
            window.indexedDBSync = new ActiveXObject("SQLCE.FactorySync.4.0");

            if (window.JSON) {
                window.indexedDB.json = window.JSON;
                window.indexedDBSync.json = window.JSON;
            } else {
                var jsonObject = {
                    parse: function (txt) {
                        if (txt === "[]") return [];
                        if (txt === "{}") return {};
                        throw { message: "Unrecognized JSON to parse: " + txt };
                    }
                };
                window.indexedDB.json = jsonObject;
                window.indexedDBSync.json = jsonObject;

            }

            // Add some interface-level constants and methods.
            window.IDBDatabaseException = {
                UNKNOWN_ERR: 0,
                NON_TRANSIENT_ERR: 1,
                NOT_FOUND_ERR: 2,
                CONSTRAINT_ERR: 3,
                DATA_ERR: 4,
                NOT_ALLOWED_ERR: 5,
                SERIAL_ERR: 11,
                RECOVERABLE_ERR: 21,
                TRANSIENT_ERR: 31,
                TIMEOUT_ERR: 32,
                DEADLOCK_ERR: 33
            };

            window.IDBKeyRange = {
                SINGLE: 0,
                LEFT_OPEN: 1,
                RIGHT_OPEN: 2,
                LEFT_BOUND: 4,
                RIGHT_BOUND: 8
            };

            window.IDBRequest = {
                INITIAL: 0,
                LOADING: 1,
                DONE: 2
            };

            window.IDBTransaction = {
                READ_ONLY: 0,
                READ_WRITE: 1,
                VERSION_CHANGE: 2
            };

            window.IDBKeyRange.only = function (value) {
                return window.indexedDB.range.only(value);
            };

            window.IDBKeyRange.leftBound = function (bound, open) {
                return window.indexedDB.range.leftBound(bound, open);
            };

            window.IDBKeyRange.rightBound = function (bound, open) {
                return window.indexedDB.range.rightBound(bound, open);
            };

            window.IDBKeyRange.bound = function (left, right, openLeft, openRight) {
                return window.indexedDB.range.bound(left, right, openLeft, openRight);
            };
}

Creating and opening a database

Once we have our Indexed DB initialized, we can start the real thing. Creating a database. There is no specific method to create a new database, but when we call the open method, a database will be created if it doesn’t exists. After that a connection to the database will be opened. To open or create a database, the only thing you need is a name.

var dbreq = window.indexedDB.open(“database name”);

dbreq.onsuccess = function (event) {
        var dbConnection;
        // IE prototype Implementation
        if (event.result) {
                dbConnection = event.result;
        }
        //IE 10 Preview 3, Firefox & Chrome implementation
        else {
                dbConnection = dbreq.result;
        }
}

dbreq.onerror = function (event) {
       // Log or show the error message
}

Calling the open method, will return an IDBRequest object. On this object we can attach an onerror function and an onsuccess function. The onerror event will provide handling the error returned by the open function, here you can provide logging or error handling. In the onsuccess event, the database connection will be opened. We can now start using the database connection.

As you can see in code, IE prototype implementation is handling this on an other way then IE 10 Preview 3, Firefox and Chrome. In the IE prototype implementation we get the result (the database connection) out the parameter that is passed trough with the onsuccess function. For IE 10 Preview 3, Firefox and Chrome, we get the result from the IDBRequest object. This is the implementation that was defined by the W3C.

Deleting a database

Deleting the database will happen almost the same way as opening a database. You provide the name of the database you want to delete, and the database will get deleted. The error event will only be called when something goes wrong. Providing a database name that doesn’t exists, will not result in an error and the onsuccess function will get called.

var dbreq = window.indexedDB.deleteDatabase(“database name”);
        dbreq.onsuccess = function (event) {
             // Database deleted
        }
        dbreq.onerror = function (event) {
            // Log or show the error message
        }

Now we can create, open and delete a database. In one of my next posts, I will show you how you can create/change your database structure.

Sunday, September 25, 2011

Indexed DB: The basics

The Indexed DB API has the purpose to provide storage for large numbers of objects. This is necessary to satisfy offline data requirements. The web storage API is useful for storing data as key-value pairs, but has some limitations. It only has 5MB of storage space available, it does not provide in-order retrieval of keys, efficient searching over values, or storage of duplicate values for a key.

The Indexed DB specification provides an advanced key-value data management. It does this by using a transactional database to store their keys and corresponding values (more than one value for 1 key is allowed) and providing a means of traversing keys in a deterministic order.

The Indexed DB specification declares 2 different API’s. You have an asynchronous that is currently implemented by the most modern browsers (IE 10, Chrome 11.0, Firefox 4), and you have an synchronous API. This last one isn’t yet implemented  in any browser. The synchronous Indexed DB API methods provide a blocking access pattern to Indexed DB databases. Since they block the calling thread they are only available from workers. But first some definitions

Database

For every origin you can create an infinite number of databases. The only thing you need to create a database is an unique name. A database also has a version, this version will be used to determine the structure of the database. When a database is created for the first time, the version will be an empty string. Each database can only have one version at a time, this means the database can’t exist in multiple versions at once.

Object store

A database compromises one or more object stores. These object stores hold the data that is stored into the database. This data is stored as a list of records. Each record exists of a key and a value. The keys are sorted in ascending order by default and a key can never be exist multiple times within one object store.

Every object store has a name that is unique within the database. Optionally it has an key generator and a key path. A key generator generates a monotonically increasing numbers every time a key is needed. When a key path is given, the key path will be used as key. The last possibility to provide a key, is by explicitly specifying it when storing the value.

The set of object stores can be changed, but it can only change by using the Version_change transaction. This transaction will change the version of the database and change the set of object stores as you defined.

key path

A key path is a DOMstring and defines how we can extract the key from the value. For example if you are using JSON, the DOMstring will be the name of your property.

Keys

To enable the most efficiently manner to retrieve records stored in the database, each record is organized by it’s key. A valid key can be one of the following types:

  • Array of JS objects
  • A DOMstring
  • A data
  • and a float

Index

An index allows looking up records in a object store using properties of the values in the object stores records. It is a specialized key-value storage that has a referenced object store. The index has a list of records which hold the data stored in the index. The records in an index are automatically populated whenever records in the referenced object store are added, update or deleted. It’s possible that multiple indexes are referencing to the same object store, so when the object store changes all the indexes get updated.

The keys for the index are derived from the referenced object store's values using a key path. The index also contains a unique flag. When it’s true it will enforce that the key will be unique over all the records in the object store.

Transactions

A transaction will be used to interact with the database, it represents an atomic and durable set of data access and mutation operations. All data that is read or written to the database will happen using an transaction. To create a transaction, a connection is needed. Each transaction has a mode which declares what type of interactions are allowed within the transaction. This mode is set when creating the transaction and will remain the same for the lifetime of the transaction. It also has as scope, this declares the object stores that can be affected within the transaction. An active flag determines if new request can be added. And with the request list you get an overview of all the requests that have been placed against the transaction.

The available modes are:

  • READ_ONLY
  • READ_WRITE
  • VERSION_CHANGE

Request

Every read or write operation on the database is done by a request. A request exists out of a flag done which indicates if the request is completed and  a source object. If the request is completed the result or error code become accessible.

Cursor

A cursor is a mechanism to iterate over multiple records in the database. It compromises a range of records in either an index or a object store. The source of the cursor contains the index or object store we want to iterate. The cursor also has a position which indicates the object it is currently working with and a direction where to the cursor is moving. A position can’t be seen as an index, but rather as a key of the previously returned record. The key and value property of the cursor contain the key and value the cursor is currently holding.

This was a brief introduction to the Indexed DB API, more information about Indexed DB can be found here. In a future post I will handle about creating a database and his structure.

Thursday, September 15, 2011

New features of IE10

With the release of the Windows 8 Developer preview on Wednesday at the BUILD conference, the third preview of IE10 was released. I had never expected that this would bring that many new features. Some of the features were already available at the html5labs, but needed sever installations to get it work. But from now all these features are released in the new preview of IE10. Even features who weren't available at html5labs are added.

From now it will be possible to build web applications that will work online as well offline. The API for this is the HTML Application Cache. In a manifest file you describe all the resources (HTML files, JS files, CSS files, Images, …) you need to let your application work offline. For storing your data offline, we now have 2 possibilities. We have the Local storage we can use to save key/value pairs. This is handy if we save small amounts of data and do not need a structured way to be saved or need to query on data in the value. The second possibility is the use of IndexedDB. This is an offline database that runs in the client. You can’t use SQL to query on it, but it has a set of interfaces that provide methods to create, read, update and delete your data and structure.

Another feature that was available at html5labs was web sockets. Web sockets enable you to use TCP to communicate between your browser and the webserver. On this way we can save a lot of traffic when build applications who need frequent polling to get there data. When using HTTP we are always sending an HTTP header. In a web socket message we send only add 0x00 at the begin of the message and 0xFF at the end.

With the history API we will be able to manipulate the URL without having a page refresh or navigation. This way we can use AJAX to give the user a fluent way to work with your application (without page refresh) and adjust the URL at the same time. This enables the user to move back and forward in your web application who uses AJAX.

To improve the performance of your web applications, IE added the possibility to run scripts Asynchronously and the use of Web workers to make your web application multithreaded in your browser.

The File API provides the web developers a secure way to access files on the local machine. This way the user can manipulate local files without having to upload it to the server.

Other improvements are:

  • Rich Visual Effects: CSS Text Shadow, CSS 3D Transforms, CSS3 Transitions and Animations, CSS3 Gradient, SVG Filter Effects
  • Sophisticated Page Layouts: CSS3 for publication quality page layouts and application UI (CSS3 grid, flexbox, multi-column, positioned floats, regions, and hyphenation), HTML5 Forms, input controls, and validation
  • Enhanced Web Programming Model: Better offline applications through local storage with IndexedDB and the HTML5 Application Cache; Web Sockets, HTML5 History, Async scripts, HTML5 File APIs, HTML5 Drag-drop, HTML5 Sandboxing, Web workers, ES5 Strict mode support.

Saturday, September 10, 2011

Getting started with IndexedDB on IE

I have been playing with HTML5 for a while, and more and more I’m seeing the advantage of building applications in HTML 5. In particular applications that will run online and offline as well. One of the things we need for this is storage on the client side. For now most browsers only support WebStorage for this. The disadvantage of Webstorage is the maximum of 5mb of data and every thing is stored in KeyValue pairs, which make searching in the data harder.

Some browsers are now experimenting with the IndexedDB spec. A description of the spec can be found here. In FireFox en Chrome the IndexedDB API is all ready build-in. Not in the window.IndexedDB, but in window.mozIndexedDB for FireFox and window.webkitIndexedDB for Chrome. For internet explorer, you can use an experimental API that you can find on html5labs.

To get started with IndexedDB for Firefox and Chrome we don’t need to install something, to get started with IndexedDB for Internet explorer, we need to install the IndexedDB prototype. The files we need to install can be found here. Once the file is downloaded, we unpack the zip-file.

The first thing we need to do is run the vcredist_x86.exe which can be found in the map we just unpacked. Once that is installed, we need to install the sqlcejse40.dll:

    1. Open the command prompt as administrator
    2. Navigate with the cd command to the unpacked zip-file
    3. Run the following command:
      regsvr32.exe sqlcejse40.dll

Once we pasted these steps, we should be able to open and use the demo included in the zip-file. But beware, you need to run you Internet Explorer with administrator right, otherwise you will get the following error in the error textbox:

6 - Error 0x80040E09, minor 25039 (0x000061CF).

Now when everything is properly installed, we can start to develop. But, this will be content of a next blogpost.

Friday, September 2, 2011

Configuring webserver for html5 video

When u are using HTML 5.0 video on your website, you need to remember that your webserver is configured to send the correct MIME–type with your file. If you don’t the browsers won’t recognize it and the video won’t play. You will see an X appearing on your video, and the video will not start playing when you click on it.

If u are using an Apache webserver, you can use the AddType directive in your side-wide httpd.conf or in the .htaccess file that is located in your directory where your videos are stored.

The following line should be added in that case:

AddType video/ogg .ogv
AddType video/mp4 .mp4
AddType video/webm .webm

When u are using an IIS server there are 2 possibilities. You can configure it on your IIS server, or you can add the MIME–types in your Web.config.

When you want to configure the MIME–types on your IIS server there are some differences between the versions.

Configuring MIME-Type for IIS 6.0
Configureer MIME-type for IIS 7.0

The other possibility is using your Web.config. This is ideal for developers who are use IIS Express and don’t have a full instance of IIS running. But beware, this is only supported when you are using IIS 7.0 or higher. The following section needs to be added in your configuration file:

<configuration>
  <system.webServer>
    <staticContent>
      <mimeMap fileExtension=".mp4" mimeType="video/mp4" />
      <mimeMap fileExtension=".webm" mimeType="video/webm" />
      <mimeMap fileExtension=".ogv" mimeType="video/ogv" />
    </staticContent>
  </system.webServer>
</configuration>

Friday, August 26, 2011

Drawing with the canvas element

Yesterday i followed a mswebcafe workshop about the canvas element. In this session we got a closer look at the possibilities of the canvas element. At the end of the session we got the possibility show what we had learned that day. I choose to create a canvas where you could draw lines with your cursor. Afterwards several people asked me to share my code, and what is a better way than make a blog post about it.

To accomplish this the first thing we need to do is enable our webpage to render HTML 5. We do this by setting the document type to:

<!DOCTYPE html>

The next thing we need to do is adding our canvas element. Everything we put between the canvas element will be shown on browsers that don’t support the canvas element.

<canvas id="canvas" width="500" height="500">You’re browser doesn’t support the canvas element</canvas>

Everything that is left now, will be accomplished trough JS. First thing first if we want to do something with the canvas element, we have to retrieve it as it’s context.

var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");

In the startDraw function, the first thing we will do is determine the point from where we want to start drawing. Next, we will add a new event handler on the mousemove event so we can follow the cursor en draw where ever he goes.

function startDraw(e) {
      startpoint = getCursorPosition(e);
      canvas.addEventListener("mousemove", drawIt, false);
}

Via the getCursorPosition methode we can determine what the current mouse position is. The way to do this is:

function getCursorPosition(e) {
      var x;
      var y;
      if (e.pageX != undefined && e.pageY != undefined) {
           x = e.pageX;
           y = e.pageY;
      }
      else {
           x = e.clientX + document.body.scrollLeft +
                 document.documentElement.scrollLeft;
           y = e.clientY + document.body.scrollTop +
                 document.documentElement.scrollTop;
       }
       x -= canvas.offsetLeft;
       y -= canvas.offsetTop;
       return {"x": x, "y": y};
}

When we stop drawing our line (mouseup event), we will first cancel the event and then we will remove the mousemove event so it will stop drawing.

function stopDraw(e) {
      e.preventDefault();
      canvas.removeEventListener("mousemove", drawIt, false);
}

Now we have come to the key function: the function to draw the line on the canvas. First thing we will do is determining the current position of the cursor. Once we have that we can draw the line with the drawLine method. Next we are visualizing the line. The main things we need to do is call the stroke to paint the line on the canvas. And, if you do not close and start a new path the stroke will get applied again to all lines since beginPath was called. The last thing we need to do is updating the start point to the current position of the mouse.

function drawIt(e) {
      var point = getCursorPosition(e);
      drawLine(startpoint.x, startpoint.y, point.x, point.y);
      context.stroke();
      context.closePath();
      context.beginPath();
      startpoint = point;
}

In the drawLine function we set the color of the line and determine first the position from where we want to draw the line (moveTo), next we determine where to we want to draw the line (lineTo). Optionally you can set the width of the line and the cap style of the pen.

function drawLine(fromx, fromy, tox, toy) {
      context.strokeStyle = "red";
      context.moveTo(fromx, fromy);
      context.lineTo(tox,toy);
      context.lineWidth = 1;
      context.lineCap = "round";
}

Clearing the drawings on the canvas can easily been done by resetting the width of the canvas and so forcing it to redraw nothing.

function clearCanvas() {
       canvas.width = canvas.width;
}

Thursday, August 18, 2011

HTML 5 Presentation

It is already a year ago that i posted my last post. Today I’ll try to get started again, but not so much on topics about windows azure. I have found a new passion in HTML 5 web apps. From now most of my post will handle about building HTML 5.0 apps.

For starting I have made a presentation about HTML 5 for the acADDemICTs. These are our new realdolmen employees.

Hope to see you soon with more content about HTML 5.0 on this blog