Client Storage

Recently i wanted to make a simple storage solution on client side, I check many codes on internet, and except PersistJS, it seems there is not so much things out there to have a near 100% client storage support.

Available storage

Here is a basic (updated) list of available storage solution, which can be found in most of cases

  • Browser side :

    • localStorage
    • globalStorage
    • sessionStorage
    • openDatabase
    • userData
    • cookies
  • Plugin side :

Note : unfortunately, if you don’t have javascript enabled on final client side, approximately all of them will not work except cookie…

Local storage

Local storage is one of the new HTML5 feature, wich is implemented in most of modern browser, usage is quite simple :

//If you need to test localStorage is available :
if(window.localStorage){
  //Setting a value (you can store any kind of data, not only string)
  window.localStorage.setItem("name", "value");
  //Reading a value (will return "value" here)
  var res = window.localStorage.getItem("name");
  //Removing item
  window.localStorage.removeItem("name");
}

That’s all for localStorage.

globalStorage

In the global storage, you do yourself the storage, it can be accessed by other site (as the name suggest). Here is a basic usage :

var hostname = window.location.hostname;
//If you need to test globalStorage is available :
if(window.globalStorage){
  //Setting a value (you can store any kind of data, not only string)
  window.globalStorage[hostname]["name"] = "value";
  //Reading a value (will return "value" here)
  var res = window.globalStorage[hostname]["name"];
  //Removing item
  delete window.globalStorage[hostname]["name"];
}

As you see, from the localStorage point of view, you can consider as a more « free » way to store data because everybody can access to it. But this can lead in the same way as a security issue. You should always avoid this one if localStorage is available.

sessionStorage

The sessionStorage is close to localStorage, except data does not persist if the browser close. This storage can be usefull for a cart system : you should cancel order if the client side restart browser. So it’s not the best one for persistence because of that behaviour. But it can still be enough in some cases :

//If you need to test sessionStorage is available :
if(window.sessionStorage){
  //Setting a value (you can store any kind of data, not only string)
  window.sessionStorage.setItem("name", "value");
  //Reading a value (will return "value" here)
  var res = window.sessionStorage.getItem("name");
  //Removing item
  window.sessionStorage.removeItem("name");
}

As you see, extremely close to localStorage one (almost the same).

openDatabase

openDatabase is a client side database, quite usefull so, it can do a lot more than localStorage. Unfortunately his behaviour is quite different from the other, this makes a generic getter/setter for all of thooses functions to perform in asynchronous way only (which is personnaly bad, for a simple getter/setter) :

