• HTML5 and the localStorage Object

    Using the localStorage Object HTML5

    Next

    An application of the localStorage Object

    The HTML5 specification contains an object that provides a valuable alternative to cookies for gathering and storing visitors' personal information. The EU's recent directive regarding cookies makes this particularly relevant.

    The localStorage object, a child of the Window object., can hold up to 20 megabytes of data. Developers apply it to a wide variety of purposes: shopping baskets, miniature databases, and even web-based games. Data held within a local storage area is persistant (although not across browsers) and so can be recalled when a user returns to the site. User preferences and other information stored in this manner can therefore be accessed via JavaScript without any server-side requirement.

    The Object

    • clear()
      • local Storage.clear();
      • Returns nothing, clears all data from the localStorage Object.
    • constructor
      • var x = new Object();
      • Invokes the constructor with the new keyword.
    • getItem(sKey)
      • localStorage.getItem(strKey);
      • var returnVal = Storage.getItem(strKey);
      • Retrieves the item denoted by the supplied key.
      • Returns the item or null if it does not exist.
    • key(num)
      • localStorage.key(index);
      • var returnVal = localStorage.key(num);
      • Returns the name of the indicated key.
      • Can be any string including an empty one.
      • If out of range, it will throw an 'invalid argument' error.
    • length
      • var returnVal = localStorage.length;
      • Returns the quantity of items stored.
    • remainingSpace
      • var returnVal = localStorage.remainingSpace;
      • Returns the amount of space left in the localStorage Object.
    • removeItem(sKey)
      • var returnVal = localStorage.removeItem(strKey);
      • Returns S_OK or an error code depending on the result of applying the method.
    • setItem(key, val)
      • var returnVal = localStorage.setItem(strKey, strValue);
      • Returns S_OK or an error code depending on the result of applying the method.

    Example

    I had occasion to take advantage of this to make an online "wizard" to aid users of the online sailing/racing simulator/game Virtual Skipper5 (VSK5). It creates a guestlist that, if in place, can be used to allow "friends" into a race even if it's full.

    Some users had problems creating and/or maintaining this file because it uses XML. I wanted an editor that allows an individual's login name to be added to and removed from a list. When completed, this list can be converted to XML and then copied and pasted into their file. I also wanted it to be repeatable so it wouldn't need to be reproduced each time they wanted to edit it.

    It was too small an operation for a database and I wanted to keep it simple, so data persistance came to the fore. This allows data to be saved on a user's computer and dropped into a textbox so that a current list (copied from the current file) can be parsed and translated to a new list if it is their first use of the form.

    The files are shown below and can be seen in action at the VSK5 Guestlist Wizard.

    The Data

    <?xml version="1.0" encoding="utf-8" ?> <guestlist> <player> <login>John_Doe</login> </player> <player> <login>Joe_Soap</login> </player> <player> <login>Fred1</login> </player> <player> <login>Futtuck_shroud</login> </player> <player> <login>Baggy</login> </player> <player> <login>curried_giblets</login> </player> <player> <login>socrates-nightmare</login> </player> <player> <login>noodle</login> </player> <player> <login>jesse</login> </player> <player> <login>ElvisRidesAgain</login> </player> <player> <login>CynthiaFarquhar</login> </player> <player> <login>fontleroy</login> </player> <player> <login>boyblue</login> </player> <player> <login>kryptonite</login> </player> </guestlist>

    The CSS

    #main-content { background: background-color: white; } #frm fieldset legend { text-align:center; } #inside-content { border-radius: 18px; -webkit-border-radius: 18px; -webkit-box-shadow: 0px 0px 18px rgba(0, 0, 0, 0.6); } input, textarea, a { outline: none; } .pg-wrap { background: none; min-height: 600px; } form { background: url(../images/frm-bg.png) repeat-y; padding: 5% 0 5% 0; width: 80%; height: 80%; display: block; margin: 10% auto 10% auto; border-radius: 16px; -moz-border-radius: 16px; -webkit-border-radius: 16px; -moz-box-shadow: 0px 0px 16px rgba(0, 0, 0, 0.6); -webkit-box-shadow: 0px 0px 16px rgba(0, 0, 0, 0.6); -moz-box-shadow: 0px 0px 16px rgba(0, 0, 0, 0.6); -webkit-box-shadow: 0px 0px 16px rgba(0, 0, 0, 0.6); box-shadow: 0px 0px 16px rgba(0, 0, 0, 0.6); } fieldset { margin: auto; display: block; width: 80%; height: 90%; padding: 5% 5% 5% 5%; border-radius: 16px; -webkit-border-radius: 16px; -webkit-box-shadow: 0px 0px 16px rgba(0, 0, 0, 0.6); } .h1-form { text-align: center; padding-top: 200px; } #frm fieldset input[type=text],#frm fieldset textarea { padding-left:10px; } #frm fieldset textarea { width:100%; } input, legend, textarea, label, option, select { font-size: 1.3em; } input[type=button] { font-size: 1.3em; color:#444; } legend { padding:5px; background-image: url(../images/navbar-bg.png); border-radius: 6px; -moz-border-radius: 6px; -webkit-border-radius: 6px; -moz-box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.6); -webkit-box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.6); -moz-box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.6); -webkit-box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.6); box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.6); } div.left { float:left; width:38%; height:100%; } #mainblock { display:none; } div.right { float:right; width:58%; height:100%; } .menu { display:block; text-align:left; height:100px; width:90%; background:no-repeat 10px center; padding-left:80px; padding-right:30px; margin:0; white-space:normal; } #add { background-image:url(http://www.diades.net/library/images/add.png); } #delete { background-image:url(http://www.diades.net/library/images/remove.png); } #save { background-image:url(http://www.diades.net/library/images/store.png); } #create { background-image:url(http://www.diades.net/library/images/create.png); } #clear { background-image:url(http://www.diades.net/library/images/delete.png); } #parse { background-image:url(http://www.diades.net/library/images/parse.png); } input[type=text],label[for=namelist] select { border:none; background-color:transparent; } textarea { width: 80%; height: 130px; margin: 0 0 0 0x; padding: 13px 0 13px 0; font-family: Helvetica, sans-serif; overflow: auto; border:none; } #blah { height:auto; width:90%; padding:0 5% 0 5%; } label[for=loginname],label[for=namelist],#glist { border: 1px solid #ccc; display: block; border-radius: 16px; -moz-border-radius: 16px; -webkit-border-radius: 16px; -moz-box-shadow: 0px 0px 16px rgba(0, 0, 0, 0.6); -webkit-box-shadow: 0px 0px 16px rgba(0, 0, 0, 0.6); text-indent: 10px; font-weight: bold; margin: 5px auto 5px auto; background-color:#fff; } label[for=namelist] select { width:88%; border:none; } input[type=button]:hover,label[for=loginname]:hover,label[for=namelist]:hover,#glist:hover { -moz-box-shadow: 0px 0px 18px rgba(0, 0, 0, 0.6); -webkit-box-shadow: 0px 0px 18px rgba(0, 0, 0, 0.6); box-shadow: 0px 0px 18px rgba(0, 0, 0, 0.6); }

    The HTML

    <!DOCTYPE html> <html lang="en"> <head> <title>diades.net - Guestlist</title> <!-- Author: Keith Parker (diades) Web Sites: www.webxpertz.net www.diades.net vsk.diades.net web-development.diades.net www.teamjb.org Comments: --> <!-- Force IE into IE9 or 10 as against quirks mode --> <meta http-equiv="X-UA-Compatible" content="IE=9, IE=10" /> <meta name="description" content="" /> <meta name="keywords" content="" /> <meta name="author" content="Keith Parker (diades)" /> <meta http-equiv="Content-Type" content="text/html" charset=UTF-8" /> <link rel="stylesheet" type="text/css" href="/css/lists.css" /> <script type="text/javascript" src="/library/js/lists.js"></script> <script type="text/javascript"> onload = function () { if (window.localStorage['guestlist']) getdata(document.getElementById('namelist'), 'guest') } </script> </head> <body id="black"> <section> <div class="clsBody"> <form id="frm"> <fieldset> <legend>VSK5 (Virtual Skipper 5)</br>Guestlist Wizard</legend> <div class="left"> <input class="menu" type="button" value="Add Name"id="add" onclick="addName(loginname,namelist)" title="Type a Login name into the first text box and click here to add it to your list." /> <input class="menu" type="button" value="Delete Name"id="delete" onclick="deleteName(namelist,1)" title="Select the name that you want to remove from the Name list select box and click here." /> <input class="menu" type="button" value="Save Guestlist"id="save" onclick="savedata(namelist,1,true)" title="Click here to save the list to the local storage database on your computer." /> <input class="menu" type="button" value="Create Guestlist"id="create" onclick="MakeList(this.form,1)" title="Click here to create the Guestlist XML." /> <input class="menu" type="button" value="Clear Database"id="clear" onclick="clearstore(1)" title="Click here to clear the Guestlist from your local storage database." /> <input class="menu" type="button" value="Parse List"id="parse" onclick="parseList(glist,namelist)" title="Click here to Parse your current Guestlist" /> </div> <div class="right"> <div class="left"> <label for="loginname">Login Name<input autofocusid="loginname" name="loginname" type="text" class="required" required /></label> <br /><br /> <label for="namelist">Name list<select id="namelist" name="namelist" size="10"></select></label> </div> <div class="right"> <ul id="blah"> <li>Type in a Login Name and press "Add Name".</li> <li>Repeat this for each name that you wish to add.</li> <li>When you have completed the list, you have the option of the following:</li> <li>"Save Guestlist" - this will not create a guestlist but saves the list of names to your computer so that it will reload on your return to this editor. This allows you to edit the list at a later date.</li> <li>Click on "Create Guestlist" - This creates the XML that will be, once cut and pasted to a text file, your guestlist. This will not save the list for later editing!</li> <li>Click on "Clear Database" - this will do just that, any stored data will be lost!.</li> <li><em>New!</em> Paste your current Guestlist into the large textbox called "Guestlist", then click on "Parse List". The list will be parsed and entered into the select list for editing. You can then edit and or save the list.</li> </ul> </div> <br /><br /><br /> <label for="glist"><textarea id="glist" cols="60" rows="20"></textarea>Guestlist</label> </div> </fieldset> </form> </div> </section> </div> </div> <div id="footer"> <p id="copyright">Copyright ©2012 diades - <a href="/" rel="" title="DiaDes Dot Net">DiaDes Dot Net</a></p> </div> </div> </body> </html>

    The JavaScript

    /* Removes the selected name from the list */ function deleteName(objList, flag) { //check that there is data if (objList.options.length > 0) { //remove the selected name objList.remove(objList.selectedIndex); } else { //advise that there was nothing to remove alert('Nothing to delete'); } } /* Adds a name to the list */ function addName(objName, objList) { //check that there is data if (objName.value.length > 0) { //get the options object var opts = objList.options; //add the new data opts[opts.length] = new Option(objName.value, objName.value); //reset the input field objName.value = ""; //send the cursor to the field objName.focus(); //select anything that might be there objName.select(); else //advise that there is nothing to do alert("Nothing to add"); } } /* Creates the XML for the guestlist from the list of login names */ function MakeList(objFrm, intWhich) { //get the options object var list = objFrm.namelist.options; //check to see if there is anything in the list if (list.length > 0) { //check to see which file type is being manipulated and set the value accordingly for output var type = intWhich ? "Guestlist" : "Blacklist"; var xmltype = intWhich ? "guestlist" : "blacklist"; //populate the vars for the XML with data xmltype += '>'; var str = "\n\n<"; str += xmltype; // loop through the list and create the XML nodes for (var i = 0; i < list.length; i++) str += "\n\t\n\t\t" + list[i].value + "\n\t"; //set the XML closing root node objFrm.glist.value = intWhich ? str + "\n" : str + "\n"; else //advise that there is no data to manipulate. alert('No list to create'); } } /* Cleans the localStorage object before saving the current list to the localStorage object */ function savedata(ctrl, flag, bLast) { //check that there is data to operate with if (ctrl.options.length > 0) { //clean the localStorage object of the correct dataset window.localStorage.removeItem(flag == 0 ? 'black' : 'guest'); //create a data object var data = []; //loop through the optionlist and populate the data object for (var i = 0; i < ctrl.options.length; i++) data[i] = ctrl.options[i].value; //save the data object to the correct dataset window.localStorage[flag ? 'guest' : 'black'] = data; //advise of success alert('Data saved'); else //advise nothing to save if(bLast) alert("No data to save"); } } /* Gets the data from the localStorage Object and loads the list box with the data */ function getdata(ctrl, skey) { //Create a variable for the dataset var store = ""; //Get the dataset store = window.localStorage[skey]; //send the data to an array var data = store.split(","); Loop throught the array and add it to the option list for (var i = 0; i < data.length; i++) { var opt = document.createElement("option"); ctrl.add(opt); opt.value = data[i]; var txt = document.createTextNode(data[i]); opt.appendChild(txt); } } /* Clears all data from the localStorage object */ function clearstore(flag) { //Check to see if the required dataset exists if (window.localStorage[(flag == 0) ? 'black' : 'guest'] != undefined) { //clear the dataset window.localStorage.removeItem((flag == 0) ? 'black' : 'guest'); //advise of success alert('Data cleared'); else //advise nothing to clear alert('No data to remove'); } } /* takes the data (a results file) pasted into the textarea and parses it to place the data into the list for editing */ function parseList(oLst, oDrop) { //ensure that there is data to operate with if (oLst.value == '') { //no data, advise accordingly alert('No data to parse'); //quit the operation return//data exists so set some regular expressions to parse with var re1 = /\<\?xml version=\"1.0\" encoding=\"utf\-8\" \?\>/gi; var re2 = /\<\/login\>/gi; var re3 = /\/gi; var re4 = /\/gi; var re5 = /<\/player\>/gi; var re6 = /\/gi; var re7 = /\<\/guestlist\>/gi; var re8 = /[\n\t ]/gi; var re9 = /,$/gi; //start removing unwanted sections lst = oLst.value.replace(re1, ''); //this regex also inserts a comma for later use lst = lst.replace(re2, ','); lst = lst.replace(re3, ''); lst = lst.replace(re4, ''); lst = lst.replace(re5, ''); lst = lst.replace(re6, ''); lst = lst.replace(re7, ''); lst = lst.replace(re8, ''); lst = lst.replace(re9, ''); //use the comma inserted earlier to create an array from the remaining data var list = lst.split(','); //loop through the array for (var i = 0; i < list.length; i++) { //populate the listbox with the parsed data var el = document.createElement('option'); oDrop.add(el); el.value = list[i]; var txt = document.createTextNode(list[i]); el.appendChild(txt); } //clear the inputed file data oLst.value = ''; }

    Edited by Eric Sherman (MMI)


    Next
  • Recent Articles