Miscellanea menu

Javascript library to save and load objects properly from local storage
Documentation
There is plenty of documentation in the code. This is just a pretty version.

Simple usage

<script type="text/javascript" src="objSaveLoad.js"></script> ... if(OSL.Test()==false){alert(....); etc.} // Test() initialises shims etc. ... var myObj = new FancyClass('foo','bar'); OSL.Save(OSL.LOCAL,'BuzKey',myObj); ... var myReconstructedObj = OSL.Load(OSL.LOCAL,'BuzKey');
Load() returns null if key is not found. For example
var foo = OSL.LoadLocal("foo"); // load foo array if(foo === null){foo = [];} // or initialise it empty

Complete example

// A sample class to play with. Note that the function TestFun() is embedded TestObj = function (Nonce){ // If this was inside a namespace then the syntax would be // TestObj : function TestObj(Nonce){ this.foo = Nonce; // anyone can store/retrieve foo this.TestFun = function(NonceAgain){ // this is the killer part that would get lost return(this.foo==NonceAgain); // using JSON stringify/store and reverse } } // Initialise OSL library and test it (RECOMMENDED EVERY TIME) if(OSL.Test()===false){ alert('OSL not supported on this browser'); }else{ var testOb1 = new TestObject(123); OSL.SaveSession('testing',testOb1); var testOb2 = OSL.LoadSession('testing'); if(testOb2.TestFun(123)===true){alert('Hurrah!');} OSL.Delete('S','testing'); }

When constructor is not in global namespace