//If you need to test openDatabase is available :
var databaseName = "dbtest";
var tableName = "myTable";
if(window.openDatabase){
  //First of all, we have to create database if it does not exist (the last parameter define the maximum allowed size in bytes)
  var db = window.openDatabase(databaseName, "1.0", "Database test description", 1024*1024*2);
  //Creating the table if it's not existing
  db.transaction(function(tx){
    tx.executeSql("CREATE TABLE IF NOT EXISTS "+tableName+"(key TEXT, value TEXT)", []);
  });

  //Now we can manipulate our new system :

  //Setting a value (you can store data according to table above, so here, you can store key TEXT and value TEXT)
  db.transaction(function(tx){
    tx.executeSql("INSERT INTO "+tableName+" (key, value) VALUES(?, ?)", ["name", "test"],
      //The result appear here, you should use a callback function here to get result
      function(tx, result){},
      //Any error appear here, you should also use a callback function here to get error
      function(tx, error){}
  });

  //Reading a value (will go to callback function)
  db.transaction(function(tx){
    tx.executeSql("SELECT * FROM "+tableName+" WHERE key=?", ["name"],
      //The result appear here, you should use a callback function here to get result (should send back "test" here)
      function(tx, result){},
      //Any error appear here, you should also use a callback function here to get error
      function(tx, error){}
  });

  //Removing item
  db.transaction(function(tx){
    tx.executeSql("DELETE FROM "+tableName+" WHERE key=?", ["name"],
      //The result appear here, you should use a callback function here to get result
      function(tx, result){},
      //Any error appear here, you should also use a callback function here to get error
      function(tx, error){}
  });
}

As you see it is a lot more complicated already, but on the otherside possibilities are also great. You can refer to sqlite SQL syntax which is the database usually choosen in background for such system.

userData

Get back to IE5+ (yes), Microsoft implements a browser side storage called userData, pretty unknow, this function is the best function to work with IE. Because it’s so old, the behaviour and the way to use it is a little bit different :

//We test it's a IE browser
var userDataId = "userDataId";
var dbName = "databaseTest";
if(document.all){
  //Create base system (quite strange but it works)
  document.write('<input type="text" id="'+userDataId+'" style="behavior:url(#default#userData)" />');

  //Getting the database
  var db = document.getElementById(userDataId);

  //Now we can play with

  //Setting an item
  db.setAttribute("name", "test");
  db.save(dbName);

  //getting an item
  var value = db.getAttribute("name");

  //Removing an item
  db.removeAttribute("name");
  db.save(dbName);
}

Pay attention to the save function, and the dbName. Thooses are needed to retrieve data on next access.

cookies

The cookie system can of course also be used to store temp data. Thooses cookies can be disabled, so they are not the perfect solution, also, they usually have a strong limit (few kb only), which put them as a « second chance » possibilities, regarding all other great -and new- available methods.

function setCookie(name, value, expires, path, domain, secure){
  document.cookie=name+"="+escape(value)+
  ((expires==undefined) ? "" : ("; expires="+expires.toGMTString())) +
  ((path==undefined) ? "" : ("; path="+path)) +
  ((domain==undefined) ? "" : ("; domain="+domain")) +
  ((secure==true) ? "; secure" : "");
}

function getCookie(name){
  if(document.cookie.length == 0){return null;}
  var regCookie = new RegExp("(; )", "g");
  var cookies = document.cookie.split(regCookies);
  for(var i=0; i<cookies.length; ++i){
    var regInfo = new RegExp("=", "g");
    var infos = cookies[i].split(regInfo);
    if(infos[0]==name){
      return unescape(infos[i]);
    }
  }
  return null;
}
//The best way to test cookies, are to try getter/setter.
var date = new Date();
var dateErase = new Date();
date.setTime(date.getTime() + 3600);
dateErase.setTime(dateErase.getTime() - 1);

//Erase (if exist) previous cookie
setCookie("t", "", dateErase);

//Setting a dummy cookie
setCookie("t", "y", date, "/");

if(getCookie("t") == "y"){
  //Setting a cookie
  setCookie("name", "test", date, "/");
  //Reading a cookie
  var res = getCookie("name");
  //Erasing a cookie : set a already passed time
  setCookie("name", "", eraseDate);
}

The cookie still one of the most used storage. The good (and also) the bad things is that cookie are sended to server side on each request, quite interesting to transfert data from javascript to server side, quite bad things for bandwidth usage compare to other methods.

Now we can go on plugin side

Google Gears

Google gears was a great plugin with lots of functionnalities, it has been stopped to focus on HTML5. This plugin is still available on some non-updated browser.
The google gears storage was quite similar to openDatabase :

var databaseName = "dbTest";
var tableName = "tableTest";
//To test the google gears is available, you need to use the JS file they are providing
//The test here is not enough powerfull to be sure to have google gears
if(window.google && window.google.gears){
  //First of all, we have to create database if it does not exist
  var db = window.google.gears.factory.create("beta.database");
  db.open(databaseName);
  //Creating the table if it's not existing
  db.execute("CREATE TABLE IF NOT EXISTS "+tableName+"(key TEXT, value TEXT)", []);

  //Now we can manipulate our new system :

  //Setting a value (you can store data according to table above, so here, you can store key TEXT and value TEXT)
  db.execute("INSERT INTO "+tableName+" VALUES(?, ?)", ["name", "test"]);

  //Reading a value (will go to callback function)
  var result = db.execute("SELECT key, value FROM "+tableName+" WHERE key = ? LIMIT 1", ["name"];
  var val = null;
  if(result.isValidRow()){
    val = result.fieldByName("value");
  }else{
    //An error occurs
  }

  //Removing item
  db.execute("DELETE FROM "+tableName+" WHERE key = ?", ["name"]);
}

Unfortunately I could not test in a pretty good way this code, I know it should works in most of case, but I didn’t have enough material to test it.

Adobe Flash

Adobe Flash is one of the most used plugin in web browser environment, and, of course, it can do storage. I create here a basic flash program under the excellent Flash Develop IDE.
You can found the source code of the program here. The compiled program (in release mode, using the lightest possible system), is only 2kb.

You can use it like this :
First you need to include this in your page, doing so, please use the default JS script given with all flash programs. I try to remove this script, but safari was not working anymore (it does not detect Flash), if I didn’t include that file and append it to DOM manually.

I consider you get the program and it is loaded by Javascript file provided with all projects :
//I consider flash object tag (<object...) got an id "flash"
var flashObject = document.getElementById("flash");

flashObject.setDatabase("dbTest");

//Now we can set a value
flashObject.setData("name", "test");

//Reading
var res = flashObject.getData("name");

//Deleting
flashObject.removeData("name");

That’s all for supporting a basic storage with Adobe Flash. Lets go to the equivalent in Silverlight

Microsoft Silverlight

Silverlight got quite the same code for accessing storage. I create this one with the also excellent Mono Develop under linux.
You can found the source code of the program here.

Again you should use the script provided by microsoft to install this program on JS side. The program is also tiny, not more than 5kb.

To use this one, do like this :

//Getting item (suppose a <object id="silverlight"...)
var silverlightObject = document.getElementById("silverlight");

//Setting a value
silverlightObject.Content.store.saveData("name", "test");

//Reading
var res = silverlightObject.Content.store.loadData("name");

//Deleting
silverlightObject.Content.store.removeData("name");

The .Content.store is the usual way to access function from a DOM element in silverlight. We can now finish by the latest one, JavaFX

JavaFX

JavaFX introduce a storage capacities recently, but according to my own test, it is working, but as many java, it is extremely slow loading, this can have problem to use it at the beginning of loading page : it may not be ready yet. I use Netbean to do this, be carefull, at that time (when I create this program), only Netbean 6.9 was able to handle JavaFX, Netbean 7 and above wasn’t.
The main class can be found here while the storage class can be found here
The compiled version provide a jar file (package of compiled classes) to include in you web page. Again you should use script provided by Netbean to install it in proper way using given JS files (see the HTML page, the script is linked inside). Also JNLP files may be required.

Here is a basic usage of this program :

//Getting item (suppose a <object id="javafx"...)
var javaFXObject = document.getElementById("javafx");

//Setting a database
javaFXObject.Packages.javafxstorage.localStorage.setDatabase("dbTest");

//Setting a value
javaFXObject.Packages.javafxstorage.localStorage.setData("name", "test");

//Reading
var res = javaFXObject.Packages.javafxstorage.localStorage.getData("name");

//Deleting
javaFXObject.Packages.javafxstorage.localStorage.removeData("name");

Here it is. As I said loading may be extremely slow, so be patient for this one.

Final words

With all of thooses storages, you may have a complete overview of storage capacities on client side. As you see, there is lots of possibilities. I should say that, using any of plugins may require extra bandwidth due to JS script used by all of them to prepare environment for your program. But this is the only way to support old browsers if they have Adobe/Silverlight/JavaFX (available from usual Java Runtime).

Long time ago, I create a qooxdoo class from that work, but I never get any reply from them to make a contrib extension for supporting a lots of thooses capacities. Finally I include it in my own project, but I never publish it, that’s why I wrote this article. Take your time to implement your own version, and improve this one !

Publicités

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s

%d blogueurs aiment cette page :