Tuesday, May 22, 2012

HTML5 Dev Conf

I was speaking at the HTML5 Dev Conf on May 21, 2012 on Client Storage.

The talk covered the state of client storage, touching on cookies and local/session storage. It looked at the WebSQL specification, the reasons it was deprecated and how IndexedDB is the next big thing for a database in the browsers.
It also spoke about the limitations on IndexedDB and the list of libraries that could help using IndexedDB now. Some libraries covered include gazeljs, db.js, queryIndexedDB and backbone's IndexedDB Adapter. I also spoke about the JQuery IndexedDB library that I wrote, in addition to Linq2IndexedDB that Kristof and I are working on. I also introduced the IndexedDB shim on WebSql that would let people use IndexedDB API on Safari, Opera - enabling it on iPad and the iPhone.



Friday, May 18, 2012

Introducing - IndexedDB Shim over WebSql


IndexedDB is a client side database technology supported by Firefox, Internet Explorer and Chrome. It is a replacement to the now deprecated WebSql standard. Unfortunately, IndexedDB is not yet supported in Opera or Safari, make adoption of this standard slower.
The specification is also evolving and its implementation has differences even in the browsers that implement it. In the previous post, I wrote about how Chrome implements setVersion, while Firefox has been supporting the onupgradeneeded method as per the newer version of the specification.
This post is about a project that I am currently working on - bringing the IndexedDB technology to browsers that only have WebSql as the database. WebSql iteself has shims implemented and this should work well over those shims too.
So far, the simpler operations like object stores, data get and put, and cursors have been implemented. The shim is based on the implementation of IndexedDB in Firefox. Since WebSql provides a transactional SQLite like platform, translating IndexedDB concepts to the WebSql world was easy.


IDBDatabase
A database in IndexedDB corresponds directly to a database in WebSql. An additional, top level database called __sysdb__ is added to keep track of the database versions etc. WebSql database versions were not used in this implementation.Note that there is no implementation of db.close()

IDBTransaction
The transactions for IndexedDB directly correspond to transactions in WebSql. The lack of the abort method in WebSQL Transactions is overcome by throwing an exception to cancel the transaction.

IDBObjectStore
An IndexedDB Object Store is corresponds to a table in WebSql. Every database also has a __sys__ table that tracks meta data like autoIncrement, keyPath, etc about object stores. Adding data to the object store is added using a record in the table that looks like {keyId, value}. I hope to use the Firefox Key implementation to allow collations, but for now, all keys are simply JSON strings. Values are also not obtained using the Structured Cloning algorithm, but using JSON.stringify for now. KeyPaths are evaluated when required using eval. Since SQLite allows only integer keys for autoIncrement, an extra inc column is added to such tables to keep track of the auto increment values.

IDBCursors
Cursors are implemented using offset and limit queries in WebSql. Continue simply selects the next  element and a variable saves the offset value that should be applied to the query.

IDBIndexes
Indexes are still not implemented yet and I am working on getting Indexes working. I am looking at the way Firefox implements indexes.

Testing
You can run the tests on Chrome, Opera and Safari using the page at http://nparashuram.com/IndexedDB/polyfill/. In chome, you should be able to open the Resources tab to see the various tables created by the implementation and how they correspond to IndexedDB constructs.

You can watch out this space for updates. Please feel free to fork the project on github and help me confirm to the standards better. I am doing test driven development, and you can run the tests at http://nparashuram.com/IndexedDB/polyfill/

I hope that this plugin makes the IndexedDB API available in more places, enabling faster adoption of the specification. 

Saturday, May 12, 2012

IndexedDB setVersion vs onupgradeneeded

Try out the latest version of the plugin - http://nparashuram.com/jquery-indexeddb/test/

The latest specification of IndexedDB has removed the setVersion method and uses the newupgradeneeded method instead. In an older post, I had written about this change to the jquery-indexeddb plugin. However, Chrome still does not support the onupgradeneeded method and hence, the new version of jquery indexeddb plugin had to have a different name.
Over the past few weeks, I was able to work on some code that would wrap the indexeddb.open() method to allow the onupgradeneeded method. Instead of deeply coupling the setVersion-onupgradeneeded shim with the jquery plugin, I was able to get it to work as an independent shim that could also be used with standard IndexedDB applications.

Using the shim
To use the shim, simply include this javascript, and instead of calling window.indexedDB.open, call openReqShim. The events fired would be onsuccess, onerror, onblocked, and onupgradeneeded, as in the specification. The onupgradeneeded would have a versionTransaction that can be used to create/delete objectStores or Indexes.

Inside the shim

A database is opened when the openReqShim() call is made, very similar to indexedDB.open() call. The database name, and an optional database version are passed to this call, similar to the original call. The call returns the IDBRequest object.

For Firefox
In case of firefox, when the database is opened with the specified version greater than the database version, the onupgradeneeded method is called. This call is passed to the callback specified by the user. This is followed by a call to onsuccess, that is also passed to the user's onsuccess function.

