This is the second post in our series on building Mobile Widgets. The first post was an introduction to Mobile Widgets.
In this post we will build a persistence library that works across multiple platforms and abstracts away the differences of those different platforms into a common set of methods.
Seeing that we are also about to release our Ripple Emulator, we will be using it for our testing to showcase the built-in persistence view and platform switching capabilities of the Ripple Emulator.
Lets get started…
The different platforms:
Persistence is handled differently by each of the platforms that we would like to support here. Sometime the differences are subtle, and sometimes no so much. Let’s first expose the different methods that each of the platforms use to save, retrieve, and remove preferences from their respective local storage.
JIL API 1.0.x to 1.1
The first release of the JIL framework exposed two methods for dealing with persisting preferences. Here are the methods with their signatures:
Saving ====> Widget.setPreferenceForKey(key, preference)
Retrieving ==> Widget.preferenceForKey(key)
Removing ==> Widget.setPreferenceForKey(key, null)
JIL API 1.2.x
In the 1.2 release of the JIL API the same methods mentioned above still exist, however, a change was made to the setPreferenceForKey method signature (notice that key and preference have been reversed). The methods dealing with persistence are below:
Saving ====> Widget.setPreferenceForKey(preference, key)
Retrieving ==> Widget.preferenceForKey(key)
Removing ==> Widget.setPreferenceForKey(null, key)
Note: to see the differences between the different beta releases, you can visit our public JIL-API repository here: http://wiki.github.com/tinyhippos/JIL-API/api-change-log
The persistence mechanism for Opera Widgets is very similar to the JIL API 1.2. The main difference is that Opera Widgets use a lower case “widget” object. The methods are as follows:
Saving ====> widget.setPreferenceForKey(preference, key)
Retrieving ==> widget.preferenceForKey(key)
Removing ==> widget.setPreferenceForKey(null, key)
HTML 5 Local Storage
This is pretty straight forward, just using the localStorage object. Here are the methods:
Saving ====> localStorage[key] = preference
Retrieving ==> localStorage[key]
Removing ==> localStorage.removeItem(key)
Should none of the storage options mentioned above be available, we’ll also add support for plain old cookies. To make our lives easier, we just used jQuery for saving and retrieving values using cookies.
The persistence wrapper
Rather then go line by line to show you how we’ve written this helper library, we’ll direct you to our open source github repository so that you can download it, play with it, and perhaps contribute to it should you think of any enhancements you’d like to add.
github repository: http://github.com/tinyhippos/MobileWidgets the persistence library can be found in the “lib” directory and is named Persistence.js
For convenience, our persistence library is dependent on jQuery and json2. All the info can be found in the source file :-)
The testing widget
In order to see the persistence wrapper in action, we need to build a little testing widget. I’m not going to show the process of building the entire widget to save time and space. you can however get the full source code for it here in the DemoWidget repository: http://github.com/tinyhippos/ripple_demo
We have created a very simple form that allows us to specify a key and value to be saved or deleted if it’s already in storage. Below is the very simple HTML for the form:
For simplicity, we’ll use jQuery to bind the events to each of the buttons “onmousedown” events. We are using “onmousedown” since some of the widget frameworks have a documented issue with handling the onclick event properly. Once we execute the save or remove functions, we’ll also display a message to the user. Here is the code for the event binding:
The shell of for our global Demo object looks something like this:
Now, you might notice that the notation seems a little odd, that’s because we’re using an auto invoked function passing in our global Demo object into it and using the $ to denote our global object. This notation is used so that we can get proper JS closure as well as to avoid polluting our global namespace with all of our functions.
Now, let’s see it in action
Now that we have both our persistence library and our demo widget, let’s load them into the Ripple Emulator and see it all in action. The Ripple Emulator isn’t available publicly just yet, but you can sign up here to be the first to get the details once we launch into beta (April 27th).
We will point Ripple at the directory that contains the demo widget, enable it and go to the form. It only takes 1 second to load and we will see this:
Once it’s loaded we can enter some values into the form we created and hit the “Save Preference” button in the widget. You will notice on the bottom left panel in Ripple that you can now see the key and it’s value as they would have been saved on the mobile device. Our persistence library adds an optional prefix to the key, this is a feature we found useful, but please feel free to remove it if it doesn’t suite your needs.
Now, we can click on the “Delete” button and we’ll see that the key and it’s value have been removed from storage.
And for our final trick, we’ll change our platform from JIL API 1.2.1 to the Opera widget platform. You can do this seamlessly in the Ripple Emulator by selecting the platform you wish to test on at the top right of the screen (we’ll cover this in more detail in a later post). You’ll note in the screen shots below that once we save a preference it will show up in preferences table on the bottom left as before. The screen shots also shows the Chrome Web Inspector console, and you’ll note the console message showing that we saved a preference using JIL (in the first screen shot) as our current framework and Opera (in the second screen shot)
Stay tuned for more articles in this series where we’ll explore other parts of the Ripple Emulator and provide more open source libraries and information on Mobile Widget development best practices.
Your feedback is important to us
Your feedback is very important to us. Please feel free to comment on the Ripple Emulator, our sample code, or anything else for that matter. We’ve open sourced the sample code and encourage the community to contribute so that all mobile widget and mobile web developers can benefit.