Take for example the following object
var SomeNamespace = { SomeClass : function SomeClass('foo'){ // note syntax! *IMPORTANT* // construct... // NOT ...function(...) but function name(...) } }

Method 1:

Add a .myNamespace property to the object. You can do this at construction time or before calling Save(). In this case .myNamespace = 'SomeNamespace';

Method 2:

At Load() time supply a third parameter. eg var reconstructedObj = OSL.LoadLocal('BarKey','SomeNamespace');

Remote storage

SaveRemote is asynchronous. LoadRemote is synchronous. This means you must not do SaveRemote('foo') followed immediately by LoadRemote('foo') because you will end up asking for something that hasn't been saved yet.
Before you can do something like var foo = OSL.LoadRemote('foo'); you have to initialise the AJAX part of OSL. This will test to see if the server is live and accepting requests. Do this along these lines:
if(!OSL.SERVER.Initialise('http://mydomain.com/myserver.php', {pword:"easy",uname:"fred"})){ alert("Server is down or doesn't like your password"); }

Tips and tricks

  • OSL.LOCAL is 'L', OSL.SESSION is 'S' and OSL.REMOTE is 'R' Use literals if you prefer.
  • Convenience functions SaveLocal(Key,Obj) and LoadLocal(Key) and SaveSession(Key,Obj) and LoadSession(Key) are provided. (Extra arguments as per Save() and Load() ).
  • OSL.Test() tests if local storage, browser js supports it and does a test save/load to prove the whole thing.
  • Older browsers have no or patchy support for ECMA5 level of javascript This might be fixed with 'ddr-ecma5' javascript code available on-line. (or vulpeculox.net/misc/jsjq/objectSaveLoad in an emergency.)
  • If you want to deconstruct/reconstruct objects to/from strings then the Deconstruct() and Reconstruct() methods are easy to use.

Side-effects

Save() and Deconstruct() add .myClassName and possibly .myNamespace to the object being Saved. In most cases this can be ignored but Clean(Obj) is provided to wipe out all .myClassName properties and Clean(Obj,true) will also delete .myNamespace properties. If testing the save/load routines you might do something like this:
OSL.Save(myKey,myObject); var myLoadedObject = OSL.Load(myKey); OSL.Clean(myObject); // needed to return to virgin state if(Compare(myObject,myLoadedObject)){console.log('SAME');}
API reference
Call Description Notes
Set, get etc.
OSL.SaveLocal(Key,Obj)
OSL.SaveSession(Key,Obj)
OSL.SaveRemote(Key,Obj)
OSL.Store the object under the given key name
  • OSL.SaveRemote is asynchronous! See GetAfterSet() in the source code.
OSL.LoadLocal(Key,[Namespace])
OSL.LoadSession(Key,[Namespace])
OSL.LoadRemote(Key,[Namespace])
Tries to get the whole object from storage. If Key not found then null is returned.
NamespaceSee above. Optionally this tells the recreator where to find the constructor.
  • LoadRemote is synchronous, ie. It blocks so don't do lots of little loads or you will wait forever.
  • You should test for a null response in case you have to create an empty object to suit your needs. Something like this could go horribly wrong: var myObj = OSL.LoadLocal('badkey'); myObj.MyFunction();
OSL.DeleteLocal(Key)
OSL.DeleteSession(Key)
OSL.DeleteRemote(Key)
Removes object indexed by Key from store.
  • DeleteRemote is asynchronous!
  • No exception raised if key isn't present
OSL.ClearLocal()
OSL.ClearSession()
OSL.ClearRemote()
Completely erase the contents of the store.
Initialising
OSL.Test() Full initialisation and testing of localStorage and sessionStorage.
  • May not be needed on modern browsers but highly recommended
  • Returns true or false
  • Diagnostic messages are reported to the javascript console
OSL.SERVER.Initialise(Url,[ExtraParameters]) Establish that the remote server is alive and accepting credentials.
  • Url is full URL of the server
  • ExtraParameters is an object of items to be posted with each request. Typically they will be credentials but could be anything fixed.
  • Only needed if remote storage is required
  • Waits for response so if the network is slow this will mean a pause.
  • Example of ExtraParameters: {pword:"easy",uname:"fred"}
  • If you need different URLs for set, get and delete then see source for SetURL()
Object manipulation
OSL.Deconstruct(Obj) Creates a string that can be used with reconstruct
OSL.Reconstruct(Obj,[Namespace]) Recreates a complete object from a string created by Deconstruct
OSL.Clone(Obj,[Namespace]) Deep copy of the object
OSL.Extend(SrcClass,ExtClass) Class inheritance. Copy prototype properties and methods as a form of inheritance from SrcClass to ExtClass.
  • These work on classes rather than objects. eg.
    function Parent(){...construction code...}; Parent.prototype.MethodToInherit = function(){...}; function Child(){...construction code...}; OSL.Extend(Parent,Child); var c = new Child(); // create instance c.MethodToInherit(); // inherits method from parent
  • Note this is a once-off copy and subsequent changes to the parent will have no effect. If we continued the example we get an error
    Parent.prototype.LaterMethod = function(){...}; c.LaterMethod(); // *unknown*
The above should be enough for most uses. See the documented source for more complexity.

Remote storage interface

<?php session_start(); $key = $_POST['key']; $token = $_POST['token']; if($token != 'secret'){ header("HTTP/1.0 401 Unauthorised"); }else{ switch($_POST['mode']){ case 'set' : $_SESSION[$key] = $_POST['data']; print('SET:' . $_SESSION[$key]);break; case 'get' : print($_SESSION[$key]);break; case 'delete' : unset($_SESSION[$key]);break; case 'clear' : $_SESSION = array();break; default : header("HTTP/1.0 405 Method Not Allowed"); } } ?>
Here is a demonstration PHP server that implements it and expects an extra parameter of token' to have the value 'secret'. (Of course you'd implement more permanent storage.)
The interface is detailed in the source. In short it connects to some server by POST with ['mode'] one of set, get, delete or clear. ['key'] is key. ['data'] is the stringified (and URI-encoded but you probably don't need to worry about that) object

Research and development
For anyone interested in the gory Javascript details of how the libray came to be developed open a console, browse the code and click the buttons.
Object reconstruction after storage as a string Wrapping one-stop local store-fetch
Test 1 Need to toSource/eval?
Test 2 Better experiment using stringify/parse and prototyping
Test 3 What's the class of an object?
Test 4 Generic record-to-object
Test 5 Can we make a generic constructor factory?
Test 6 Accessing globals constructors?
Test 7 Enriching Object object
Test 8 Constructing without using the constructor
Test 9 Fully working version
Test 10 Something more robust
Test 11 Dealing with the namespace problem
Test A Basic proof of concept
Test B Exercise the finished thing.
(Uses library)
Test C More testing
(Uses library)(See below)
Comprehensive testing Structured testing of the library