Building jqLSAdmin – Part 1

This post is all about explaining some of the thought processes that went into the bookmarklet for jqLSAdmin, the jQuery Local Storage Admin. It’s my fervent hope that after you read this, you’ll doubt my sanity just slightly less. I can’t possibly hope to eradicate that doubt, but anything which reduces it can only be a good thing. Right?

So, this whole project got started (as I think I’ve noted before) by seeing a tweet from Steve Souders(@souders) (of Even Faster Web Sites fame (seriously, if you haven’t read it, go buy it (omg inception!))) asking if there was a bookmarklet out there for administering localStorage. I’d been wanting to write a bookmarklet for some time but just hadn’t gotten around to it. I had also been meaning to research localStorage for a while, ever since I started reading up on AmplifyJS. Realizing that if Mr. Souders hadn’t found a bookmarklet out there for this, there was a pretty good chance that there really wasn’t one. So, feeling motivated, I decided to plug this particular hole in the intarwebz with some of my code.

There were a number of online resources which I wandered through for the purposes of researching localStorage, and the ones that were ultimately the most helpful were herehere, and here.

I knew I needed to make some decisions from the very beginning. The first and the most obvious was that I was going to have to be doing a lot of DOM manipulation if I wanted to make it both viewable and editable. I also knew that I wanted to do a lot of ‘edit-in-place’. A next generation of this will probably take advantage of the ‘contenteditable’ property in HTML5, but I started off old-fashioned for this iteration. So, I decided that I’d do inline editing, replacing the content with input boxes when I needed to edit.

Additionally, I knew that since it was going to be a bookmarklet, that meant everything had to be inline. So, graphics weren’t going to be something I could include unless I did a base-64 thing, and I didn’t want to get into that. And why should I when there are lots of other ways to get what you want from text and HTML entities? So I made a couple of UI/UX decisions. To start with, I would need symbols for Edit, Save, and Delete. Delete was easy, as I can use a universally-recognized bid red X. To make it just a bit more ‘bold’ and spectacular, I decided to use the HTML entity for multiplication, ×.

Now, edit is another way of saying ‘change’ right? And another way of describing a change (particularly if you speak too much business language or do too much mathematics) is delta. And delta is a Greek letter. And there are HTML entities for all of the Greek letters. So, why not use Δ for that? Plus, since it kind of resembles an arrow, it will probably make sense that someone will click on it. Now the big challenge is, what to use for ‘Save’? Well, what’s the opposite of delta? Not finding any quick answers, I just decided to go visually, and use the visual inversion of the letter delta, the anadelta, or nabla, ∇.

With my iconography handled, I figured I would sketch out roughly what it would look like. As I’m presenting associated data (it’s all key/value pairs in localStorage), let’s use a

for grouping it all together. And since we’re in an HTML5 world, let’s round the corners a bit. IE won’t like it, but IE doesn’t like anything and the feeling is mutual. An 8px border radius on the fieldset gives a nice rounded look.

I then realized that I was going to need to put this inside of something on the page so that it could even be seen. So, a CSS-only lightbox was the only option that I wanted to face. I’ve abandoned all other lightboxes besides CSS-only ones anyway, so it’s a technique with which I am very familiar. Basic premise of a CSS-only lightbox is that you have two div’s, one contained in the other. The parent div is solid black, and set with an opacity so that you can see through it. The container div is fully visible, and your content goes in there.

At this point, I’ve got a lightbox, I’ve got a fieldset, I’ve got my controls defined. How am I going to do all this construction? I could do it with raw JS, and that might be an option, but I also know that jQuery is somewhat known and noted for being a powerful manipulator of the DOM. Plus, I happen to know it really well and am most comfortable working in it. Go with what you know, right?

However, jQuery may or may not be on every page that this could get used on, so I will have to figure out a way to add jQuery dynamically to the page. I want to have jQuery and I want a relatively recent copy of it. So, the following code is an easy check to see if jQuery is present and of sufficient lineage:

if (window.jQuery && 1 > jQuery.fn.jquery) {
    alert("jQuery in da hizzouse, fool!");
}

Ultimately, loading jQuery in is as easy as defining a new script element, setting the src to be the CDN of jQuery’s latest incarnation, and adding that script element to the head of the page. I took care of that with the following code:

script=document.createElement('script');
script.src='http://code.jquery.com/jquery-latest.min.js';
var head=document.getElementsByTagName('head')[0];
head.appendChild(script);

The other thing which I was very aware that I was going to need to do was check to see if localStorage was even supported in the browser which was being used. If localStorage isn’t supported, it sorta makes this whole exercise very irrelevant. From my research, two things became very evident. The first was that there were two conditions which had to be checked. One was whether localStorage was supported, and the second was whether it was possible to add a value to the localStorage due to browser-imposed quotas.

After a fair bit of research around the interwebz, the following pair of tests seemed to do the trick:

if (typeof(localStorage) == 'undefined' ) {
        alert('Your browser does not support HTML5 localStorage. Try upgrading.');
        return false;
} else {
    try {
        localStorage.setItem('vk', 'Vankoder');  //Try setting something
    } catch (e) {
         if (e == QUOTA_EXCEEDED_ERR) {
            alert('Quota exceeded!'); //data not saved due to quota exceed so throw an error
            return false;
        }
    }
    localStorage.removeItem('vkname'); //Get rid of dummy value
}

In short, this code tests to see if localStorage is recognized, and if it is, tries to add a test value to it. Now between this and including jQuery, we have the foundation where we can begin to actually build the rest of the tool. I’ll cover that in the next post.