Monday, October 30, 2006

Firefox 2.0: Client-side session and persistent storage

Firefox 2.0 contains support for new client-side storage features. In the release notes it reads:

New support for storing structured data on the client side, to enable better handling of online transactions and improved performance when dealing with large amounts of data, such as documents and mailboxes. This is based on the WHATWG specification for client-side session and persistent storage.

WHATWG Web Applications 1.0 Working Draft describes this mechanism as being similar to HTTP session cookies. Incidentally, it is also worth noting that there are numerous other interesting sections of this specification that have not yet been implemented! When you look at the spec, it would be tempting to think that this new mechanism could just be a new way to manipulate cookies, however this is *not* what Firefox 2.0 is doing.

The code following this entry gives simple examples of how to set a variable and retrieve variables using these new cross webpage storage mechanisms; page1.html & page2.html use session storage, page1a.html & page2a.html use persistent storage.

After executing the persistent storage example I noticed that a file called webappsstore.sqlite was created in my Application Data directory for Mozilla Firefox. I think the extension for this file pretty much gives the game away, this is an SQLite file. There are a couple more SQLite files which can be found in this directory, these play a part in the new Firefox 2.0 phishing (urlclassifier2.sqlite) and search engine (search.sqlite) functionality.

Firing up an evaluation version of Visual SQLite and loading up webappsstore.sqlite you will see this file contains a table called mozwebappsstore with columns; domain, key, value, secure.

Having proven to myself that the Firefox 2.0 persistent storage is provided by SQLite, I would make an educated guess that the session storage is provided by a memory resident version of the database. Using this new storage mechanism is easier than using cookies but the key advantage over cookies is likely to be performance. Changing and reading cookies usually mean disk access. When using a memory resident database, there is no disk access. Accessing multiple values from persistent storage even though this will involve disk access is also likely to be faster because all the data is in one place. Visual SQLite did not indicate that webappsstore.sqlite contains any indexing and when dealing with large amounts of data adding indexing could further improve performance.

I have yet to see a full disclosure of the details for the storage mechanism. I do not know what the implications of embedding SQLite into Firefox 2.0 are likely to be. However, it would not be a major stretch of the imagination to expect JavaScript to gain a complete SQL access mechanism for client-side stored data (need I mention the AJAX/LAJAX again). SQLite supports SQL and as of now SQLite is already pre-embedded in my favourite browser.

page1.html (session storage)


<html>
<head>
<script type="text/javascript">
//<![CDATA[
sessionStorage.setItem("test", 123);
//]]>
</script>
<title></title>
</head>
<body>
<a href="page2.html">Page 2</a>
</body>
</html>

page2.html (session storage)


<html>
<head>
<script type="text/javascript">
//<![CDATA[
window.onload = function() {
document.getElementById("result").innerHTML = "<b>" + sessionStorage.getItem("test") + "<\/b>";
};
//]]>
</script>
<title></title>
</head>
<body>
<div id="result"></div><a href="page1.html">Page 1</a>
</body>
</html>

page1a.html (persistent storage)


<html>
<head>
<script type="text/javascript">
//<![CDATA[
var storage = globalStorage['cse-mjmcl.cse.bris.ac.uk'];
storage.setItem("test", 123);
//]]>
</script>
<title></title>
</head>
<body>
<a href="page2a.html">Page 2a</a>
</body>
</html>

page2a.html (persistent storage)


<html>
<head>
<script type="text/javascript">
//<![CDATA[
window.onload = function() {
var storage = globalStorage['cse-mjmcl.cse.bris.ac.uk'];
document.getElementById("result").innerHTML = "<b>" + storage.getItem("test") + "<\/b>";
};
//]]>
</script>
<title></title>
</head>
<body>
<div id="result"></div><a href="page1a.html">Page 1a</a>
</body>
</html>

Friday, October 06, 2006

Multiple DHTML trees on a page with dynamic ids

I have written before about XBEL and DHTML, Unobtrusive DHTML, and the power of unordered lists and D.D. de Kerf's Easy DHTML TreeView. My previous DHTML tree implementation (derived from D.D. de Kerf's DHTML tree) made use of JavaScript's this keyword to toggle folders. I have extended this method to include "Expand/Collapse" support. We have seen expand and collapse before in Matt Kruse's DHTML Tree. However, I have chosen a slightly different approach inspired by Random Content Order script.

The id of the tree is still used for expand/collapse (via getElementById()). The difference with this technique is that JavaScript now generates the tree id. This means we can have multiple DHTML trees on a page with expand/collapse buttons that do not interfere with each other without any special preliminary HTML preparation being necessary.

An HTML element id is supposed to be unique on a page. The key benefit of this method is that we no longer need to ensure a unique id is assigned to each unordered tree list in the HTML. My new technique is particularly useful where pages may contain several instances of a DHTML tree. These could be rendered as a result of aggregating content from multiple sources (like a portal does). Uniqueness of id is now a random affair taken care of by the JavaScript.

Additionally, the expand/collapse buttons themselves are attached using JavaScript therefore if it is not enabled they will not even appear. Note also that all the trees share the same JavaScript and CSS file.

My new DHTML tree implementation.

Look at the static source code and you will see that each tree starts out with identical HTML markup. A useful tip is to use JSLint to help debug JavaScript. My DHTML tree was initially behaving a little strangely on IE and I have found that Microsoft's script debugger is not very good. Incidentally, a designer has helped me with graphics (Thanks Ben).