For Chrome
In case of chrome, the onupgradeneeded function is not called. The database's onsuccess function is called. Here, the existence of the setVersion method is checked. If the method exists, and the specified version is greater than the database version, a the setVersion method is called. The onsuccess of the setVersion's request call invokes the user's onupgradeneeded method with the version transaction. Once the method completes, the versionTrasnaction is committed by closing the database. The database is opened again with the latest version and this is passed to the onsuccess defined by the user.

Future
The above shim tries to make the programming interface for the IndexedDB API confirm to the specification for Chrome. The latest version of the specification has also deprecated constants like IDBTransaction.READ_WRITE, replacing them with string constants like "readwrite". This change is currently available in Firefox Aurora and Chrome Canary, and I am working on it now, so you can watch out this space for any updates.


Friday, May 11, 2012

Running QUnit tests sequentially in order

Download QueuedUnit.js

Wikipedia defines Unit Tests as a method to test individual pieces of code independently. This basically implies that the order in which the QUnit tests run should not really matter. However, there could be cases where such tests may have to run in order and it is not very easy to do so on QUnit.

Use Case
There could be cases where you would like tests to run in order for better coverage, or simply because you have to write lesser setup/tear down code for each case. I have been working on a couple of API-centric projects and I found that I could be lazy and write lesser code if I could get the tests to run in order.   The projects, IndexedDB WebSql Shim and a jquery plugin for IndexedDB have tests where a database is first created, and sample data entered, and the subsequent tests use this setup to iterate over or search for data.
Alternatively, I could have written a common set up method that creates the mock database for every test. 

Experiment
Looking at this code snippet the QUnit tests are written such that they are started long after (100 milliseconds) the script tag is encountered. This causes the first test to run, but then, the order of the tests becomes 1,4,3,2. 
If the time interval is reduced to something like 10 milliseconds, the test execution order now changes to 1,2,3,4. 
I tried playing with QUnit.config.autostart, QUnit.config.autorun, but none of them seem to get the tests to execute in order. 

Solution
To get it working quickly, I had to brew my own solution, and the result was just a tiny framework. The gist simply loads the tests, one after another. The only changes from traditional QUnit async tests would be 
  • Replace asyncTest with queuedAsyncTest().
  • Replace module() with queuedModule(). 
  • At all points that the test is over, the nextTest() function should be called to add the next test to the queue. 
  • Once the tests are all ready to run, call nextText(), to start running test 1. 
A timeout method checks if the current test has finished in time, and if it has not, the current test simply fails and it moves on to the next text.
Here is the modified code snippet working with the QueuedUnit function calls.

Compare the test results - Before and After.

Issues
The requirement to call nextTest() to start the next test seems annoying. Also, if nextTest() is not specified, QUnit simply stops, unaware if the test passed of failed, but these are errors similar to a missing start() that can be avoided.

You can grab QueuedUnit.js on github, and leave a comment letting us know if it helped you become lazier:). After all, lazy testing is better than no testing!!



Friday, April 27, 2012

Buccolingual positioner (and CSS3 transforms)

While placing a dental implant, a dental surgeon must decide on the position and the angle of placement in the jaw bone among other things, and this needs to be communicated to the lab. The 3D Click guide is a model-based guided implant placement technology. As detailed on this page, the placement of the BLP is a surgical decision and one way to do it was to use it is layers in Photoshop.
If you are wondering, you are not on a dental blog, this is just a prelude to a project that I have been working on. It all started when Dr. Vidhya was introduced to the 3D click guide technique by Dr. Lambert Stumpel. She noticed that the technique could use some more optimization in the way the placement of the implant is communicated with the lab. Photoshop was a really big tool and expecting labs to have Photoshop just to view the angle and placement that the dental surgeon wants. If you are still interested in learning about what the actual process was, you could check out this presentation.
Seeing me working on HTML5, Vidhya realized that this is something that CSS3 Transforms and HTML5 could solve, and wanted to develop a web based approach that would make the communication a lot easier.
She came up with the design and requirements of the project and I decided to take a jab at writing code. The tools is live (with examples) on github, and on the site. Now to the CSS3 part of the tool.
The computer science part of the problem was the ability to resize, move and position an image on top of another image. Once it is done, the whole setup needs to be saved.
JQuery UI could be used to drag and resizer but it fails when CSS rotation is applied to it - the resize and drag handles do not interact well with the mouse. I started working on rolling out my own version of a library that could do this, but then stumbled across this work by Pavel Markovnin. The library basically tracks mouse drag and changes the image based on the resizee or rotation handles. Some changes to the library and I got it working for my requirement.
The harder part was get capture the final work, and save it as an image. Drawing the background image on a canvas was simple, the trick was in the way the foreground smaller image (called blp) had to be drawn. For getting the rotation, the transform css property returns the martix. This matrix can be directly applied to the canvas using the canvas context.transform property. However, the library applies rotation with the rotation origin being the center of the image; this is more natural when rotating the image. Canvas transforms however start at top left of the image, and hence, this difference has to be corrected. Also, the jQuery offset function seemed to return different values for a rotate image in Firefox 11 and Firefox 12, Chrome, etc. This additional quirk had to be take care of, before the image was obtained using canvas.toDataUrl.
With the image, the surgeon can send it to the lab for implementation. Thanks to Dr. Vidhya, the BLP process is one step easier - no more Photoshop installs; just a simple web based approach to make it better !